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

1.1       www         1: # The LearningOnline Network with CAPA
                      2: # Handler to set parameters for assessments
                      3: #
1.621   ! raeburn     4: # $Id: lonparmset.pm,v 1.620 2023/05/22 21:10:55 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.617     raeburn   332: use Text::Wrap();
1.416     jms       333: use LONCAPA qw(:DEFAULT :match);
                    334: 
                    335: 
1.560     damieng   336: ##################################################
                    337: # CONTENT AND PROBLEM SETTINGS HTML PAGE HEADER/FOOTER
                    338: ##################################################
                    339: 
                    340: # Page header
1.561     damieng   341: #
                    342: # @param {Apache2::RequestRec} $r - Apache request object
                    343: # @param {string} $mode - selected tab, 'parmset' for course and problem settings, or 'coursepref' for course settings
                    344: # @param {string} $crstype - course type ('Community' for community settings)
1.507     www       345: sub startSettingsScreen {
1.531     raeburn   346:     my ($r,$mode,$crstype)=@_;
1.507     www       347: 
1.531     raeburn   348:     my $tabtext = &mt('Course Settings');
                    349:     if ($crstype eq 'Community') {
                    350:         $tabtext = &mt('Community Settings');
                    351:     } 
1.507     www       352:     $r->print("\n".'<ul class="LC_TabContentBigger" id="main">');
                    353:     $r->print("\n".'<li'.($mode eq 'coursepref'?' class="active"':'').'><a href="/adm/courseprefs"><b>&nbsp;&nbsp;&nbsp;&nbsp;'.
1.531     raeburn   354:                                           $tabtext.
1.507     www       355:                                           '&nbsp;&nbsp;&nbsp;&nbsp;</b></a></li>');
                    356: 
1.523     raeburn   357:     $r->print("\n".'<li'.($mode eq 'parmset'?' class="active"':'').' id="tabbededitor"><a href="/adm/parmset"><b>'.
1.507     www       358:                                                                  &mt('Content and Problem Settings').'</b></a></li>');
                    359:     $r->print("\n".'</ul>'."\n");
1.523     raeburn   360:     $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       361: }
                    362: 
1.560     damieng   363: # Page footer
1.507     www       364: sub endSettingsScreen {
                    365:    my ($r)=@_;
                    366:    $r->print('</div></div></div>');
                    367: }
                    368: 
                    369: 
                    370: 
1.560     damieng   371: ##################################################
1.563     damieng   372: # (mostly) TABLE MODE
1.560     damieng   373: # (parmval is also used for the log of parameter changes)
                    374: ##################################################
                    375: 
1.566     damieng   376: # Calls parmval_by_symb, getting the symb from $id with &symbcache.
1.561     damieng   377: #
                    378: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566     damieng   379: # @param {string} $id - resource id or map pc
1.561     damieng   380: # @param {string} $def - the resource's default value for this parameter
                    381: # @param {string} $uname - user name
                    382: # @param {string} $udom - user domain
                    383: # @param {string} $csec - section name
                    384: # @param {string} $cgroup - group name
                    385: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
                    386: # @returns {Array}
1.2       www       387: sub parmval {
1.275     raeburn   388:     my ($what,$id,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
                    389:     return &parmval_by_symb($what,&symbcache($id),$def,$uname,$udom,$csec,
                    390:                                                            $cgroup,$courseopt);
1.201     www       391: }
                    392: 
1.561     damieng   393: # Returns an array containing
                    394: # - the most specific level that is defined for that parameter (integer)
                    395: # - an array with the level as index and the parameter value as value (when defined)
                    396: #   (level 1 is the most specific and will have precedence)
                    397: #
                    398: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566     damieng   399: # @param {string} $symb - resource symb or map src
1.561     damieng   400: # @param {string} $def - the resource's default value for this parameter
                    401: # @param {string} $uname - user name
                    402: # @param {string} $udom - user domain
                    403: # @param {string} $csec - section name
                    404: # @param {string} $cgroup - group name
                    405: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
                    406: # @returns {Array}
1.201     www       407: sub parmval_by_symb {
1.275     raeburn   408:     my ($what,$symb,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
1.200     www       409: 
1.352     albertel  410:     my $useropt;
                    411:     if ($uname ne '' && $udom ne '') {
1.561     damieng   412:         $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1.352     albertel  413:     }
1.200     www       414: 
1.8       www       415:     my $result='';
1.44      albertel  416:     my @outpar=();
1.2       www       417: # ----------------------------------------------------- Cascading lookup scheme
1.446     bisitz    418:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305     albertel  419:     $map = &Apache::lonnet::deversion($map);
1.561     damieng   420:     
                    421:     # NOTE: some of that code looks redondant with code in lonnavmaps::parmval_real,
                    422:     # any change should be reflected there.
                    423:     
1.201     www       424:     my $symbparm=$symb.'.'.$what;
1.556     raeburn   425:     my $recurseparm=$map.'___(rec).'.$what; 
1.201     www       426:     my $mapparm=$map.'___(all).'.$what;
1.10      www       427: 
1.269     raeburn   428:     my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$what;
                    429:     my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556     raeburn   430:     my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269     raeburn   431:     my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
                    432: 
1.190     albertel  433:     my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$what;
                    434:     my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556     raeburn   435:     my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190     albertel  436:     my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
                    437: 
                    438:     my $courselevel=$env{'request.course.id'}.'.'.$what;
                    439:     my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556     raeburn   440:     my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190     albertel  441:     my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.2       www       442: 
1.11      www       443: 
1.182     albertel  444: # --------------------------------------------------------- first, check course
1.11      www       445: 
1.561     damieng   446: # 18 - General Course
1.200     www       447:     if (defined($$courseopt{$courselevel})) {
1.556     raeburn   448:         $outpar[18]=$$courseopt{$courselevel};
                    449:         $result=18;
                    450:     }
                    451: 
1.561     damieng   452: # 17 - Map or Folder level in course (recursive) 
1.556     raeburn   453:     if (defined($$courseopt{$courseleveli})) {
                    454:         $outpar[17]=$$courseopt{$courseleveli};
                    455:         $result=17;
1.43      albertel  456:     }
1.11      www       457: 
1.561     damieng   458: # 16 - Map or Folder level in course (non-recursive)
1.200     www       459:     if (defined($$courseopt{$courselevelm})) {
1.556     raeburn   460:         $outpar[16]=$$courseopt{$courselevelm};
                    461:         $result=16;
1.43      albertel  462:     }
1.11      www       463: 
1.182     albertel  464: # ------------------------------------------------------- second, check default
                    465: 
1.561     damieng   466: # 15 - resource default
1.556     raeburn   467:     if (defined($def)) { $outpar[15]=$def; $result=15; }
1.182     albertel  468: 
                    469: # ------------------------------------------------------ third, check map parms
                    470: 
1.556     raeburn   471:     
1.561     damieng   472: # 14 - map default
1.376     albertel  473:     my $thisparm=&parmhash($symbparm);
1.556     raeburn   474:     if (defined($thisparm)) { $outpar[14]=$thisparm; $result=14; }
1.182     albertel  475: 
1.561     damieng   476: # 13 - resource level in course
1.200     www       477:     if (defined($$courseopt{$courselevelr})) {
1.556     raeburn   478:         $outpar[13]=$$courseopt{$courselevelr};
                    479:         $result=13;
1.43      albertel  480:     }
1.11      www       481: 
1.182     albertel  482: # ------------------------------------------------------ fourth, back to course
1.352     albertel  483:     if ($csec ne '') {
1.561     damieng   484: # 12 - General for section
1.200     www       485:         if (defined($$courseopt{$seclevel})) {
1.556     raeburn   486:             $outpar[12]=$$courseopt{$seclevel};
                    487:             $result=12;
                    488:         }
1.561     damieng   489: # 11 - Map or Folder level for section (recursive)
1.556     raeburn   490:         if (defined($$courseopt{$secleveli})) {
                    491:             $outpar[11]=$$courseopt{$secleveli};
                    492:             $result=11;
                    493:         }
1.561     damieng   494: # 10 - Map or Folder level for section (non-recursive)
1.200     www       495:         if (defined($$courseopt{$seclevelm})) {
1.556     raeburn   496:             $outpar[10]=$$courseopt{$seclevelm};
                    497:             $result=10;
                    498:         }
1.561     damieng   499: # 9 - resource level in section
1.200     www       500:         if (defined($$courseopt{$seclevelr})) {
1.556     raeburn   501:             $outpar[9]=$$courseopt{$seclevelr};
                    502:             $result=9;
                    503:         }
1.43      albertel  504:     }
1.275     raeburn   505: # ------------------------------------------------------ fifth, check course group
1.352     albertel  506:     if ($cgroup ne '') {
1.561     damieng   507: # 8 - General for group
1.269     raeburn   508:         if (defined($$courseopt{$grplevel})) {
1.556     raeburn   509:             $outpar[8]=$$courseopt{$grplevel};
                    510:             $result=8;
                    511:         }
1.561     damieng   512: # 7 - Map or Folder level for group (recursive)
1.556     raeburn   513:         if (defined($$courseopt{$grpleveli})) {
                    514:             $outpar[7]=$$courseopt{$grpleveli};
                    515:             $result=7;
1.269     raeburn   516:         }
1.561     damieng   517: # 6 - Map or Folder level for group (non-recursive)
1.269     raeburn   518:         if (defined($$courseopt{$grplevelm})) {
1.556     raeburn   519:             $outpar[6]=$$courseopt{$grplevelm};
                    520:             $result=6;
1.269     raeburn   521:         }
1.561     damieng   522: # 5 - resource level in group
1.269     raeburn   523:         if (defined($$courseopt{$grplevelr})) {
1.556     raeburn   524:             $outpar[5]=$$courseopt{$grplevelr};
                    525:             $result=5;
1.269     raeburn   526:         }
                    527:     }
1.11      www       528: 
1.556     raeburn   529: # ---------------------------------------------------------- sixth, check user
1.11      www       530: 
1.352     albertel  531:     if ($uname ne '') {
1.561     damieng   532: # 4 - General for specific student
                    533:         if (defined($$useropt{$courselevel})) {
                    534:             $outpar[4]=$$useropt{$courselevel};
                    535:             $result=4;
                    536:         }
1.556     raeburn   537: 
1.561     damieng   538: # 3 - Map or Folder level for specific student (recursive)
                    539:         if (defined($$useropt{$courseleveli})) {
                    540:             $outpar[3]=$$useropt{$courseleveli};
                    541:             $result=3;
                    542:         }
1.473     amueller  543: 
1.561     damieng   544: # 2 - Map or Folder level for specific student (non-recursive)
                    545:         if (defined($$useropt{$courselevelm})) {
                    546:             $outpar[2]=$$useropt{$courselevelm};
                    547:             $result=2;
                    548:         }
1.473     amueller  549: 
1.561     damieng   550: # 1 - resource level for specific student
                    551:         if (defined($$useropt{$courselevelr})) {
                    552:             $outpar[1]=$$useropt{$courselevelr};
                    553:             $result=1;
                    554:         }
1.43      albertel  555:     }
1.44      albertel  556:     return ($result,@outpar);
1.2       www       557: }
                    558: 
1.198     www       559: 
                    560: 
1.376     albertel  561: # --- Caches local to lonparmset
                    562: 
1.446     bisitz    563: 
1.561     damieng   564: # Reset lonparmset caches (called at the beginning and end of the handler).
1.376     albertel  565: sub reset_caches {
                    566:     &resetparmhash();
                    567:     &resetsymbcache();
                    568:     &resetrulescache();
1.203     www       569: }
                    570: 
1.561     damieng   571: # cache for map parameters, stored temporarily in $env{'request.course.fn'}_parms.db
                    572: # (these parameters come from param elements in .sequence files created with the advanced RAT)
1.376     albertel  573: {
1.561     damieng   574:     my $parmhashid; # course identifier, to initialize the cache only once for a course
                    575:     my %parmhash; # the parameter cache
                    576:     # reset map parameter hash
1.376     albertel  577:     sub resetparmhash {
1.560     damieng   578:         undef($parmhashid);
                    579:         undef(%parmhash);
1.376     albertel  580:     }
1.446     bisitz    581: 
1.561     damieng   582:     # dump the _parms.db database into %parmhash
1.376     albertel  583:     sub cacheparmhash {
1.560     damieng   584:         if ($parmhashid eq  $env{'request.course.fn'}) { return; }
                    585:         my %parmhashfile;
                    586:         if (tie(%parmhashfile,'GDBM_File',
                    587:             $env{'request.course.fn'}.'_parms.db',&GDBM_READER(),0640)) {
                    588:             %parmhash=%parmhashfile;
                    589:             untie(%parmhashfile);
                    590:             $parmhashid=$env{'request.course.fn'};
                    591:         }
1.201     www       592:     }
1.446     bisitz    593: 
1.561     damieng   594:     # returns a parameter value for an identifier symb.parts.parameter, using the map parameter cache
1.376     albertel  595:     sub parmhash {
1.560     damieng   596:         my ($id) = @_;
                    597:         &cacheparmhash();
                    598:         return $parmhash{$id};
1.376     albertel  599:     }
1.560     damieng   600: }
1.376     albertel  601: 
1.566     damieng   602: # cache resource id or map pc -> resource symb or map src, using lonnavmaps to find association
1.446     bisitz    603: {
1.561     damieng   604:     my $symbsid; # course identifier, to initialize the cache only once for a course
                    605:     my %symbs; # hash id->symb
                    606:     # reset the id->symb cache
1.376     albertel  607:     sub resetsymbcache {
1.560     damieng   608:         undef($symbsid);
                    609:         undef(%symbs);
1.376     albertel  610:     }
1.446     bisitz    611: 
1.566     damieng   612:     # returns the resource symb or map src corresponding to a resource id or map pc
                    613:     # (using lonnavmaps and a cache)
1.376     albertel  614:     sub symbcache {
1.560     damieng   615:         my $id=shift;
                    616:         if ($symbsid ne $env{'request.course.id'}) {
                    617:             undef(%symbs);
                    618:         }
                    619:         if (!$symbs{$id}) {
                    620:             my $navmap = Apache::lonnavmaps::navmap->new();
                    621:             if ($id=~/\./) {
                    622:                 my $resource=$navmap->getById($id);
                    623:                 $symbs{$id}=$resource->symb();
                    624:             } else {
                    625:                 my $resource=$navmap->getByMapPc($id);
                    626:                 $symbs{$id}=&Apache::lonnet::declutter($resource->src());
                    627:             }
                    628:             $symbsid=$env{'request.course.id'};
1.473     amueller  629:         }
1.560     damieng   630:         return $symbs{$id};
1.473     amueller  631:     }
1.560     damieng   632: }
1.201     www       633: 
1.561     damieng   634: # cache for parameter default actions (stored in parmdefactions.db)
1.446     bisitz    635: {
1.561     damieng   636:     my $rulesid; # course identifier, to initialize the cache only once for a course
                    637:     my %rules; # parameter default actions hash
1.376     albertel  638:     sub resetrulescache {
1.560     damieng   639:         undef($rulesid);
                    640:         undef(%rules);
1.376     albertel  641:     }
1.446     bisitz    642: 
1.561     damieng   643:     # returns the value for a given key in the parameter default action hash
1.376     albertel  644:     sub rulescache {
1.560     damieng   645:         my $id=shift;
                    646:         if ($rulesid ne $env{'request.course.id'}
                    647:             && !defined($rules{$id})) {
                    648:             my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                    649:             my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                    650:             %rules=&Apache::lonnet::dump('parmdefactions',$dom,$crs);
                    651:             $rulesid=$env{'request.course.id'};
                    652:         }
                    653:         return $rules{$id};
1.221     www       654:     }
                    655: }
                    656: 
1.416     jms       657: 
1.561     damieng   658: # Returns the values of the parameter type default action
                    659: # "default value when manually setting".
                    660: # If none is defined, ('','','','','') is returned.
                    661: #
                    662: # @param {string} $type - parameter type
                    663: # @returns {Array<string>} - (hours, min, sec, value)
1.229     www       664: sub preset_defaults {
                    665:     my $type=shift;
                    666:     if (&rulescache($type.'_action') eq 'default') {
1.560     damieng   667:         # yes, there is something
                    668:         return (&rulescache($type.'_hours'),
                    669:             &rulescache($type.'_min'),
                    670:             &rulescache($type.'_sec'),
                    671:             &rulescache($type.'_value'));
1.229     www       672:     } else {
1.560     damieng   673:         # nothing there or something else
                    674:         return ('','','','','');
1.229     www       675:     }
                    676: }
                    677: 
1.416     jms       678: 
1.561     damieng   679: # Checks that a date is after enrollment start date and before
                    680: # enrollment end date.
                    681: # Returns HTML with a warning if it is not, or the empty string otherwise.
                    682: # This is used by both overview and table modes.
                    683: #
                    684: # @param {integer} $checkdate - the date to check.
                    685: # @returns {string} - HTML possibly containing a localized warning message.
1.277     www       686: sub date_sanity_info {
                    687:    my $checkdate=shift;
                    688:    unless ($checkdate) { return ''; }
                    689:    my $result='';
                    690:    my $crsprefix='course.'.$env{'request.course.id'}.'.';
                    691:    if ($env{$crsprefix.'default_enrollment_end_date'}) {
                    692:       if ($checkdate>$env{$crsprefix.'default_enrollment_end_date'}) {
1.413     bisitz    693:          $result.='<div class="LC_warning">'
                    694:                  .&mt('After course enrollment end!')
                    695:                  .'</div>';
1.277     www       696:       }
                    697:    }
                    698:    if ($env{$crsprefix.'default_enrollment_start_date'}) {
                    699:       if ($checkdate<$env{$crsprefix.'default_enrollment_start_date'}) {
1.413     bisitz    700:          $result.='<div class="LC_warning">'
                    701:                  .&mt('Before course enrollment start!')
                    702:                  .'</div>';
1.277     www       703:       }
                    704:    }
1.413     bisitz    705: # Preparation for additional warnings about dates in the past/future.
                    706: # An improved, more context sensitive version is recommended,
                    707: # e.g. warn for due and answer dates which are defined before the corresponding open date, etc.
                    708: #   if ($checkdate<time) {
                    709: #      $result.='<div class="LC_info">'
                    710: #              .'('.&mt('in the past').')'
                    711: #              .'</div>';
                    712: #      }
                    713: #   if ($checkdate>time) {
                    714: #      $result.='<div class="LC_info">'
                    715: #              .'('.&mt('in the future').')'
                    716: #              .'</div>';
                    717: #      }
1.277     www       718:    return $result;
                    719: }
1.561     damieng   720: 
                    721: 
                    722: # Store a parameter value and type by ID, also triggering more parameter changes based on parameter default actions.
1.186     www       723: #
1.566     damieng   724: # @param {string} $sresid - resource id or map pc
1.565     damieng   725: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561     damieng   726: # @param {integer} $snum - level
                    727: # @param {string} $nval - new value
                    728: # @param {string} $ntype - new type
                    729: # @param {string} $uname - username
                    730: # @param {string} $udom - userdomain
                    731: # @param {string} $csec - section name
                    732: # @param {string} $cgroup - group name
1.186     www       733: sub storeparm {
1.269     raeburn   734:     my ($sresid,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.275     raeburn   735:     &storeparm_by_symb(&symbcache($sresid),$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,'',$cgroup);
1.197     www       736: }
                    737: 
1.561     damieng   738: my %recstack; # hash parameter name -> 1 when a parameter was used before in a recursive call to storeparm_by_symb
                    739: 
                    740: # Store a parameter value and type by symb, also triggering more parameter changes based on parameter default actions.
                    741: # Uses storeparm_by_symb_inner to actually store the parameter, ignoring any returned error.
                    742: #
1.566     damieng   743: # @param {string} $symb - resource symb or map src
1.565     damieng   744: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561     damieng   745: # @param {integer} $snum - level
                    746: # @param {string} $nval - new value
                    747: # @param {string} $ntype - new type
                    748: # @param {string} $uname - username
                    749: # @param {string} $udom - userdomain
                    750: # @param {string} $csec - section name
                    751: # @param {boolean} $recflag - should be true for recursive calls to storeparm_by_symb, false otherwise
                    752: # @param {string} $cgroup - group name
1.197     www       753: sub storeparm_by_symb {
1.275     raeburn   754:     my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$recflag,$cgroup)=@_;
1.226     www       755:     unless ($recflag) {
1.560     damieng   756:         # first time call
                    757:         %recstack=();
                    758:         $recflag=1;
1.226     www       759:     }
1.560     damieng   760:     # store parameter
1.226     www       761:     &storeparm_by_symb_inner
1.473     amueller  762:     ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup);
1.560     damieng   763:     # don't do anything if parameter was reset
1.266     www       764:     unless ($nval) { return; }
1.226     www       765:     my ($prefix,$parm)=($spnam=~/^(.*[\_\.])([^\_\.]+)$/);
1.560     damieng   766:     # remember that this was set
1.226     www       767:     $recstack{$parm}=1;
1.560     damieng   768:     # what does this trigger?
1.226     www       769:     foreach my $triggered (split(/\:/,&rulescache($parm.'_triggers'))) {
1.560     damieng   770:         # don't backfire
                    771:         unless ((!$triggered) || ($recstack{$triggered})) {
                    772:             my $action=&rulescache($triggered.'_action');
                    773:             my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
                    774:             # set triggered parameter on same level
                    775:             my $newspnam=$prefix.$triggered;
                    776:             my $newvalue='';
                    777:             my $active=1;
                    778:             if ($action=~/^when\_setting/) {
                    779:             # are there restrictions?
                    780:                 if (&rulescache($triggered.'_triggervalue')=~/\w/) {
                    781:                     $active=0;
1.565     damieng   782:                     foreach my $possiblevalue (split(/\s*\,\s*/,&rulescache($triggered.'_triggervalue'))) {
1.560     damieng   783:                         if (lc($possiblevalue) eq lc($nval)) { $active=1; }
                    784:                     }
                    785:                 }
                    786:                 $newvalue=&rulescache($triggered.'_value');
                    787:             } else {
                    788:                 my $totalsecs=((&rulescache($triggered.'_days')*24+&rulescache($triggered.'_hours'))*60+&rulescache($triggered.'_min'))*60+&rulescache($triggered.'_sec');
                    789:                 if ($action=~/^later\_than/) {
                    790:                     $newvalue=$nval+$totalsecs;
                    791:                 } else {
                    792:                     $newvalue=$nval-$totalsecs;
                    793:                 }
                    794:             }
                    795:             if ($active) {
                    796:                 &storeparm_by_symb($symb,$newspnam,$snum,$newvalue,&rulescache($triggered.'_type'),
                    797:                         $uname,$udom,$csec,$recflag,$cgroup);
                    798:             }
                    799:         }
1.226     www       800:     }
                    801:     return '';
                    802: }
                    803: 
1.561     damieng   804: # Adds all given arguments to the course parameter log.
                    805: # @returns {string} - the answer to the lonnet query.
1.293     www       806: sub log_parmset {
1.525     raeburn   807:     return &Apache::lonnet::write_log('course','parameterlog',@_);
1.284     www       808: }
                    809: 
1.561     damieng   810: # Store a parameter value and type by symb, without using the parameter default actions.
                    811: # Expire related sheets.
                    812: #
1.566     damieng   813: # @param {string} $symb - resource symb or map src
1.561     damieng   814: # @param {string} $spnam - part info and parameter name separated by a dot, e.g. '0.weight'
                    815: # @param {integer} $snum - level
                    816: # @param {string} $nval - new value
                    817: # @param {string} $ntype - new type
                    818: # @param {string} $uname - username
                    819: # @param {string} $udom - userdomain
                    820: # @param {string} $csec - section name
                    821: # @param {string} $cgroup - group name
                    822: # @returns {string} - HTML code with an error message if the parameter could not be stored.
1.226     www       823: sub storeparm_by_symb_inner {
1.197     www       824: # ---------------------------------------------------------- Get symb, map, etc
1.269     raeburn   825:     my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.197     www       826: # ---------------------------------------------------------- Construct prefixes
1.186     www       827:     $spnam=~s/\_([^\_]+)$/\.$1/;
1.446     bisitz    828:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305     albertel  829:     $map = &Apache::lonnet::deversion($map);
                    830: 
1.197     www       831:     my $symbparm=$symb.'.'.$spnam;
1.556     raeburn   832:     my $recurseparm=$map.'___(rec).'.$spnam;
1.197     www       833:     my $mapparm=$map.'___(all).'.$spnam;
                    834: 
1.269     raeburn   835:     my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$spnam;
                    836:     my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556     raeburn   837:     my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269     raeburn   838:     my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
                    839: 
1.190     albertel  840:     my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$spnam;
                    841:     my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556     raeburn   842:     my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190     albertel  843:     my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
1.446     bisitz    844: 
1.190     albertel  845:     my $courselevel=$env{'request.course.id'}.'.'.$spnam;
                    846:     my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556     raeburn   847:     my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190     albertel  848:     my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.446     bisitz    849: 
1.186     www       850:     my $storeunder='';
1.578     raeburn   851:     my $possreplace='';
1.556     raeburn   852:     if (($snum==18) || ($snum==4)) { $storeunder=$courselevel; }
1.578     raeburn   853:     if (($snum==17) || ($snum==3)) { 
                    854:         $storeunder=$courseleveli;
                    855:         $possreplace=$courselevelm; 
                    856:     } 
                    857:     if (($snum==16) || ($snum==2)) { 
                    858:         $storeunder=$courselevelm;
                    859:         $possreplace=$courseleveli;
                    860:     }
1.556     raeburn   861:     if (($snum==13) || ($snum==1)) { $storeunder=$courselevelr; }
                    862:     if ($snum==12) { $storeunder=$seclevel; }
1.578     raeburn   863:     if ($snum==11) { 
                    864:         $storeunder=$secleveli;
                    865:         $possreplace=$seclevelm; 
                    866:     }
                    867:     if ($snum==10) { 
                    868:         $storeunder=$seclevelm;
                    869:         $possreplace=$secleveli;
                    870:     }
1.556     raeburn   871:     if ($snum==9) { $storeunder=$seclevelr; }
                    872:     if ($snum==8) { $storeunder=$grplevel; }
1.578     raeburn   873:     if ($snum==7) { 
                    874:         $storeunder=$grpleveli;
                    875:         $possreplace=$grplevelm;
                    876:     }
                    877:     if ($snum==6) {
                    878:         $storeunder=$grplevelm;
                    879:         $possreplace=$grpleveli;
                    880:     }
1.556     raeburn   881:     if ($snum==5) { $storeunder=$grplevelr; }
1.269     raeburn   882: 
1.446     bisitz    883: 
1.186     www       884:     my $delete;
                    885:     if ($nval eq '') { $delete=1;}
                    886:     my %storecontent = ($storeunder         => $nval,
1.473     amueller  887:             $storeunder.'.type' => $ntype);
1.186     www       888:     my $reply='';
1.560     damieng   889:     
1.556     raeburn   890:     if ($snum>4) {
1.186     www       891: # ---------------------------------------------------------------- Store Course
                    892: #
1.560     damieng   893:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                    894:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                    895:         # Expire sheets
                    896:         &Apache::lonnet::expirespread('','','studentcalc');
                    897:         if (($snum==13) || ($snum==9) || ($snum==5)) {
                    898:             &Apache::lonnet::expirespread('','','assesscalc',$symb);
1.578     raeburn   899:         } elsif (($snum==17) || ($snum==16) || ($snum==11) || ($snum==10) || ($snum==7) || ($snum==6)) {
1.560     damieng   900:             &Apache::lonnet::expirespread('','','assesscalc',$map);
                    901:         } else {
                    902:             &Apache::lonnet::expirespread('','','assesscalc');
                    903:         }
                    904:         # Store parameter
                    905:         if ($delete) {
                    906:             $reply=&Apache::lonnet::del
                    907:             ('resourcedata',[keys(%storecontent)],$cdom,$cnum);
                    908:                 &log_parmset(\%storecontent,1);
                    909:         } else {
                    910:             $reply=&Apache::lonnet::cput
                    911:             ('resourcedata',\%storecontent,$cdom,$cnum);
                    912:             &log_parmset(\%storecontent);
1.578     raeburn   913:             if ($possreplace) {
                    914:                 my $resdata = &Apache::lonnet::get_courseresdata($cnum,$cdom);
                    915:                 if (ref($resdata) eq 'HASH') {
                    916:                     if (exists($resdata->{$possreplace})) {
                    917:                         if (&Apache::lonnet::del
                    918:                             ('resourcedata',[$possreplace,$possreplace.'.type'],$cdom,$cnum) eq 'ok') {
                    919:                             &log_parmset({$possreplace => '', $possreplace.'.type' => $ntype},1);   
                    920:                         }
                    921:                     }
                    922:                 }
                    923:             }
1.560     damieng   924:         }
                    925:         &Apache::lonnet::devalidatecourseresdata($cnum,$cdom);
1.186     www       926:     } else {
                    927: # ------------------------------------------------------------------ Store User
                    928: #
1.560     damieng   929:         # Expire sheets
                    930:         &Apache::lonnet::expirespread($uname,$udom,'studentcalc');
                    931:         if ($snum==1) {
                    932:             &Apache::lonnet::expirespread
                    933:             ($uname,$udom,'assesscalc',$symb);
1.578     raeburn   934:         } elsif (($snum==2) || ($snum==3)) {
1.560     damieng   935:             &Apache::lonnet::expirespread
                    936:             ($uname,$udom,'assesscalc',$map);
                    937:         } else {
                    938:             &Apache::lonnet::expirespread($uname,$udom,'assesscalc');
                    939:         }
                    940:         # Store parameter
                    941:         if ($delete) {
                    942:             $reply=&Apache::lonnet::del
                    943:             ('resourcedata',[keys(%storecontent)],$udom,$uname);
                    944:             &log_parmset(\%storecontent,1,$uname,$udom);
                    945:         } else {
                    946:             $reply=&Apache::lonnet::cput
                    947:             ('resourcedata',\%storecontent,$udom,$uname);
                    948:             &log_parmset(\%storecontent,0,$uname,$udom);
1.578     raeburn   949:             if ($possreplace) {
                    950:                 my $resdata = &Apache::lonnet::get_userresdata($uname,$udom);
                    951:                 if (ref($resdata) eq 'HASH') {
                    952:                     if (exists($resdata->{$possreplace})) {
                    953:                         if (&Apache::lonnet::del
                    954:                             ('resourcedata',[$possreplace,$possreplace.'.type'],$udom,$uname) eq 'ok') {
                    955:                             &log_parmset({$possreplace => '',$possreplace.'.type' => $ntype},1,
                    956:                                           $uname,$udom);
                    957:                         }
                    958:                     }
                    959:                 }
                    960:             }
1.560     damieng   961:         }
                    962:         &Apache::lonnet::devalidateuserresdata($uname,$udom);
1.186     www       963:     }
1.446     bisitz    964: 
1.186     www       965:     if ($reply=~/^error\:(.*)/) {
1.560     damieng   966:         return "<span class=\"LC_error\">Write Error: $1</span>";
1.186     www       967:     }
                    968:     return '';
                    969: }
                    970: 
1.9       www       971: 
1.561     damieng   972: # Returns HTML with the value of the given parameter,
                    973: # using a readable format for dates, and
                    974: # a warning if there is a problem with a date.
                    975: # Used by table mode.
                    976: # Returns HTML for the editmap.png image if no value is defined and $editable is true.
                    977: #
                    978: # @param {string} $value - the parameter value
                    979: # @param {string} $type - the parameter type
                    980: # @param {boolean} $editable - Set to true to get an icon when no value is defined.
1.9       www       981: sub valout {
1.600     raeburn   982:     my ($value,$type,$editable)=@_;
1.59      matthew   983:     my $result = '';
                    984:     # Values of zero are valid.
                    985:     if (! $value && $value ne '0') {
1.528     bisitz    986:         if ($editable) {
                    987:             $result =
                    988:                 '<img src="/res/adm/pages/editmap.png"'
                    989:                .' alt="'.&mt('Change').'"'
1.539     raeburn   990:                .' title="'.&mt('Change').'" style="border:0;" />';
1.528     bisitz    991:         } else {
                    992:             $result='&nbsp;';
                    993:         }
1.59      matthew   994:     } else {
1.66      www       995:         if ($type eq 'date_interval') {
1.559     raeburn   996:             my ($totalsecs,$donesuffix) = split(/_/,$value,2);
                    997:             my ($usesdone,$donebuttontext,$proctor,$secretkey);
                    998:             if ($donesuffix =~ /^done\:([^\:]+)\:(.*)$/) {
                    999:                 $donebuttontext = $1;
                   1000:                 (undef,$proctor,$secretkey) = split(/_/,$2);
                   1001:                 $usesdone = 'done';
                   1002:             } elsif ($donesuffix =~ /^done(|_.+)$/) {
                   1003:                 $donebuttontext = &mt('Done');
                   1004:                 ($usesdone,$proctor,$secretkey) = split(/_/,$donesuffix);
                   1005:             }
1.554     raeburn  1006:             my ($sec,$min,$hour,$mday,$mon,$year)=gmtime($totalsecs);
1.413     bisitz   1007:             my @timer;
1.66      www      1008:             $year=$year-70;
                   1009:             $mday--;
                   1010:             if ($year) {
1.413     bisitz   1011: #               $result.=&mt('[quant,_1,yr]',$year).' ';
                   1012:                 push(@timer,&mt('[quant,_1,yr]',$year));
1.66      www      1013:             }
                   1014:             if ($mon) {
1.413     bisitz   1015: #               $result.=&mt('[quant,_1,mth]',$mon).' ';
                   1016:                 push(@timer,&mt('[quant,_1,mth]',$mon));
1.66      www      1017:             }
                   1018:             if ($mday) {
1.413     bisitz   1019: #               $result.=&mt('[quant,_1,day]',$mday).' ';
                   1020:                 push(@timer,&mt('[quant,_1,day]',$mday));
1.66      www      1021:             }
                   1022:             if ($hour) {
1.413     bisitz   1023: #               $result.=&mt('[quant,_1,hr]',$hour).' ';
                   1024:                 push(@timer,&mt('[quant,_1,hr]',$hour));
1.66      www      1025:             }
                   1026:             if ($min) {
1.413     bisitz   1027: #               $result.=&mt('[quant,_1,min]',$min).' ';
                   1028:                 push(@timer,&mt('[quant,_1,min]',$min));
1.66      www      1029:             }
                   1030:             if ($sec) {
1.413     bisitz   1031: #               $result.=&mt('[quant,_1,sec]',$sec).' ';
                   1032:                 push(@timer,&mt('[quant,_1,sec]',$sec));
1.66      www      1033:             }
1.413     bisitz   1034: #           $result=~s/\s+$//;
                   1035:             if (!@timer) { # Special case: all entries 0 -> display "0 secs" intead of empty field to keep this field editable
                   1036:                 push(@timer,&mt('[quant,_1,sec]',0));
                   1037:             }
                   1038:             $result.=join(", ",@timer);
1.559     raeburn  1039:             if ($usesdone eq 'done') {
1.558     raeburn  1040:                 if ($secretkey) {
1.559     raeburn  1041:                     $result .= ' '.&mt('+ "[_1]" with proctor key: [_2]',$donebuttontext,$secretkey);  
1.558     raeburn  1042:                 } else {
1.559     raeburn  1043:                     $result .= ' + "'.$donebuttontext.'"';
                   1044:                 }
1.554     raeburn  1045:             }
1.213     www      1046:         } elsif (&isdateparm($type)) {
1.361     albertel 1047:             $result = &Apache::lonlocal::locallocaltime($value).
1.560     damieng  1048:                 &date_sanity_info($value);
1.59      matthew  1049:         } else {
                   1050:             $result = $value;
1.517     www      1051:             $result=~s/\,/\, /gs;
1.560     damieng  1052:             $result = &HTML::Entities::encode($result,'"<>&');
1.59      matthew  1053:         }
                   1054:     }
                   1055:     return $result;
1.9       www      1056: }
                   1057: 
1.59      matthew  1058: 
1.561     damieng  1059: # Returns HTML containing a link on a parameter value, for table mode.
                   1060: # The link uses the javascript function 'pjump'.
                   1061: #
                   1062: # @param {string} $type - parameter type
                   1063: # @param {string} $dis - dialog title for editing the parameter value and type
                   1064: # @param {string} $value - parameter value
                   1065: # @param {string} $marker - identifier for the parameter, "resource id&part_parameter name&level", will be passed as pres_marker when the user submits a change.
                   1066: # @param {string} $return - prefix for the name of the form and field names that will be used to submit the form ('parmform.pres')
                   1067: # @param {string} $call - javascript function to call to submit the form ('psub')
1.588     raeburn  1068: # @param {boolean} $recursive - true if link is for a map/folder where parameter is currently set to be recursive.
                   1069: # @param {string} $extra - optional additional information to send as tenth arg in call to javascript pjump function.
1.5       www      1070: sub plink {
1.588     raeburn  1071:     my ($type,$dis,$value,$marker,$return,$call,$recursive,$extra)=@_;
1.23      www      1072:     my $winvalue=$value;
                   1073:     unless ($winvalue) {
1.592     raeburn  1074:         if (&isdateparm($type) || (&is_specialstring($type))) {
1.190     albertel 1075:             $winvalue=$env{'form.recent_'.$type};
1.591     raeburn  1076:         } elsif ($type eq 'string_yesno') {
                   1077:             if ($env{'form.recent_string'} =~ /^(yes|no)$/i) {
                   1078:                 $winvalue=$env{'form.recent_string'};
                   1079:             }
1.23      www      1080:         } else {
1.190     albertel 1081:             $winvalue=$env{'form.recent_'.(split(/\_/,$type))[0]};
1.23      www      1082:         }
                   1083:     }
1.229     www      1084:     my ($parmname)=((split(/\&/,$marker))[1]=~/\_([^\_]+)$/);
                   1085:     my ($hour,$min,$sec,$val)=&preset_defaults($parmname);
                   1086:     unless (defined($winvalue)) { $winvalue=$val; }
1.593     raeburn  1087:     my $valout = &valout($value,$type,1);
1.429     raeburn  1088:     my $unencmarker = $marker;
1.378     albertel 1089:     foreach my $item (\$type, \$dis, \$winvalue, \$marker, \$return, \$call,
1.588     raeburn  1090:               \$hour, \$min, \$sec, \$extra) {
1.560     damieng  1091:         $$item = &HTML::Entities::encode($$item,'"<>&');
                   1092:         $$item =~ s/\'/\\\'/g;
1.378     albertel 1093:     }
1.429     raeburn  1094:     return '<table width="100%"><tr valign="top" align="right"><td><a name="'.$unencmarker.'" /></td></tr><tr><td align="center">'.
1.473     amueller 1095:     '<a href="javascript:pjump('."'".$type."','".$dis."','".$winvalue."','"
1.588     raeburn  1096:         .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."','".$extra."'".');">'.
1.578     raeburn  1097:         $valout.'</a></td></tr>'.($recursive?'<tr><td align="center" class="LC_parm_recursive">'.
                   1098:                                               &mt('recursive').'</td></tr>' : '').'</table>';
                   1099: 
1.5       www      1100: }
                   1101: 
1.561     damieng  1102: # Javascript for table mode.
1.280     albertel 1103: sub page_js {
                   1104: 
1.81      www      1105:     my $selscript=&Apache::loncommon::studentbrowser_javascript();
1.88      matthew  1106:     my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
1.280     albertel 1107: 
                   1108:     return(<<ENDJS);
                   1109: <script type="text/javascript">
1.454     bisitz   1110: // <![CDATA[
1.44      albertel 1111: 
1.88      matthew  1112:     $pjump_def
1.44      albertel 1113: 
                   1114:     function psub() {
1.591     raeburn  1115:         var specstring = /^string_!(yesno|any)/i;
1.44      albertel 1116:         if (document.parmform.pres_marker.value!='') {
                   1117:             document.parmform.action+='#'+document.parmform.pres_marker.value;
                   1118:             var typedef=new Array();
                   1119:             typedef=document.parmform.pres_type.value.split('_');
1.562     damieng  1120:             if (document.parmform.pres_type.value!='') {
1.589     raeburn  1121:                 if ((typedef[0]=='date') || 
1.591     raeburn  1122:                     (specstring.test(document.parmform.pres_type.value)))  {
1.562     damieng  1123:                     eval('document.parmform.recent_'+
                   1124:                         document.parmform.pres_type.value+
                   1125:                         '.value=document.parmform.pres_value.value;');
                   1126:                 } else {
                   1127:                     eval('document.parmform.recent_'+typedef[0]+
                   1128:                         '.value=document.parmform.pres_value.value;');
                   1129:                 }
1.44      albertel 1130:             }
                   1131:             document.parmform.submit();
                   1132:         } else {
                   1133:             document.parmform.pres_value.value='';
                   1134:             document.parmform.pres_marker.value='';
                   1135:         }
                   1136:     }
                   1137: 
1.57      albertel 1138:     function openWindow(url, wdwName, w, h, toolbar,scrollbar) {
                   1139:         var options = "width=" + w + ",height=" + h + ",";
                   1140:         options += "resizable=yes,scrollbars="+scrollbar+",status=no,";
                   1141:         options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";
                   1142:         var newWin = window.open(url, wdwName, options);
                   1143:         newWin.focus();
                   1144:     }
1.523     raeburn  1145: 
1.454     bisitz   1146: // ]]>
1.523     raeburn  1147: 
1.44      albertel 1148: </script>
1.81      www      1149: $selscript
1.280     albertel 1150: ENDJS
                   1151: 
                   1152: }
1.507     www      1153: 
1.561     damieng  1154: # Javascript to show or hide the map selection (function showHide_courseContent),
                   1155: # for table and overview modes.
1.523     raeburn  1156: sub showhide_js {
                   1157:     return <<"COURSECONTENTSCRIPT";
                   1158: 
                   1159: function showHide_courseContent() {
                   1160:     var parmlevValue=document.getElementById("parmlev").value;
                   1161:     if (parmlevValue == 'general') {
                   1162:         document.getElementById('mapmenu').style.display="none";
                   1163:     } else {
                   1164:         if ((parmlevValue == "full") || (parmlevValue == "map")) {
                   1165:             document.getElementById('mapmenu').style.display ="";
                   1166:         } else {
                   1167:             document.getElementById('mapmenu').style.display="none";
                   1168:         }
                   1169:     }
                   1170:     return;
                   1171: }
                   1172: 
                   1173: COURSECONTENTSCRIPT
                   1174: }
                   1175: 
1.561     damieng  1176: # Javascript functions showHideLenient and toggleParmTextbox, for overview mode
1.549     raeburn  1177: sub toggleparmtextbox_js {
                   1178:     return <<"ENDSCRIPT";
                   1179: 
                   1180: if (!document.getElementsByClassName) {
                   1181:     function getElementsByClassName(node, classname) {
                   1182:         var a = [];
                   1183:         var re = new RegExp('(^| )'+classname+'( |$)');
                   1184:         var els = node.getElementsByTagName("*");
                   1185:         for(var i=0,j=els.length; i<j; i++)
                   1186:             if(re.test(els[i].className))a.push(els[i]);
                   1187:         return a;
                   1188:     }
                   1189: }
                   1190: 
                   1191: function showHideLenient() {
                   1192:     var lenients;
                   1193:     var setRegExp = /^set_/;
                   1194:     if (document.getElementsByClassName) {
                   1195:         lenients = document.getElementsByClassName('LC_lenient_radio');
                   1196:     } else {
                   1197:         lenients = getElementsByClassName(document.body,'LC_lenient_radio');
                   1198:     }
                   1199:     if (lenients != 'undefined') {
                   1200:         for (var i=0; i<lenients.length; i++) {
                   1201:             if (lenients[i].checked) {
                   1202:                 if (lenients[i].value == 'weighted') {
                   1203:                     if (setRegExp.test(lenients[i].name)) {
                   1204:                         var identifier = lenients[i].name.replace(setRegExp,'');
                   1205:                         toggleParmTextbox(document.parmform,identifier);
                   1206:                     }
                   1207:                 }
                   1208:             }
                   1209:         }
                   1210:     }
                   1211:     return;
                   1212: }
                   1213: 
                   1214: function toggleParmTextbox(form,key) {
                   1215:     var divfortext = document.getElementById('LC_parmtext_'+key);
                   1216:     if (divfortext) {
                   1217:         var caller = form.elements['set_'+key];
                   1218:         if (caller.length) {
                   1219:             for (i=0; i<caller.length; i++) {
                   1220:                 if (caller[i].checked) {
                   1221:                     if (caller[i].value == 'weighted') {
                   1222:                         divfortext.style.display = 'inline';
                   1223:                     } else {
                   1224:                         divfortext.style.display = 'none';
                   1225:                     }
                   1226:                 }
                   1227:             }
                   1228:         }
                   1229:     }
                   1230:     return;
                   1231: }
                   1232: 
                   1233: ENDSCRIPT
                   1234: }
                   1235: 
1.561     damieng  1236: # Javascript function validateParms, for overview mode
1.549     raeburn  1237: sub validateparms_js {
                   1238:     return <<'ENDSCRIPT';
                   1239: 
                   1240: function validateParms() {
                   1241:     var textRegExp = /^settext_/;
                   1242:     var tailLenient = /\.lenient$/;
                   1243:     var patternRelWeight = /^\-?[\d.]+$/;
                   1244:     var patternLenientStd = /^(yes|no|default)$/;
1.597     raeburn  1245:     var ipRegExp = /^setip/;
1.549     raeburn  1246:     var ipallowRegExp = /^setipallow_/;
                   1247:     var ipdenyRegExp = /^setipdeny_/; 
1.597     raeburn  1248:     var deeplinkRegExp = /^deeplink_/;
1.601     raeburn  1249:     var dlListScopeRegExp = /^deeplink_(state|others|listing|scope)_/; 
                   1250:     var dlLinkProtectRegExp = /^deeplink_protect_/;
                   1251:     var dlLtidRegExp = /^deeplink_ltid_/;
                   1252:     var dlLticRegExp = /^deeplink_ltic_/;
1.597     raeburn  1253:     var dlKeyRegExp = /^deeplink_key_/;
                   1254:     var dlMenusRegExp = /^deeplink_menus_/;
                   1255:     var dlCollsRegExp = /^deeplink_colls_/;
1.613     raeburn  1256:     var dlTargetRegExp = /^deeplink_target_/;
1.616     raeburn  1257:     var dlExitRegExp = /^deeplink_exit_/;
                   1258:     var dlExitTextRegExp = /^deeplink_exittext_/;
1.549     raeburn  1259:     var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;
1.616     raeburn  1260:     var numelements = document.parmform.elements.length;
                   1261:     if ((typeof(numelements) != 'undefined') && (numelements != null)) {
                   1262:         if (numelements) {
                   1263:             for (i=0; i<numelements; i++) {
1.549     raeburn  1264:                 var name=document.parmform.elements[i].name;
1.588     raeburn  1265:                 if (textRegExp.test(name)) {
1.549     raeburn  1266:                     var identifier = name.replace(textRegExp,'');
                   1267:                     if (tailLenient.test(identifier)) {
                   1268:                         if (document.parmform.elements['set_'+identifier].length) {
                   1269:                             for (var j=0; j<document.parmform.elements['set_'+identifier].length; j++) {
                   1270:                                 if (document.parmform.elements['set_'+identifier][j].checked) {
                   1271:                                     if (!(patternLenientStd.test(document.parmform.elements['set_'+identifier][j].value))) {
                   1272:                                         var relweight = document.parmform.elements[i].value;
                   1273:                                         relweight = relweight.replace(/^\s+|\s+$/g,'');
                   1274:                                         if (!patternRelWeight.test(relweight)) {
                   1275:                                             relweight = '0.0';
                   1276:                                         }
                   1277:                                         if (document.parmform.elements['set_'+identifier][j].value == 'weighted') {
                   1278:                                             document.parmform.elements['set_'+identifier][j].value = relweight;
                   1279:                                         } else {
                   1280:                                             document.parmform.elements['set_'+identifier][j].value += ','+relweight;
                   1281:                                         }
                   1282:                                     }
                   1283:                                     break;
                   1284:                                 }
                   1285:                             }
                   1286:                         }
                   1287:                     }
1.597     raeburn  1288:                 } else if (ipRegExp.test(name)) {
                   1289:                     if (ipallowRegExp.test(name)) {
                   1290:                         var identifier = name.replace(ipallowRegExp,'');
                   1291:                         var possallow = document.parmform.elements[i].value;
                   1292:                         possallow = possallow.replace(/^\s+|\s+$/g,'');
                   1293:                         if (patternIP.test(possallow)) {
                   1294:                             if (document.parmform.elements['set_'+identifier].value) {
                   1295:                                 possallow = ','+possallow;
                   1296:                             }
                   1297:                             document.parmform.elements['set_'+identifier].value += possallow;
                   1298:                         }
                   1299:                     } else if (ipdenyRegExp.test(name)) {
                   1300:                         var identifier = name.replace(ipdenyRegExp,'');
                   1301:                         var possdeny = document.parmform.elements[i].value;
                   1302:                         possdeny = possdeny.replace(/^\s+|\s+$/g,'');
                   1303:                         if (patternIP.test(possdeny)) {
                   1304:                             possdeny = '!'+possdeny;
                   1305:                             if (document.parmform.elements['set_'+identifier].value) {
                   1306:                                 possdeny = ','+possdeny;
                   1307:                             }
                   1308:                             document.parmform.elements['set_'+identifier].value += possdeny;
1.588     raeburn  1309:                         }
                   1310:                     }
                   1311:                 } else if (deeplinkRegExp.test(name)) {
1.597     raeburn  1312:                     if (dlListScopeRegExp.test(name)) {
                   1313:                         var identifier =  name.replace(dlListScopeRegExp,'');
                   1314:                         var idx = document.parmform.elements[i].selectedIndex;
                   1315:                         if (idx > 0) { 
                   1316:                             var possdeeplink = document.parmform.elements[i].options[idx].value
                   1317:                             possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,'');
                   1318:                             if (document.parmform.elements['set_'+identifier].value) {
                   1319:                                 possdeeplink = ','+possdeeplink;
                   1320:                             }
                   1321:                             document.parmform.elements['set_'+identifier].value += possdeeplink;
                   1322:                         }
1.601     raeburn  1323:                     } else if (dlLinkProtectRegExp.test(name)) {
1.597     raeburn  1324:                         if (document.parmform.elements[i].checked) {
1.601     raeburn  1325:                             var identifier =  name.replace(dlLinkProtectRegExp,'');
1.597     raeburn  1326:                             var posslinkurl = document.parmform.elements[i].value;
                   1327:                             posslinkurl = posslinkurl.replace(/^\s+|\s+$/g,'');
                   1328:                             if (document.parmform.elements['set_'+identifier].value) {
                   1329:                                 posslinkurl = ','+posslinkurl;
                   1330:                             }
                   1331:                             document.parmform.elements['set_'+identifier].value += posslinkurl;
                   1332:                         }
1.601     raeburn  1333:                     } else if (dlLtidRegExp.test(name)) {
                   1334:                         var identifier = name.replace(dlLtidRegExp,'');
                   1335:                         if (isRadioSet('deeplink_protect_'+identifier,'ltid')) {
                   1336:                             var possltid = document.parmform.elements[i].value;
                   1337:                             possltid = possltid.replace(/\D+/g,'');
                   1338:                             if (possltid.length) {
1.597     raeburn  1339:                                 if (document.parmform.elements['set_'+identifier].value) {
1.601     raeburn  1340:                                     possltid = ':'+possltid;
1.597     raeburn  1341:                                 }
1.601     raeburn  1342:                                 document.parmform.elements['set_'+identifier].value += possltid;
1.597     raeburn  1343:                             } else {
                   1344:                                 document.parmform.elements['set_'+identifier].value = '';
1.601     raeburn  1345:                                 alert("A link type of 'domain LTI launch' was selected but no domain LTI launcher was selected.\nPlease select one, or choose a different supported link type.");
1.597     raeburn  1346:                                 return false;  
                   1347:                             }
                   1348:                         }
1.601     raeburn  1349:                     } else if (dlLticRegExp.test(name)) {
                   1350:                         var identifier = name.replace(dlLticRegExp,'');
                   1351:                         if (isRadioSet('deeplink_protect_'+identifier,'ltic')) {
                   1352:                             var possltic = document.parmform.elements[i].value;
                   1353:                             possltic = possltic.replace(/\D+/g,'');
                   1354:                             if (possltic.length) {
                   1355:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1356:                                     possltic = ':'+possltic;
                   1357:                                 }
                   1358:                                 document.parmform.elements['set_'+identifier].value += possltic;
                   1359:                             } else {
                   1360:                                 document.parmform.elements['set_'+identifier].value = '';
                   1361:                                 alert("A link type of 'course LTI launch' was selected but no course LTI launcher was selected.\nPlease select one, or choose a different supported link type.");
                   1362:                                 return false;
                   1363:                             }
                   1364:                         }
1.597     raeburn  1365:                     } else if (dlKeyRegExp.test(name)) {
                   1366:                         var identifier = name.replace(dlKeyRegExp,'');
1.601     raeburn  1367:                         if (isRadioSet('deeplink_protect_'+identifier,'key')) {
1.597     raeburn  1368:                             var posskey = document.parmform.elements[i].value;
                   1369:                             posskey = posskey.replace(/^\s+|\s+$/g,'');
                   1370:                             var origlength = posskey.length;
                   1371:                             posskey = posskey.replace(/[^a-zA-Z\d_.!@#$%^&*()+=-]/g,'');
                   1372:                             var newlength = posskey.length;
                   1373:                             if (newlength > 0) {
                   1374:                                 var change = origlength - newlength;
                   1375:                                 if (change) {
                   1376:                                     alert(change+' disallowed character(s) removed from deeplink key'); 
                   1377:                                 }
                   1378:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1379:                                     posskey = ':'+posskey;
                   1380:                                 }
                   1381:                                 document.parmform.elements['set_'+identifier].value += posskey;
                   1382:                             } else {
                   1383:                                 document.parmform.elements['set_'+identifier].value = '';
                   1384:                                 if (newlength < origlength) {
                   1385:                                     alert("A link type of 'deep with key' was selected but the key value was blank, after removing disallowed characters.\nPlease enter a key using one or more of: a-zA-Z0-9_.!@#$%^&*()+=-");
                   1386:                                 } else {
                   1387:                                     alert("A link type of 'deep with key' was selected but the key value was blank.\nPlease enter a key.");
                   1388:                                 }
                   1389:                                 return false;
                   1390:                             }
                   1391:                         }
                   1392:                     } else if (dlMenusRegExp.test(name)) {
                   1393:                         if (document.parmform.elements[i].checked) {
                   1394:                             var identifier =  name.replace(dlMenusRegExp,'');
                   1395:                             var posslinkmenu = document.parmform.elements[i].value;
                   1396:                             posslinkmenu = posslinkmenu.replace(/^\s+|\s+$/g,'');
                   1397:                             if (posslinkmenu == 'std') {
                   1398:                                 posslinkmenu = '0';
                   1399:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1400:                                     posslinkmenu = ','+posslinkmenu;
                   1401:                                 }
                   1402:                                 document.parmform.elements['set_'+identifier].value += posslinkmenu;
                   1403:                             }
                   1404:                         }
                   1405:                     } else if (dlCollsRegExp.test(name)) {
                   1406:                         var identifier =  name.replace(dlCollsRegExp,'');
                   1407:                         if (isRadioSet('deeplink_menus_'+identifier,'colls')) {
                   1408:                             var posslinkmenu = document.parmform.elements[i].value;
                   1409:                             if (document.parmform.elements['set_'+identifier].value) {
                   1410:                                 posslinkmenu = ','+posslinkmenu;
                   1411:                             }
                   1412:                             document.parmform.elements['set_'+identifier].value += posslinkmenu;
                   1413:                         }
1.614     raeburn  1414:                     } else if (dlTargetRegExp.test(name)) {
                   1415:                         var identifier =  name.replace(dlTargetRegExp,'');
1.613     raeburn  1416:                         var idx = document.parmform.elements[i].selectedIndex;
                   1417:                         if (idx > 0) {
1.616     raeburn  1418:                             var linktarget = document.parmform.elements[i].options[idx].value
                   1419:                             linktarget = linktarget.replace(/^\s+|\s+$/g,'');
                   1420:                             if (document.parmform.elements['set_'+identifier].value) {
                   1421:                                 linktarget = ','+linktarget;
                   1422:                             }
                   1423:                             document.parmform.elements['set_'+identifier].value += linktarget;
                   1424:                         }
                   1425:                     } else if (dlExitRegExp.test(name)) {
                   1426:                         if (document.parmform.elements[i].checked) {
                   1427:                             var identifier =  name.replace(dlExitRegExp,'');
                   1428:                             var posslinkexit = document.parmform.elements[i].value;
                   1429:                             posslinkexit = posslinkexit.replace(/^\s+|\s+$/g,'');
1.613     raeburn  1430:                             if (document.parmform.elements['set_'+identifier].value) {
1.616     raeburn  1431:                                 posslinkexit = ','+posslinkexit;
                   1432:                             }
                   1433:                             document.parmform.elements['set_'+identifier].value += posslinkexit;
                   1434:                         }
                   1435:                     } else if (dlExitTextRegExp.test(name)) {
                   1436:                         var identifier = name.replace(dlExitTextRegExp,'');
                   1437:                         if ((isRadioSet('deeplink_exit_'+identifier,'yes')) ||
                   1438:                             (isRadioSet('deeplink_exit_'+identifier,'url'))) {
                   1439:                             var posstext = document.parmform.elements[i].value;
                   1440:                             posstext = posstext.replace(/^\s+|\s+$/g,'');
                   1441:                             var origlength = posstext.length;
                   1442:                             posstext = posstext.replace(/[:;'",]/g,'');
                   1443:                             var newlength = posstext.length;
                   1444:                             if (newlength > 0) {
                   1445:                                 var change = origlength - newlength;
                   1446:                                 if (change) {
                   1447:                                     alert(change+' disallowed character(s) removed from Exit Button text');
                   1448:                                 }
                   1449:                                 if (posstext !== 'Exit Tool') {
                   1450:                                     posstext = ':'+posstext;
                   1451:                                     document.parmform.elements['set_'+identifier].value += posstext;
                   1452:                                 }
                   1453:                             } else {
                   1454:                                 document.parmform.elements['set_'+identifier].value = '';
                   1455:                                 if (newlength < origlength) {
                   1456:                                     alert("An exit link type of 'In use' was selected but the button text value was blank, after removing disallowed characters.\nDisallowed characters are ,\":;'");
                   1457:                                 } else {
                   1458:                                     alert("An exit link type of 'In use' was selected but the button text value was blank.\nPlease enter the text to use.");
                   1459:                                 }
                   1460:                                 return false;
1.613     raeburn  1461:                             }
                   1462:                         }
1.549     raeburn  1463:                     }
                   1464:                 }
                   1465:             }
                   1466:         }
                   1467:     }
                   1468:     return true;
                   1469: }
                   1470: 
1.597     raeburn  1471: function isRadioSet(name,expected) {
                   1472:     var menuitems = document.getElementsByName(name);
                   1473:     var radioLength = menuitems.length;
                   1474:     result = false;
                   1475:     if (radioLength  > 1) {
                   1476:         for (var j=0; j<radioLength; j++) {
                   1477:             if (menuitems[j].checked) {
                   1478:                 if (menuitems[j].value == expected) {
                   1479:                     result = true;
                   1480:                     break;
                   1481:                 }
                   1482:             }
                   1483:         }
                   1484:     }
                   1485:     return result;
                   1486: }
                   1487: 
1.549     raeburn  1488: ENDSCRIPT
                   1489: }
                   1490: 
1.561     damieng  1491: # Javascript initialization, for overview mode
1.549     raeburn  1492: sub ipacc_boxes_js  {
                   1493:     my $remove = &mt('Remove');
                   1494:     return <<"END";
                   1495: \$(document).ready(function() {
                   1496:     var wrapper         = \$(".LC_string_ipacc_wrap");
                   1497:     var add_button      = \$(".LC_add_ipacc_button");
                   1498:     var ipaccRegExp     = /^LC_string_ipacc_/;
                   1499: 
                   1500:     \$(add_button).click(function(e){
                   1501:         e.preventDefault();
                   1502:         var identifier = \$(this).closest("div").attr("id");
                   1503:         identifier = identifier.replace(ipaccRegExp,'');
1.551     raeburn  1504:         \$(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  1505:     });
                   1506: 
                   1507:     \$(wrapper).delegate(".LC_remove_ipacc","click", function(e){
                   1508:         e.preventDefault(); \$(this).closest("div").remove();
                   1509:     })
                   1510: });
                   1511: 
                   1512: 
                   1513: END
                   1514: }
                   1515: 
1.561     damieng  1516: # Javascript function toggleSecret, for overview mode.
1.558     raeburn  1517: sub done_proctor_js {
1.611     raeburn  1518:     my $defaultdone = &mt('Done');
                   1519:     &js_escape(\$defaultdone);
1.558     raeburn  1520:     return <<"END";
                   1521: function toggleSecret(form,radio,key) {
                   1522:     var radios = form[radio+key];
                   1523:     if (radios.length) {
                   1524:         for (var i=0; i<radios.length; i++) {
                   1525:             if (radios[i].checked) {
                   1526:                 if (radios[i].value == '_done_proctor') {
                   1527:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1528:                         document.getElementById('done_'+key+'_proctorkey').type='text';
                   1529:                     }
                   1530:                 } else {
                   1531:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1532:                         document.getElementById('done_'+key+'_proctorkey').type='hidden';
                   1533:                         document.getElementById('done_'+key+'_proctorkey').value='';
                   1534:                     }
                   1535:                 }
1.611     raeburn  1536:                 if (document.getElementById('done_'+key+'_buttontext')) {
                   1537:                     if (radios[i].value == '') {
                   1538:                         document.getElementById('done_'+key+'_buttontext').value = '';
                   1539:                     } else {
                   1540:                         if (document.getElementById('done_'+key+'_buttontext').value == '') {
                   1541:                             document.getElementById('done_'+key+'_buttontext').value = '$defaultdone';
                   1542:                         }
                   1543:                     }
                   1544:                 }
1.558     raeburn  1545:             }
                   1546:         }
                   1547:     }
                   1548: }
                   1549: END
                   1550: 
                   1551: }
                   1552: 
1.588     raeburn  1553: # Javascript function toggle
                   1554: sub deeplink_js {
                   1555:     return <<"END";
                   1556: function toggleDeepLink(form,item,key) {
                   1557:     var radios = form['deeplink_'+item+'_'+key];
                   1558:     if (radios.length) {
                   1559:         var keybox;
                   1560:         if (document.getElementById('deeplink_key_'+item+'_'+key)) {
                   1561:             keybox = document.getElementById('deeplink_key_'+item+'_'+key);
                   1562:         }
1.601     raeburn  1563:         var divoptions = new Array();
                   1564:         if (item == 'protect') {
                   1565:             divoptions = ['ltic','ltid'];
1.597     raeburn  1566:         } else {
                   1567:             if (item == 'menus') {
1.601     raeburn  1568:                 divoptions = ['colls'];
1.597     raeburn  1569:             }
                   1570:         }
1.601     raeburn  1571:         var seldivs = new Array();
                   1572:         if ((item == 'protect') || (item == 'menus')) {
                   1573:             for (var i=0; i<divoptions.length; i++) {
                   1574:                 if (document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key)) {
                   1575:                     seldivs[i] = document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key);
                   1576:                 } else {
                   1577:                     seldivs[i] = '';
                   1578:                 }
                   1579:             }
1.588     raeburn  1580:         }
                   1581:         for (var i=0; i<radios.length; i++) {
                   1582:             if (radios[i].checked) {
1.601     raeburn  1583:                 if ((item == 'protect') || (item == 'menus')) {
                   1584:                     for (var j=0; j<seldivs.length; j++) {
                   1585:                         if (radios[i].value == divoptions[j]) {
                   1586:                             if (seldivs[j] != '') {
                   1587:                                 seldivs[j].style.display = 'inline-block';
                   1588:                             }
                   1589:                             if (item == 'protect') {
                   1590:                                 keybox.type = 'hidden';
                   1591:                                 keybox.value = '';
                   1592:                             }
                   1593:                         } else {
                   1594:                             if (seldivs[j] != '') {
                   1595:                                 seldivs[j].style.display = 'none';
                   1596:                                 form['deeplink_'+divoptions[j]+'_'+key].selectedIndex = 0;
                   1597:                             }
                   1598:                         }
1.597     raeburn  1599:                     }
1.601     raeburn  1600:                     if (item == 'protect') {
1.597     raeburn  1601:                         if (radios[i].value == 'key') {
                   1602:                             keybox.type = 'text';
                   1603:                         } else {
                   1604:                             keybox.type = 'hidden';
                   1605:                         }
1.588     raeburn  1606:                     }
1.616     raeburn  1607:                 } else if (item == 'exit') {
                   1608:                     if (document.getElementById('deeplinkdiv_'+item+'_'+key)) {
                   1609:                         if (radios[i].value == 'no') {
                   1610:                             document.getElementById('deeplinkdiv_'+item+'_'+key).style.display = 'none';          
                   1611:                             if (document.getElementById('deeplink_exittext_'+key)) {
                   1612:                                 if (document.getElementById('deeplink_exittext_'+key).value != '') {
                   1613:                                     document.getElementById('deeplink_exittext_'+key).value = '';    
                   1614:                                 }
                   1615:                             }
                   1616:                         } else {
                   1617:                             document.getElementById('deeplinkdiv_'+item+'_'+key).style.display = 'inline-block';
                   1618:                             if (document.getElementById('deeplink_exittext_'+key)) {
                   1619:                                 if (document.getElementById('deeplink_exittext_'+key).value == '') {
                   1620:                                     document.getElementById('deeplink_exittext_'+key).value = 'Exit Tool';
                   1621:                                 }
                   1622:                             }
                   1623:                         }
                   1624:                     }
1.588     raeburn  1625:                 }
                   1626:             }
                   1627:         }
                   1628:     }
                   1629: }
                   1630: END
                   1631: 
                   1632: }
                   1633: 
1.561     damieng  1634: # Prints HTML page start for table mode.
                   1635: # @param {Apache2::RequestRec} $r - the Apache request
                   1636: # @param {string} $psymb - resource symb
                   1637: # @param {string} $crstype - course type (Community / Course / Placement Test)
1.280     albertel 1638: sub startpage {
1.531     raeburn  1639:     my ($r,$psymb,$crstype) = @_;
1.281     albertel 1640: 
1.515     raeburn  1641:     my %loaditems = (
                   1642:                       'onload'   => "group_or_section('cgroup')",
                   1643:                     );
                   1644:     if (!$psymb) {
1.523     raeburn  1645:         $loaditems{'onload'} = "showHide_courseContent(); group_or_section('cgroup'); resize_scrollbox('mapmenuscroll','1','1');";
1.515     raeburn  1646:     }
1.280     albertel 1647: 
1.560     damieng  1648:     if ((($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   1649:             (!$env{'form.dis'})) || ($env{'form.symb'})) {
                   1650:         &Apache::lonhtmlcommon::add_breadcrumb({help=>'Problem_Parameters',
                   1651:             text=>"Problem Parameters"});
1.414     droeschl 1652:     } else {
1.560     damieng  1653:         &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
                   1654:             text=>"Table Mode",
                   1655:             help => 'Course_Setting_Parameters'});
1.414     droeschl 1656:     }
1.523     raeburn  1657:     my $js = &page_js().'
                   1658: <script type="text/javascript">
                   1659: // <![CDATA[
                   1660: '.
                   1661:             &Apache::lonhtmlcommon::resize_scrollbox_js('params').'
                   1662: // ]]>
                   1663: </script>
                   1664: ';
1.446     bisitz   1665:     my $start_page =
1.523     raeburn  1666:         &Apache::loncommon::start_page('Set/Modify Course Parameters',$js,
                   1667:                                        {'add_entries' => \%loaditems,});
1.446     bisitz   1668:     my $breadcrumbs =
1.473     amueller 1669:     &Apache::lonhtmlcommon::breadcrumbs('Table Mode Parameter Setting','Table_Mode');
1.506     www      1670:     my $escfilter=&Apache::lonhtmlcommon::entity_encode($env{'form.filter'});
                   1671:     my $escpart=&Apache::lonhtmlcommon::entity_encode($env{'form.part'});
1.507     www      1672:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  1673:     &startSettingsScreen($r,'parmset',$crstype);
1.280     albertel 1674:     $r->print(<<ENDHEAD);
1.193     albertel 1675: <form method="post" action="/adm/parmset?action=settable" name="parmform">
1.419     bisitz   1676: <input type="hidden" value="" name="pres_value" />
                   1677: <input type="hidden" value="" name="pres_type" />
                   1678: <input type="hidden" value="" name="pres_marker" />
                   1679: <input type="hidden" value="1" name="prevvisit" />
1.506     www      1680: <input type="hidden" value="$escfilter" name="filter" />
                   1681: <input type="hidden" value="$escpart" name="part" />
1.44      albertel 1682: ENDHEAD
                   1683: }
                   1684: 
1.209     www      1685: 
1.561     damieng  1686: # Prints a row for table mode (except for the tr start).
                   1687: # Every time a hash reference is passed, a single entry is used, so print_row
                   1688: # could just use these values, but why make it simple when it can be complicated ?
                   1689: #
                   1690: # @param {Apache2::RequestRec} $r - the Apache request
                   1691: # @param {string} $which - parameter key ('parameter_'.part.'_'.name)
                   1692: # @param {hash reference} $part - parameter key -> parameter part (can be problem part.'_'.response id for response parameters)
                   1693: # @param {hash reference} $name - parameter key -> parameter name
1.566     damieng  1694: # @param {hash reference} $symbp - map pc or resource/map id -> map src.'___(all)' or resource symb
1.561     damieng  1695: # @param {string} $rid - resource id
                   1696: # @param {hash reference} $default - parameter key -> resource parameter default value
                   1697: # @param {hash reference} $defaulttype - parameter key -> resource parameter default type
                   1698: # @param {hash reference} $display - parameter key -> full title for the parameter
                   1699: # @param {string} $defbgone - user level and other levels background color
                   1700: # @param {string} $defbgtwo - section level background color, also used for part number
                   1701: # @param {string} $defbgthree - group level background color
                   1702: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   1703: # @param {string} $uname - user name
                   1704: # @param {string} $udom - user domain
                   1705: # @param {string} $csec - section name
                   1706: # @param {string} $cgroup - group name
                   1707: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   1708: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.582     raeburn  1709: # @param {boolean} $readonly - true if no editing allowed.
                   1710: # @param {array reference} - $recurseup - list of maps containing current one, ending at top-level.
                   1711: # @param {hash reference} - $maptitles - - hash map id or src -> map title 
                   1712: # @param {hash reference} - $allmaps_inverted - hash map src -> map pc
                   1713: # @param {scalar reference} - $reclinks - number of "parameter in effect" cells with link to map where recursive param was set 
1.44      albertel 1714: sub print_row {
1.201     www      1715:     my ($r,$which,$part,$name,$symbp,$rid,$default,$defaulttype,$display,$defbgone,
1.568     raeburn  1716:     $defbgtwo,$defbgthree,$parmlev,$uname,$udom,$csec,$cgroup,$usersgroups,$noeditgrp,
1.582     raeburn  1717:     $readonly,$recurseup,$maptitles,$allmaps_inverted,$reclinks)=@_;
1.275     raeburn  1718:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   1719:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   1720:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.582     raeburn  1721:     my $numlinks = 0;
1.553     raeburn  1722: 
1.560     damieng  1723:     # get the values for the parameter in cascading order
                   1724:     # empty levels will remain empty
1.44      albertel 1725:     my ($result,@outpar)=&parmval($$part{$which}.'.'.$$name{$which},
1.473     amueller 1726:       $rid,$$default{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1727:     # get the type for the parameters
                   1728:     # problem: these may not be set for all levels
1.66      www      1729:     my ($typeresult,@typeoutpar)=&parmval($$part{$which}.'.'.
1.275     raeburn  1730:                                           $$name{$which}.'.type',$rid,
1.473     amueller 1731:          $$defaulttype{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1732:     # cascade down manually
1.182     albertel 1733:     my $cascadetype=$$defaulttype{$which};
1.556     raeburn  1734:     for (my $i=18;$i>0;$i--) {
1.560     damieng  1735:         if ($typeoutpar[$i]) {
1.66      www      1736:             $cascadetype=$typeoutpar[$i];
1.560     damieng  1737:         } else {
1.66      www      1738:             $typeoutpar[$i]=$cascadetype;
                   1739:         }
                   1740:     }
1.57      albertel 1741:     my $parm=$$display{$which};
                   1742: 
1.203     www      1743:     if ($parmlev eq 'full') {
1.419     bisitz   1744:         $r->print('<td style="background-color:'.$defbgtwo.';" align="center">'
1.506     www      1745:                   .($$part{$which} eq '0'?'0 ('.&mt('default').')':$$part{$which}).'</td>');
1.433     raeburn  1746:     } else {
1.57      albertel 1747:         $parm=~s|\[.*\]\s||g;
                   1748:     }
1.231     www      1749:     my $automatic=&rulescache(($which=~/\_([^\_]+)$/)[0].'_triggers');
                   1750:     if ($automatic) {
1.560     damieng  1751:         $parm.='<span class="LC_warning"><br />'.&mt('Automatically sets').' '.join(', ',split(/\:/,$automatic)).'</span>';
1.231     www      1752:     }
1.619     raeburn  1753:     my $advice;
                   1754:     if ((ref($name) eq 'HASH') && ($name->{$which} eq 'mapalias') &&
                   1755:         (ref($symbp) eq 'HASH') && ($parmlev eq 'full')) {
                   1756:         if ($symbp->{$rid} =~ m{^uploaded/}) {
                   1757:             if ($result == 14) {
                   1758:                 $advice = &mt('Use Course Editor to modify this.');
                   1759:             } else {
                   1760:                 $advice = &mt('Use Course Editor to set this.');
                   1761:             }
                   1762:         } else {
                   1763:             if ($result == 14) {
                   1764:                 $advice = &mt('Use Resource Assembly Tool to modify this.');
                   1765:             } else {
                   1766:                 $advice = &mt('Use Resource Assembly Tool to set this.');
                   1767:             }
                   1768:         }
                   1769:         $parm .= '<br /><span class="LC_fontsize_small LC_cusr_emph">'.$advice.'</span>';
                   1770:     }
1.427     bisitz   1771:     $r->print('<td>'.$parm.'</td>');
1.446     bisitz   1772: 
1.44      albertel 1773:     my $thismarker=$which;
                   1774:     $thismarker=~s/^parameter\_//;
                   1775:     my $mprefix=$rid.'&'.$thismarker.'&';
1.582     raeburn  1776:     my ($parmname)=($thismarker=~/\_([^\_]+)$/);
                   1777:     my ($othergrp,$grp_parm,$controlgrp,$effective_parm,$effparm_rec,$effparm_level,
1.588     raeburn  1778:         $eff_groupparm,$recurse_check,$recursinfo,$extra);
1.582     raeburn  1779:     if ((ref($recurseup) eq 'ARRAY') && (@{$recurseup} > 0)) {
                   1780:         if ($result eq '') {
                   1781:             $recurse_check = 1;
                   1782:         } elsif (($uname ne '') && ($result > 3)) {
                   1783:             $recurse_check = 1;
                   1784:         } elsif (($cgroup ne '') && ($result > 7)) {
                   1785:             $recurse_check = 1;
                   1786:         } elsif (($csec ne '') && ($result > 11)) {
                   1787:             $recurse_check = 1;
                   1788:         } elsif ($result > 17) {
                   1789:             $recurse_check = 1;
                   1790:         }
                   1791:         if ($recurse_check) {
                   1792:             my $what = $$part{$which}.'.'.$$name{$which};
                   1793:             my $prefix;
                   1794:             if (($uname ne '') && ($udom ne '')) {
                   1795:                 my $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
                   1796:                 $prefix = $env{'request.course.id'};
                   1797:                 $recursinfo = &get_recursive($recurseup,$useropt,$what,$prefix);
                   1798:                 if (ref($recursinfo) eq 'ARRAY') {
                   1799:                     $effparm_rec = 1;
                   1800:                     $effparm_level = &mt('user: [_1]',$uname);
                   1801:                 }
                   1802:             }
                   1803:             if (($cgroup ne '') && (!$effparm_rec)) {
                   1804:                 $prefix = $env{'request.course.id'}.'.['.$cgroup.']';
                   1805:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
                   1806:                 if (ref($recursinfo) eq 'ARRAY') {
                   1807:                     $effparm_rec = 1;
                   1808:                     $effparm_level = &mt('group: [_1]',$cgroup);
                   1809:                 }
                   1810:             }
                   1811:             if (($csec ne '') && (!$effparm_rec)) {
                   1812:                 $prefix = $env{'request.course.id'}.'.['.$csec.']';
                   1813:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
                   1814:                 if (ref($recursinfo) eq 'ARRAY') {
                   1815:                     $effparm_rec = 1;
                   1816:                     $effparm_level = &mt('section: [_1]',$csec);
                   1817:                 }
                   1818:             }
                   1819:             if (!$effparm_rec) {
                   1820:                 $prefix = $env{'request.course.id'};
                   1821:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix); 
                   1822:                 if (ref($recursinfo) eq 'ARRAY') {
                   1823:                     $effparm_rec = 1;
                   1824:                 }
                   1825:             }
                   1826:         }
                   1827:     }
                   1828:     if ((!$effparm_rec) && ($result == 17 || $result == 11 || $result == 7 || $result == 3)) {
                   1829:         $effparm_rec = 1;
                   1830:     }
                   1831:     if ((!$effparm_rec) && 
                   1832:         (($$name{$which} eq 'encrypturl') || ($$name{$which} eq 'hiddenresource')) && 
                   1833:         ($result == 16 || $result == 10 || $result == 6 || $result == 2)) {
1.578     raeburn  1834:         $effparm_rec = 1;
                   1835:     }
1.588     raeburn  1836:     if ($parmname eq 'deeplink') {
1.601     raeburn  1837:         my ($domltistr,$crsltistr);
1.588     raeburn  1838:         my %lti =
                   1839:             &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604     raeburn  1840:                                             'linkprot');
1.601     raeburn  1841:         if (keys(%lti)) {
                   1842:             foreach my $item (sort { $a <=> $b }  (keys(%lti))) {
1.604     raeburn  1843:                 if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
                   1844:                     $domltistr .= $item.':'.&escape(&escape($lti{$item}{'name'})).',';
1.588     raeburn  1845:                 }
                   1846:             }
1.601     raeburn  1847:             $domltistr =~ s/,$//;
                   1848:             if ($domltistr) {
                   1849:                 $extra = 'ltid_'.$domltistr;
                   1850:             }
1.588     raeburn  1851:         }
1.620     raeburn  1852:         my %courselti = &Apache::lonnet::get_course_lti($cnum,$cdom,'provider');
1.601     raeburn  1853:         if (keys(%courselti)) {
                   1854:             foreach my $item (sort { $a <=> $b } keys(%courselti)) {
                   1855:                 if (($item =~ /^\d+$/) && (ref($courselti{$item}) eq 'HASH')) {
                   1856:                     $crsltistr .= $item.':'.&escape(&escape($courselti{$item}{'name'})).',';
                   1857:                 }
                   1858:             }
                   1859:             $crsltistr =~ s/,$//;
                   1860:             if ($crsltistr) {
                   1861:                 if ($extra) {
                   1862:                     $extra .= '&';
                   1863:                 }
                   1864:                 $extra .= 'ltic_'.$crsltistr;
1.588     raeburn  1865:             }
                   1866:         }
1.597     raeburn  1867:         if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
                   1868:             my @colls;
                   1869:             foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
                   1870:                 my ($num,$value) = split(/\%/,$item);
                   1871:                 if ($num =~ /^\d+$/) {
                   1872:                     push(@colls,$num);
                   1873:                 }
                   1874:             }
                   1875:             if (@colls) {
                   1876:                 if ($extra) {
                   1877:                     $extra .= '&';
                   1878:                 }
                   1879:                 $extra .= 'menus_'.join(',',@colls);
                   1880:             }
                   1881:         }
1.588     raeburn  1882:     }
1.57      albertel 1883:     if ($parmlev eq 'general') {
                   1884:         if ($uname) {
1.588     raeburn  1885:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.269     raeburn  1886:         } elsif ($cgroup) {
1.588     raeburn  1887:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1.57      albertel 1888:         } elsif ($csec) {
1.588     raeburn  1889:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57      albertel 1890:         } else {
1.588     raeburn  1891:             &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57      albertel 1892:         }
                   1893:     } elsif ($parmlev eq 'map') {
                   1894:         if ($uname) {
1.588     raeburn  1895:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.269     raeburn  1896:         } elsif ($cgroup) {
1.588     raeburn  1897:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1.57      albertel 1898:         } elsif ($csec) {
1.588     raeburn  1899:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57      albertel 1900:         } else {
1.588     raeburn  1901:             &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57      albertel 1902:         }
                   1903:     } else {
1.275     raeburn  1904:         if ($uname) {
                   1905:             if (@{$usersgroups} > 1) {
1.582     raeburn  1906:                 (my $coursereply,$othergrp,$grp_parm,$controlgrp,my $grp_is_rec) =
1.580     raeburn  1907:                     &check_other_groups($$part{$which}.'.'.$$name{$which},
1.275     raeburn  1908:                        $rid,$cgroup,$defbgone,$usersgroups,$result,$courseopt);
1.582     raeburn  1909:                 if (($coursereply) && ($result > 4)) {
1.275     raeburn  1910:                     if (defined($controlgrp)) {
                   1911:                         if ($cgroup ne $controlgrp) {
1.582     raeburn  1912:                             $eff_groupparm = $grp_parm;
                   1913:                             undef($result);
                   1914:                             undef($effparm_rec);
                   1915:                             if ($grp_is_rec) {
                   1916:                                  $effparm_rec = 1;
                   1917:                             }
1.275     raeburn  1918:                         }
                   1919:                     }
                   1920:                 }
                   1921:             }
                   1922:         }
1.57      albertel 1923: 
1.588     raeburn  1924:         &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1925:         &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1926:         &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1927:         &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1928:         &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1929: 
                   1930:         if ($csec) {
1.588     raeburn  1931:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1932:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1933:             &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1934:         }
1.269     raeburn  1935: 
                   1936:         if ($cgroup) {
1.588     raeburn  1937:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
                   1938:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
                   1939:             &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp.$readonly,'',$extra);
1.269     raeburn  1940:         }
1.446     bisitz   1941: 
1.548     raeburn  1942:         if ($uname) {
1.275     raeburn  1943:             if ($othergrp) {
                   1944:                 $r->print($othergrp);
                   1945:             }
1.588     raeburn  1946:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1947:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1948:             &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1949:         }
1.57      albertel 1950:     } # end of $parmlev if/else
1.582     raeburn  1951:     if (ref($recursinfo) eq 'ARRAY') {
                   1952:         my $rectitle = &mt('recursive');
                   1953:         if ((ref($maptitles) eq 'HASH') && (exists($maptitles->{$recursinfo->[2]}))) {
                   1954:             if ((ref($allmaps_inverted) eq 'HASH') && (exists($allmaps_inverted->{$recursinfo->[2]}))) {
                   1955:                 $rectitle = &mt('set in: [_1]','"'.
                   1956:                                 '<a href="javascript:pjumprec('."'".$allmaps_inverted->{$recursinfo->[2]}."',".
                   1957:                                                               "'$parmname','$$part{$which}'".');">'.
                   1958:                                 $maptitles->{$recursinfo->[2]}.'</a>"');
                   1959:               
                   1960:                 $numlinks ++;
                   1961:             }
                   1962:         }
                   1963:         my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1.593     raeburn  1964:         $effective_parm = &valout($recursinfo->[0],$recursinfo->[1]);
1.582     raeburn  1965:         $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
                   1966:                   '<br /><span class="LC_parm_recursive">'.$rectitle.'&nbsp;'.
                   1967:                   $effparm_level.'</span></td>');
                   1968:     } else {
                   1969:         if ($result) {
1.593     raeburn  1970:             $effective_parm = &valout($outpar[$result],$typeoutpar[$result]);
1.582     raeburn  1971:         }
                   1972:         if ($eff_groupparm) {
                   1973:             $effective_parm = $eff_groupparm;
                   1974:         }
                   1975:         $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
                   1976:                   ($effparm_rec?'<br /><span class="LC_parm_recursive">'.&mt('recursive').
                   1977:                                 '</span>':'').'</td>');
                   1978:     }
1.203     www      1979:     if ($parmlev eq 'full') {
1.136     albertel 1980:         my $sessionval=&Apache::lonnet::EXT('resource.'.$$part{$which}.
1.201     www      1981:                                         '.'.$$name{$which},$$symbp{$rid});
1.136     albertel 1982:         my $sessionvaltype=$typeoutpar[$result];
1.560     damieng  1983:         if (!defined($sessionvaltype)) {
                   1984:             $sessionvaltype=$$defaulttype{$which};
                   1985:         }
1.419     bisitz   1986:         $r->print('<td style="background-color:#999999;" align="center"><font color="#FFFFFF">'.
1.593     raeburn  1987:                   &valout($sessionval,$sessionvaltype).'&nbsp;'.
1.57      albertel 1988:                   '</font></td>');
1.136     albertel 1989:     }
1.44      albertel 1990:     $r->print('</tr>');
1.57      albertel 1991:     $r->print("\n");
1.582     raeburn  1992:     if (($numlinks) && (ref($reclinks))) {
                   1993:         $$reclinks = $numlinks;
                   1994:     }
1.44      albertel 1995: }
1.59      matthew  1996: 
1.561     damieng  1997: # Prints a cell for table mode.
                   1998: #
                   1999: # FIXME: some of these parameter names are uninspired ($which and $value)
                   2000: # Also, it would make more sense to pass the display for this cell rather
                   2001: # than the full display hash and the key to use.
                   2002: #
                   2003: # @param {Apache2::RequestRec} $r - the Apache request
                   2004: # @param {integer} $which - level
                   2005: # @param {string} $defbg - cell background color
                   2006: # @param {integer} $result - the most specific level that is defined for that parameter
                   2007: # @param {array reference} $outpar - array level -> parameter value (when defined)
                   2008: # @param {string} $mprefix - resource id.'&'.part.'_'.parameter name.'&'
                   2009: # @param {string} $value - parameter key ('parameter_'.part.'_'.name)
                   2010: # @param {array reference} $typeoutpar - array level -> parameter type (when defined)
                   2011: # @param {hash reference} $display - parameter key -> full title for the parameter
                   2012: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.568     raeburn  2013: # @param {boolean} $readonly -true if editing not allowed.
1.588     raeburn  2014: # @param {boolean} $ismaplevel - true if level is for a map.
1.597     raeburn  2015: # @param {string} $extra - extra information to pass to plink.
1.44      albertel 2016: sub print_td {
1.578     raeburn  2017:     my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,
1.588     raeburn  2018:         $noeditgrp,$readonly,$ismaplevel,$extra)=@_;
1.578     raeburn  2019:     my ($ineffect,$recursive,$currval,$currtype,$currlevel);
                   2020:     $ineffect = 0;
                   2021:     $currval = $$outpar[$which];
                   2022:     $currtype = $$typeoutpar[$which];
                   2023:     $currlevel = $which;
                   2024:     if (($result) && ($result == $which)) {
                   2025:         $ineffect = 1;
                   2026:     } 
                   2027:     if ($ismaplevel) {
                   2028:         if ($mprefix =~ /(hiddenresource|encrypturl)\&/) {
                   2029:             if (($result) && ($result == $which)) {
                   2030:                 $recursive = 1;
                   2031:             }
                   2032:         } elsif ($$outpar[$which+1] ne '') {
                   2033:             $recursive = 1;
                   2034:             $currlevel = $which+1;
                   2035:             $currval = $$outpar[$currlevel];
                   2036:             $currtype = $$typeoutpar[$currlevel];
                   2037:             if (($result) && ($result == $currlevel)) {
                   2038:                 $ineffect = 1;
                   2039:             }
                   2040:         }
                   2041:     }
                   2042:     $r->print('<td style="background-color:'.($ineffect?'#AAFFAA':$defbg).
1.419     bisitz   2043:               ';" align="center">');
1.437     raeburn  2044:     my $nolink = 0;
1.568     raeburn  2045:     if ($readonly) {
1.552     raeburn  2046:         $nolink = 1;
1.568     raeburn  2047:     } else { 
1.578     raeburn  2048:         if ($which == 14 || $which == 15 || $mprefix =~ /mapalias\&$/) {
1.553     raeburn  2049:             $nolink = 1;
1.568     raeburn  2050:         } elsif (($env{'request.course.sec'} ne '') && ($which > 12)) {
1.533     raeburn  2051:             $nolink = 1;
1.568     raeburn  2052:         } elsif ($which == 5 || $which ==  6 || $which == 7 || $which == 8) {
                   2053:             if ($noeditgrp) {
                   2054:                 $nolink = 1;
                   2055:             }
                   2056:         } elsif ($mprefix =~ /availablestudent\&$/) {
1.599     raeburn  2057:             $nolink = 1;
1.568     raeburn  2058:         } elsif ($mprefix =~ /examcode\&$/) {
                   2059:             unless ($which == 2) {
                   2060:                 $nolink = 1;
                   2061:             }
1.533     raeburn  2062:         }
1.437     raeburn  2063:     }
                   2064:     if ($nolink) {
1.577     raeburn  2065:         my ($parmname)=((split(/\&/,$mprefix))[1]=~/\_([^\_]+)$/);
1.593     raeburn  2066:         $r->print(&valout($currval,$currtype));
1.114     www      2067:     } else {
1.578     raeburn  2068:         $r->print(&plink($currtype,
                   2069:                          $$display{$value},$currval,
1.588     raeburn  2070:                          $mprefix.$currlevel,'parmform.pres','psub',$recursive,
                   2071:                          $extra));
1.114     www      2072:     }
                   2073:     $r->print('</td>'."\n");
1.57      albertel 2074: }
                   2075: 
1.561     damieng  2076: # Returns HTML and other info for the cell added when a user is selected
                   2077: # and that user is in several groups. This is the cell with the title "Control by other group".
                   2078: #
                   2079: # @param {string} $what - parameter part.'.'.parameter name
                   2080: # @param {string} $rid - resource id
                   2081: # @param {string} $cgroup - group name
                   2082: # @param {string} $defbg - cell background color
                   2083: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2084: # @param {integer} $result - level
                   2085: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
1.582     raeburn  2086: # @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  2087: sub check_other_groups {
                   2088:     my ($what,$rid,$cgroup,$defbg,$usersgroups,$result,$courseopt) = @_;
1.275     raeburn  2089:     my $courseid = $env{'request.course.id'};
                   2090:     my $output;
                   2091:     my $symb = &symbcache($rid);
                   2092:     my $symbparm=$symb.'.'.$what;
                   2093:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.556     raeburn  2094:     my $recurseparm=$map.'___(rec).'.$what; 
1.275     raeburn  2095:     my $mapparm=$map.'___(all).'.$what;
                   2096:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype) =
1.556     raeburn  2097:           &parm_control_group($courseid,$usersgroups,$symbparm,$mapparm,
                   2098:                               $recurseparm,$what,$courseopt);
1.275     raeburn  2099:     my $bgcolor = $defbg;
1.582     raeburn  2100:     my ($grp_parm,$grp_is_rec);
1.446     bisitz   2101:     if (($coursereply) && ($cgroup ne $resultgroup)) {
1.582     raeburn  2102:         my ($parmname) = ($what =~ /\.([^.]+)$/);
1.275     raeburn  2103:         if ($result > 3) {
1.419     bisitz   2104:             $bgcolor = '#AAFFAA';
1.275     raeburn  2105:         }
1.593     raeburn  2106:         $grp_parm = &valout($coursereply,$resulttype);
1.419     bisitz   2107:         $output = '<td style="background-color:'.$bgcolor.';" align="center">';
1.275     raeburn  2108:         if ($resultgroup && $resultlevel) {
1.582     raeburn  2109:             if ($resultlevel eq 'recursive') {
                   2110:                 $resultlevel = 'map/folder';
                   2111:                 $grp_is_rec = 1;
                   2112:             }
                   2113:             $output .= '<small><b>'.$resultgroup.'</b> ('.$resultlevel.'): </small>'.$grp_parm.
                   2114:                        ($grp_is_rec?'<span class="LC_parm_recursive">'.&mt('recursive').'</span>':'');
                   2115:              
1.275     raeburn  2116:         } else {
                   2117:             $output .= '&nbsp;';
                   2118:         }
                   2119:         $output .= '</td>';
                   2120:     } else {
1.419     bisitz   2121:         $output .= '<td style="background-color:'.$bgcolor.';">&nbsp;</td>';
1.275     raeburn  2122:     }
1.582     raeburn  2123:     return ($coursereply,$output,$grp_parm,$resultgroup,$grp_is_rec);
1.275     raeburn  2124: }
                   2125: 
1.561     damieng  2126: # Looks for a group with a defined parameter for given user and parameter.
1.580     raeburn  2127: # Used by check_other_groups.
1.561     damieng  2128: #
                   2129: # @param {string} $courseid - the course id
                   2130: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2131: # @param {string} $symbparm - end of the course parameter hash key for the group resource level
                   2132: # @param {string} $mapparm - end of the course parameter hash key for the group map/folder level
                   2133: # @param {string} $recurseparm - end of the course parameter hash key for the group recursive level
                   2134: # @param {string} $what - parameter part.'.'.parameter name
                   2135: # @param {hash reference} $courseopt - course parameters hash
                   2136: # @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  2137: sub parm_control_group {
1.556     raeburn  2138:     my ($courseid,$usersgroups,$symbparm,$mapparm,$recurseparm,$what,$courseopt) = @_;
1.275     raeburn  2139:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   2140:     my $grpfound = 0;
1.556     raeburn  2141:     my @levels = ($symbparm,$mapparm,$recurseparm,$what);
                   2142:     my @levelnames = ('resource','map/folder','recursive','general');
1.275     raeburn  2143:     foreach my $group (@{$usersgroups}) {
                   2144:         if ($grpfound) { last; }
                   2145:         for (my $i=0; $i<@levels; $i++) {
                   2146:             my $item = $courseid.'.['.$group.'].'.$levels[$i];
                   2147:             if (defined($$courseopt{$item})) {
                   2148:                 $coursereply = $$courseopt{$item};
                   2149:                 $resultitem = $item;
                   2150:                 $resultgroup = $group;
                   2151:                 $resultlevel = $levelnames[$i];
                   2152:                 $resulttype = $$courseopt{$item.'.type'};
                   2153:                 $grpfound = 1;
                   2154:                 last;
                   2155:             }
                   2156:         }
                   2157:     }
                   2158:     return($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   2159: }
1.201     www      2160: 
1.63      bowersj2 2161: 
                   2162: 
1.562     damieng  2163: # Extracts lots of information about all of the the course's resources into a variety of hashes, using lonnavmaps and lonnet::metadata.
                   2164: # All the parameters are references and are filled by the sub.
                   2165: #
1.566     damieng  2166: # @param {array reference} $ids - resource and map ids
                   2167: # @param {hash reference} $typep - hash resource/map id -> resource type (file extension)
                   2168: # @param {hash reference} $keyp - hash resource/map id -> comma-separated list of parameter keys from lonnet::metadata
1.562     damieng  2169: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2170: # @param {hash reference} $allparts - hash parameter part -> part title (a parameter part can be problem part.'_'.response id for response parameters)
1.566     damieng  2171: # @param {hash reference} $allmaps - hash map pc -> map src
                   2172: # @param {hash reference} $mapp - hash map pc or resource/map id -> enclosing map src
                   2173: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' for a map or resource symb for a resource
                   2174: # @param {hash reference} $maptitles - hash map pc or src -> map title (this should really be two separate hashes)
                   2175: # @param {hash reference} $uris - hash resource/map id -> resource src
1.562     damieng  2176: # @param {hash reference} $keyorder - hash parameter key -> appearance rank for this parameter when looking through every resource and every parameter, starting at 100 (integer)
                   2177: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.608     raeburn  2178: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.63      bowersj2 2179: sub extractResourceInformation {
                   2180:     my $ids = shift;
                   2181:     my $typep = shift;
                   2182:     my $keyp = shift;
                   2183:     my $allparms = shift;
                   2184:     my $allparts = shift;
                   2185:     my $allmaps = shift;
                   2186:     my $mapp = shift;
                   2187:     my $symbp = shift;
1.82      www      2188:     my $maptitles=shift;
1.196     www      2189:     my $uris=shift;
1.210     www      2190:     my $keyorder=shift;
1.211     www      2191:     my $defkeytype=shift;
1.603     raeburn  2192:     my $pssymb=shift;
1.196     www      2193: 
1.210     www      2194:     my $keyordercnt=100;
1.63      bowersj2 2195: 
1.196     www      2196:     my $navmap = Apache::lonnavmaps::navmap->new();
1.603     raeburn  2197:     return unless(ref($navmap));
                   2198:     my @allres;
                   2199:     if ($pssymb ne '') {
                   2200:         my $res = $navmap->getBySymb($pssymb);
                   2201:         if (ref($res)) {
                   2202:             @allres = ($res);
                   2203:         }
                   2204:     }
                   2205:     if (!@allres) { 
                   2206:         @allres=$navmap->retrieveResources(undef,undef,1,undef,1);
                   2207:     }
1.196     www      2208:     foreach my $resource (@allres) {
1.480     amueller 2209:         my $id=$resource->id();
1.196     www      2210:         my ($mapid,$resid)=split(/\./,$id);
1.480     amueller 2211:         if ($mapid eq '0') { next; }
                   2212:         $$ids[$#$ids+1]=$id;
                   2213:         my $srcf=$resource->src();
                   2214:         $srcf=~/\.(\w+)$/;
                   2215:         $$typep{$id}=$1;
1.584     raeburn  2216:         my $toolsymb;
                   2217:         if ($srcf =~ /ext\.tool$/) {
                   2218:             $toolsymb = $resource->symb();
                   2219:         }
1.480     amueller 2220:         $$keyp{$id}='';
1.196     www      2221:         $$uris{$id}=$srcf;
1.512     foxr     2222: 
1.584     raeburn  2223:         foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys',$toolsymb))) {
1.480     amueller 2224:             next if ($key!~/^parameter_/);
1.363     albertel 2225: 
1.209     www      2226: # Hidden parameters
1.584     raeburn  2227:             next if (&Apache::lonnet::metadata($srcf,$key.'.hidden',$toolsymb) eq 'parm');
1.209     www      2228: #
                   2229: # allparms is a hash of parameter names
                   2230: #
1.584     raeburn  2231:             my $name=&Apache::lonnet::metadata($srcf,$key.'.name',$toolsymb);
1.480     amueller 2232:             if (!exists($$allparms{$name}) || $$allparms{$name} =~ m/^\s*$/ ) {
                   2233:                 my ($display,$parmdis);
                   2234:                 $display = &standard_parameter_names($name);
                   2235:                 if ($display eq '') {
1.584     raeburn  2236:                     $display= &Apache::lonnet::metadata($srcf,$key.'.display',$toolsymb);
1.480     amueller 2237:                     $parmdis = $display;
                   2238:                     $parmdis =~ s/\s*\[Part.*$//g;
                   2239:                 } else {
                   2240:                     $parmdis = &mt($display);
                   2241:                 }
                   2242:                 $$allparms{$name}=$parmdis;
                   2243:                 if (ref($defkeytype)) {
                   2244:                     $$defkeytype{$name}=
1.584     raeburn  2245:                     &Apache::lonnet::metadata($srcf,$key.'.type',$toolsymb);
1.480     amueller 2246:                 }
                   2247:             }
1.363     albertel 2248: 
1.209     www      2249: #
                   2250: # allparts is a hash of all parts
                   2251: #
1.584     raeburn  2252:             my $part= &Apache::lonnet::metadata($srcf,$key.'.part',$toolsymb);
1.480     amueller 2253:             $$allparts{$part} = &mt('Part: [_1]',$part);
1.209     www      2254: #
                   2255: # Remember all keys going with this resource
                   2256: #
1.480     amueller 2257:             if ($$keyp{$id}) {
                   2258:                 $$keyp{$id}.=','.$key;
                   2259:             } else {
                   2260:                 $$keyp{$id}=$key;
                   2261:             }   
1.210     www      2262: #
                   2263: # Put in order
1.446     bisitz   2264: #
1.480     amueller 2265:             unless ($$keyorder{$key}) {
                   2266:                 $$keyorder{$key}=$keyordercnt;
                   2267:                 $keyordercnt++;
                   2268:             }
1.473     amueller 2269:         }
                   2270: 
                   2271: 
1.480     amueller 2272:         if (!exists($$mapp{$mapid})) {
                   2273:             $$mapp{$id}=
                   2274:             &Apache::lonnet::declutter($resource->enclosing_map_src());
                   2275:             $$mapp{$mapid}=$$mapp{$id};
                   2276:             $$allmaps{$mapid}=$$mapp{$id};
                   2277:             if ($mapid eq '1') {
1.532     raeburn  2278:                 $$maptitles{$mapid}=&mt('Main Content');
1.480     amueller 2279:             } else {
                   2280:                 $$maptitles{$mapid}=&Apache::lonnet::gettitle($$mapp{$id});
                   2281:             }
                   2282:             $$maptitles{$$mapp{$id}}=$$maptitles{$mapid};
1.556     raeburn  2283:             $$symbp{$mapid}=$$mapp{$id}.'___(all)';  # Added in rev. 1.57, but seems not to be used.
                   2284:                                                      # Lines 1038 and 1114 which use $symbp{$mapid}
                   2285:                                                      # are commented out in rev. 1.57
1.473     amueller 2286:         } else {
1.480     amueller 2287:             $$mapp{$id} = $$mapp{$mapid};
1.473     amueller 2288:         }
1.480     amueller 2289:         $$symbp{$id}=&Apache::lonnet::encode_symb($$mapp{$id},$resid,$srcf);
1.63      bowersj2 2290:     }
                   2291: }
                   2292: 
1.582     raeburn  2293: sub get_recursive {
                   2294:     my ($recurseup,$resdata,$what,$prefix) = @_; 
                   2295:     if ((ref($resdata) eq 'HASH') && (ref($recurseup) eq 'ARRAY')) {
                   2296:         foreach my $item (@{$recurseup}) {
                   2297:             my $norecursechk=$prefix.'.'.$item.'___(all).'.$what;
                   2298:             if (defined($resdata->{$norecursechk})) {
                   2299:                 if ($what =~ /\.(encrypturl|hiddenresource)$/) {
                   2300:                     my $type = $resdata->{$norecursechk.'.type'};
                   2301:                     return [$resdata->{$norecursechk},$type,$item];
                   2302:                 } else {
                   2303:                     last;
                   2304:                 }
                   2305:             }
                   2306:             my $recursechk=$prefix.'.'.$item.'___(rec).'.$what;
                   2307:             if (defined($resdata->{$recursechk})) {
                   2308:                 my $type = $resdata->{$recursechk.'.type'};
                   2309:                 return [$resdata->{$recursechk},$type,$item];
                   2310:             }
                   2311:         }
                   2312:     }
                   2313:     return;
                   2314: }
                   2315: 
1.208     www      2316: 
1.562     damieng  2317: # Tells if a parameter type is a date.
                   2318: #
                   2319: # @param {string} type - parameter type
                   2320: # @returns{boolean} - true if it is a date
1.213     www      2321: sub isdateparm {
                   2322:     my $type=shift;
                   2323:     return (($type=~/^date/) && (!($type eq 'date_interval')));
                   2324: }
                   2325: 
1.589     raeburn  2326: # Determine if parameter type is specialized string type (i.e.,
                   2327: # not just string or string_yesno.  
                   2328: 
                   2329: sub is_specialstring {
                   2330:     my $type=shift;
1.603     raeburn  2331:     return (($type=~/^string_/) && ($type ne 'string_yesno'));
1.589     raeburn  2332: }
                   2333: 
1.562     damieng  2334: # Prints the HTML and Javascript to select parameters, with various shortcuts.
1.468     amueller 2335: #
1.581     raeburn  2336: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      2337: sub parmmenu {
1.581     raeburn  2338:     my ($r)=@_;
1.208     www      2339:     $r->print(<<ENDSCRIPT);
                   2340: <script type="text/javascript">
1.454     bisitz   2341: // <![CDATA[
1.208     www      2342:     function checkall(value, checkName) {
1.453     schualex 2343: 
                   2344:         var li = "_li";
                   2345:         var displayOverview = "";
                   2346:         
                   2347:         if (value == false) {
                   2348:             displayOverview = "none"
                   2349:         }
                   2350: 
1.562     damieng  2351:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.208     www      2352:             ele = document.forms.parmform.elements[i];
                   2353:             if (ele.name == checkName) {
                   2354:                 document.forms.parmform.elements[i].checked=value;
                   2355:             }
                   2356:         }
                   2357:     }
1.210     www      2358: 
                   2359:     function checkthis(thisvalue, checkName) {
1.562     damieng  2360:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.210     www      2361:             ele = document.forms.parmform.elements[i];
                   2362:             if (ele.name == checkName) {
1.562     damieng  2363:                 if (ele.value == thisvalue) {
                   2364:                     document.forms.parmform.elements[i].checked=true;
                   2365:                 }
1.210     www      2366:             }
                   2367:         }
                   2368:     }
                   2369: 
                   2370:     function checkdates() {
1.562     damieng  2371:         checkthis('duedate','pscat');
                   2372:         checkthis('opendate','pscat');
                   2373:         checkthis('answerdate','pscat');
1.218     www      2374:     }
                   2375: 
                   2376:     function checkdisset() {
1.562     damieng  2377:         checkthis('discussend','pscat');
                   2378:         checkthis('discusshide','pscat');
                   2379:         checkthis('discussvote','pscat');
1.218     www      2380:     }
                   2381: 
                   2382:     function checkcontdates() {
1.562     damieng  2383:         checkthis('contentopen','pscat');
                   2384:         checkthis('contentclose','pscat');
1.218     www      2385:     }
1.446     bisitz   2386: 
1.210     www      2387:     function checkvisi() {
1.562     damieng  2388:         checkthis('hiddenresource','pscat');
                   2389:         checkthis('encrypturl','pscat');
                   2390:         checkthis('problemstatus','pscat');
                   2391:         checkthis('contentopen','pscat');
                   2392:         checkthis('opendate','pscat');
1.210     www      2393:     }
                   2394: 
                   2395:     function checkparts() {
1.562     damieng  2396:         checkthis('hiddenparts','pscat');
                   2397:         checkthis('display','pscat');
                   2398:         checkthis('ordered','pscat');
1.210     www      2399:     }
                   2400: 
                   2401:     function checkstandard() {
                   2402:         checkall(false,'pscat');
1.562     damieng  2403:         checkdates();
                   2404:         checkthis('weight','pscat');
                   2405:         checkthis('maxtries','pscat');
                   2406:         checkthis('type','pscat');
                   2407:         checkthis('problemstatus','pscat');
1.210     www      2408:     }
                   2409: 
1.454     bisitz   2410: // ]]>
1.208     www      2411: </script>
                   2412: ENDSCRIPT
1.453     schualex 2413: 
1.491     bisitz   2414:     $r->print('<hr />');
1.581     raeburn  2415:     &shortCuts($r);
1.491     bisitz   2416:     $r->print('<hr />');
1.453     schualex 2417: }
1.562     damieng  2418: 
                   2419: # Returns parameter categories.
                   2420: #
                   2421: # @returns {hash} - category name -> title in English
1.465     amueller 2422: sub categories {
                   2423:     return ('time_settings' => 'Time Settings',
                   2424:     'grading' => 'Grading',
                   2425:     'tries' => 'Tries',
                   2426:     'problem_appearance' => 'Problem Appearance',
                   2427:     'behaviour_of_input_fields' => 'Behaviour of Input Fields',
                   2428:     'hiding' => 'Hiding',
                   2429:     'high_level_randomization' => 'High Level Randomization',
                   2430:     'slots' => 'Slots',
                   2431:     'file_submission' => 'File Submission',
                   2432:     'misc' => 'Miscellaneous' ); 
                   2433: }
                   2434: 
1.562     damieng  2435: # Returns the category for each parameter.
                   2436: #
                   2437: # @returns {hash} - parameter name -> category name
1.465     amueller 2438: sub lookUpTableParameter {
                   2439:  
                   2440:     return ( 
                   2441:         'opendate' => 'time_settings',
                   2442:         'duedate' => 'time_settings',
                   2443:         'answerdate' => 'time_settings',
                   2444:         'interval' => 'time_settings',
                   2445:         'contentopen' => 'time_settings',
                   2446:         'contentclose' => 'time_settings',
                   2447:         'discussend' => 'time_settings',
1.560     damieng  2448:         'printstartdate' => 'time_settings',
                   2449:         'printenddate' => 'time_settings',
1.465     amueller 2450:         'weight' => 'grading',
                   2451:         'handgrade' => 'grading',
                   2452:         'maxtries' => 'tries',
                   2453:         'hinttries' => 'tries',
1.503     raeburn  2454:         'randomizeontries' => 'tries',
1.465     amueller 2455:         'type' => 'problem_appearance',
                   2456:         'problemstatus' => 'problem_appearance',
                   2457:         'display' => 'problem_appearance',
                   2458:         'ordered' => 'problem_appearance',
                   2459:         'numbubbles' => 'problem_appearance',
                   2460:         'tol' => 'behaviour_of_input_fields',
                   2461:         'sig' => 'behaviour_of_input_fields',
                   2462:         'turnoffunit' => 'behaviour_of_input_fields',
                   2463:         'hiddenresource' => 'hiding',
                   2464:         'hiddenparts' => 'hiding',
                   2465:         'discusshide' => 'hiding',
                   2466:         'buttonshide' => 'hiding',
                   2467:         'turnoffeditor' => 'hiding',
                   2468:         'encrypturl' => 'hiding',
1.587     raeburn  2469:         'deeplink' => 'hiding',
1.465     amueller 2470:         'randomorder' => 'high_level_randomization',
                   2471:         'randompick' => 'high_level_randomization',
                   2472:         'available' => 'slots',
                   2473:         'useslots' => 'slots',
                   2474:         'availablestudent' => 'slots',
                   2475:         'uploadedfiletypes' => 'file_submission',
                   2476:         'maxfilesize' => 'file_submission',
                   2477:         'cssfile' => 'misc',
                   2478:         'mapalias' => 'misc',
                   2479:         'acc' => 'misc',
                   2480:         'maxcollaborators' => 'misc',
                   2481:         'scoreformat' => 'misc',
1.514     raeburn  2482:         'lenient' => 'grading',
1.519     raeburn  2483:         'retrypartial' => 'tries',
1.521     raeburn  2484:         'discussvote'  => 'misc',
1.621   ! raeburn  2485:         'texdisplay' => 'misc',
1.584     raeburn  2486:         'examcode' => 'high_level_randomization',
1.575     raeburn  2487:     );
1.465     amueller 2488: }
                   2489: 
1.562     damieng  2490: # Adds the given parameter name to an array of arrays listing all parameters for each category.
                   2491: #
                   2492: # @param {string} $name - parameter name
                   2493: # @param {array reference} $catList - array reference category name -> array reference of parameter names
1.465     amueller 2494: sub whatIsMyCategory {
                   2495:     my $name = shift;
                   2496:     my $catList = shift;
                   2497:     my @list;
                   2498:     my %lookUpList = &lookUpTableParameter; #Initilize the lookupList
                   2499:     my $cat = $lookUpList{$name};
                   2500:     if (defined($cat)) {
                   2501:         if (!defined($$catList{$cat})){
                   2502:             push @list, ($name);
                   2503:             $$catList{$cat} = \@list;
                   2504:         } else {
                   2505:             push @{${$catList}{$cat}}, ($name);     
                   2506:         }
                   2507:     } else {
                   2508:         if (!defined($$catList{'misc'})){
                   2509:             push @list, ($name);
                   2510:             $$catList{'misc'} = \@list;
                   2511:         } else {
                   2512:             push @{${$catList}{'misc'}}, ($name);     
                   2513:         }
                   2514:     }        
                   2515: }
                   2516: 
1.562     damieng  2517: # Sorts parameter names based on appearance order.
                   2518: #
                   2519: # @param {array reference} name - array reference of parameter names
                   2520: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2521: # @returns {Array} - array of parameter names
1.465     amueller 2522: sub keysindisplayorderCategory {
                   2523:     my ($name,$keyorder)=@_;
                   2524:     return sort {
1.473     amueller 2525:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b}; 
1.465     amueller 2526:     } ( @{$name});
                   2527: }
                   2528: 
1.562     damieng  2529: # Returns a hash category name -> order, starting at 1 (integer)
                   2530: #
                   2531: # @returns {hash}
1.467     amueller 2532: sub category_order {
                   2533:     return (
                   2534:         'time_settings' => 1,
                   2535:         'grading' => 2,
                   2536:         'tries' => 3,
                   2537:         'problem_appearance' => 4,
                   2538:         'hiding' => 5,
                   2539:         'behaviour_of_input_fields' => 6,
                   2540:         'high_level_randomization'  => 7,
                   2541:         'slots' => 8,
                   2542:         'file_submission' => 9,
                   2543:         'misc' => 10
                   2544:     );
                   2545: 
                   2546: }
1.453     schualex 2547: 
1.562     damieng  2548: # Prints HTML to let the user select parameters, from a list of all parameters organized by category.
                   2549: #
                   2550: # @param {Apache2::RequestRec} $r - the Apache request
                   2551: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2552: # @param {array reference} $pscat - list of selected parameter names
                   2553: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
1.453     schualex 2554: sub parmboxes {
                   2555:     my ($r,$allparms,$pscat,$keyorder)=@_;
1.548     raeburn  2556:     my %categories = &categories();
1.467     amueller 2557:     my %category_order = &category_order();
1.465     amueller 2558:     my %categoryList = (
                   2559:         'time_settings' => [],
                   2560:         'grading' => [],
                   2561:         'tries' => [],
                   2562:         'problem_appearance' => [],
                   2563:         'behaviour_of_input_fields' => [],
                   2564:         'hiding' => [],
                   2565:         'high_level_randomization' => [],
                   2566:         'slots' => [],
                   2567:         'file_submission' => [],
                   2568:         'misc' => [],
1.489     bisitz   2569:     );
1.510     www      2570: 
1.548     raeburn  2571:     foreach my $tempparameter (keys(%$allparms)) {
1.465     amueller 2572:         &whatIsMyCategory($tempparameter, \%categoryList);
                   2573:     }
1.453     schualex 2574:     #part to print the parm-list
1.618     raeburn  2575:     $Text::Wrap::columns=60;
                   2576:     $Text::Wrap::separator='<br />';
1.536     raeburn  2577:     foreach my $key (sort { $category_order{$a} <=> $category_order{$b} } keys(%categoryList)) {
                   2578:         next if (@{$categoryList{$key}} == 0);
                   2579:         next if ($key eq '');
                   2580:         $r->print('<div class="LC_Box LC_400Box">'
                   2581:                  .'<h4 class="LC_hcell">'.&mt($categories{$key}).'</h4>'."\n");
                   2582:         foreach my $tempkey (&keysindisplayorderCategory($categoryList{$key},$keyorder)) {
1.575     raeburn  2583:             next if ($tempkey eq '');
1.536     raeburn  2584:             $r->print('<span class="LC_nobreak">'
                   2585:                      .'<label><input type="checkbox" name="pscat" '
                   2586:                      .'value="'.$tempkey.'" ');
                   2587:             if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {
                   2588:                 $r->print( ' checked="checked"');
                   2589:             }
1.617     raeburn  2590:             $r->print(' />'.($$allparms{$tempkey}=~/\S/ ? 
                   2591:                              Text::Wrap::wrap('','&nbsp;'x4,$$allparms{$tempkey})
                   2592:                              : $tempkey)
1.536     raeburn  2593:                      .'</label></span><br />'."\n");
1.465     amueller 2594:         }
1.536     raeburn  2595:         $r->print('</div>');
1.465     amueller 2596:     }
1.536     raeburn  2597:     $r->print("\n");
1.453     schualex 2598: }
1.562     damieng  2599: 
                   2600: # Prints HTML with shortcuts to select groups of parameters in one click, or deselect all.
1.468     amueller 2601: #
1.562     damieng  2602: # @param {Apache2::RequestRec} $r - the Apache request
1.453     schualex 2603: sub shortCuts {
1.581     raeburn  2604:     my ($r)=@_;
1.453     schualex 2605: 
1.491     bisitz   2606:     # Parameter Selection
                   2607:     $r->print(
                   2608:         &Apache::lonhtmlcommon::start_funclist(&mt('Parameter Selection'))
                   2609:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2610:             '<a href="javascript:checkall(true, \'pscat\')">'.&mt('Select All').'</a>')
                   2611:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2612:             '<a href="javascript:checkstandard()">'.&mt('Select Common Only').'</a>')
                   2613:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2614:             '<a href="javascript:checkall(false, \'pscat\')">'.&mt('Unselect All').'</a>')
                   2615:        .&Apache::lonhtmlcommon::end_funclist()
                   2616:     );
                   2617: 
                   2618:     # Add Selection for...
                   2619:     $r->print(
                   2620:         &Apache::lonhtmlcommon::start_funclist(&mt('Add Selection for...'))
                   2621:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2622:             '<a href="javascript:checkdates()">'.&mt('Problem Dates').'</a>')
                   2623:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2624:             '<a href="javascript:checkcontdates()">'.&mt('Content Dates').'</a>')
                   2625:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2626:             '<a href="javascript:checkdisset()">'.&mt('Discussion Settings').'</a>')
                   2627:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2628:             '<a href="javascript:checkvisi()">'.&mt('Visibilities').'</a>')
                   2629:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2630:             '<a href="javascript:checkparts()">'.&mt('Part Parameters').'</a>')
                   2631:        .&Apache::lonhtmlcommon::end_funclist()
                   2632:     );
1.208     www      2633: }
                   2634: 
1.562     damieng  2635: # Prints HTML to select parts to view (except for the title).
                   2636: # Used by table and overview modes.
                   2637: #
                   2638: # @param {Apache2::RequestRec} $r - the Apache request
                   2639: # @param {hash reference} $allparts - hash parameter part -> part title
                   2640: # @param {array reference} $psprt - list of selected parameter parts
1.209     www      2641: sub partmenu {
1.446     bisitz   2642:     my ($r,$allparts,$psprt)=@_;
1.523     raeburn  2643:     my $selsize = 1+scalar(keys(%{$allparts}));
                   2644:     if ($selsize > 8) {
                   2645:         $selsize = 8;
                   2646:     }
1.446     bisitz   2647: 
1.523     raeburn  2648:     $r->print('<select multiple="multiple" name="psprt" size="'.$selsize.'">');
1.208     www      2649:     $r->print('<option value="all"');
1.562     damieng  2650:     $r->print(' selected="selected"') unless (@{$psprt}); # useless, the array is never empty
1.208     www      2651:     $r->print('>'.&mt('All Parts').'</option>');
                   2652:     my %temphash=();
                   2653:     foreach (@{$psprt}) { $temphash{$_}=1; }
1.234     albertel 2654:     foreach my $tempkey (sort {
1.560     damieng  2655:                 if ($a==$b) { return ($a cmp $b) } else { return ($a <=> $b); }
                   2656:             } keys(%{$allparts})) {
                   2657:         unless ($tempkey =~ /\./) {
                   2658:             $r->print('<option value="'.$tempkey.'"');
                   2659:             if ($$psprt[0] eq "all" ||  $temphash{$tempkey}) {
                   2660:                 $r->print(' selected="selected"');
                   2661:             }
                   2662:             $r->print('>'.$$allparts{$tempkey}.'</option>');
1.473     amueller 2663:         }
1.208     www      2664:     }
1.446     bisitz   2665:     $r->print('</select>');
1.209     www      2666: }
                   2667: 
1.562     damieng  2668: # Prints HTML to select a user and/or a group.
                   2669: # Used by table mode.
                   2670: #
                   2671: # @param {Apache2::RequestRec} $r - the Apache request
                   2672: # @param {string} $uname - selected user name
                   2673: # @param {string} $id - selected Student/Employee ID
                   2674: # @param {string} $udom - selected user domain
                   2675: # @param {string} $csec - selected section name
                   2676: # @param {string} $cgroup - selected group name
                   2677: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   2678: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2679: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.209     www      2680: sub usermenu {
1.553     raeburn  2681:     my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,$usersgroups,$pssymb)=@_;
1.209     www      2682:     my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.
1.596     raeburn  2683:                   &Apache::loncommon::selectstudent_link('parmform','uname','udom','condition').
                   2684:                   &Apache::lonhtmlcommon::scripttag(<<ENDJS);
                   2685: function setCourseadv(form,caller) {
                   2686:     if (caller.value == 'st') {
                   2687:         form.courseadv.value = 'none';
                   2688:     } else {
                   2689:         form.courseadv.value = '';
                   2690:     }
                   2691:     return;
                   2692: }
                   2693: ENDJS
1.412     bisitz   2694: 
1.596     raeburn  2695:     my (%chkroles,$stuonly,$courseadv);
                   2696:     if ($env{'form.userroles'} eq 'any') {
                   2697:         $chkroles{'any'} = ' checked="checked"';
                   2698:     } else {
                   2699:         $chkroles{'st'} = ' checked="checked"';
                   2700:         $courseadv = 'none';
                   2701:     }
                   2702:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   2703:     if ($crstype eq 'Community') {
                   2704:         $stuonly = &mt('member only');
                   2705:     } else {
                   2706:         $stuonly = &mt('student only');
                   2707:     }
                   2708:     $chooseopt .= '<br /><span class="LC_cusr_subheading">'.
                   2709:                   &mt("User's role").':&nbsp;'.
                   2710:                   '<label><input type="radio" name="userroles" value="st"'.$chkroles{'st'}.' onclick="setCourseadv(this.form,this);" />'.
                   2711:                   $stuonly.'</label>&nbsp;&nbsp;'.
                   2712:                   '<label><input type="radio" name="userroles" value="any"'.$chkroles{'any'}.' onclick="setCourseadv(this.form,this);" />'.
                   2713:                   &mt('any role').'</label><input type="hidden" id="courseadv" name="courseadv" value="'.$courseadv.'" /></span>';
1.209     www      2714:     my $sections='';
1.300     albertel 2715:     my %sectionhash = &Apache::loncommon::get_sections();
                   2716: 
1.269     raeburn  2717:     my $groups;
1.553     raeburn  2718:     my %grouphash;
                   2719:     if (($pssymb) || &Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2720:         %grouphash = &Apache::longroup::coursegroups();
                   2721:     } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  2722:         map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  2723:     }
1.299     albertel 2724: 
1.412     bisitz   2725:     my $g_s_header='';
                   2726:     my $g_s_footer='';
1.446     bisitz   2727: 
1.552     raeburn  2728:     my $currsec = $env{'request.course.sec'};
                   2729:     if ($currsec) {
                   2730:         $sections=&mt('Section:').' '.$currsec;
                   2731:         if (%grouphash) {
                   2732:             $sections .= ';'.('&nbsp;' x2);
                   2733:         }
                   2734:     } elsif (%sectionhash && $currsec eq '') {
1.412     bisitz   2735:         $sections=&mt('Section:').' <select name="csec"';
1.299     albertel 2736:         if (%grouphash && $parmlev ne 'full') {
1.269     raeburn  2737:             $sections .= qq| onchange="group_or_section('csec')" |;
                   2738:         }
                   2739:         $sections .= '>';
1.548     raeburn  2740:     foreach my $section ('',sort(keys(%sectionhash))) {
1.473     amueller 2741:         $sections.='<option value="'.$section.'" '.
                   2742:         ($section eq $csec?'selected="selected"':'').'>'.$section.
1.275     raeburn  2743:                                                               '</option>';
1.209     www      2744:         }
                   2745:         $sections.='</select>';
1.269     raeburn  2746:     }
1.412     bisitz   2747: 
1.552     raeburn  2748:     if (%sectionhash && %grouphash && $parmlev ne 'full' && $currsec eq '') {
1.412     bisitz   2749:         $sections .= '&nbsp;'.&mt('or').'&nbsp;';
1.269     raeburn  2750:         $sections .= qq|
                   2751: <script type="text/javascript">
1.454     bisitz   2752: // <![CDATA[
1.269     raeburn  2753: function group_or_section(caller) {
                   2754:    if (caller == "cgroup") {
                   2755:        if (document.parmform.cgroup.selectedIndex != 0) {
                   2756:            document.parmform.csec.selectedIndex = 0;
                   2757:        }
                   2758:    } else {
                   2759:        if (document.parmform.csec.selectedIndex != 0) {
                   2760:            document.parmform.cgroup.selectedIndex = 0;
                   2761:        }
                   2762:    }
                   2763: }
1.454     bisitz   2764: // ]]>
1.269     raeburn  2765: </script>
                   2766: |;
1.554     raeburn  2767:     } else {
1.269     raeburn  2768:         $sections .= qq|
                   2769: <script type="text/javascript">
1.454     bisitz   2770: // <![CDATA[
1.269     raeburn  2771: function group_or_section(caller) {
                   2772:     return;
                   2773: }
1.454     bisitz   2774: // ]]>
1.269     raeburn  2775: </script>
                   2776: |;
1.446     bisitz   2777:     }
1.299     albertel 2778: 
                   2779:     if (%grouphash) {
1.597     raeburn  2780:         $groups=&mt('Group').': <select name="cgroup"';
1.552     raeburn  2781:         if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
1.269     raeburn  2782:             $groups .= qq| onchange="group_or_section('cgroup')" |;
                   2783:         }
                   2784:         $groups .= '>';
1.548     raeburn  2785:         foreach my $grp ('',sort(keys(%grouphash))) {
1.275     raeburn  2786:             $groups.='<option value="'.$grp.'" ';
                   2787:             if ($grp eq $cgroup) {
                   2788:                 unless ((defined($uname)) && ($grp eq '')) {
                   2789:                     $groups .=  'selected="selected" ';
                   2790:                 }
                   2791:             } elsif (!defined($cgroup)) {
                   2792:                 if (@{$usersgroups} == 1) {
                   2793:                     if ($grp eq $$usersgroups[0]) {
                   2794:                         $groups .=  'selected="selected" ';
                   2795:                     }
                   2796:                 }
                   2797:             }
                   2798:             $groups .= '>'.$grp.'</option>';
1.269     raeburn  2799:         }
                   2800:         $groups.='</select>';
                   2801:     }
1.412     bisitz   2802: 
1.445     neumanie 2803:     if (%sectionhash || %grouphash) {
1.446     bisitz   2804:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Group/Section')));
                   2805:         $r->print($sections.$groups);
1.448     bisitz   2806:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.554     raeburn  2807:     } else {
                   2808:         $r->print($sections); 
1.445     neumanie 2809:     }
1.446     bisitz   2810: 
                   2811:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('User')));
1.443     neumanie 2812:     $r->print(&mt('For User [_1] or Student/Employee ID [_2] at Domain [_3]'
1.412     bisitz   2813:                  ,'<input type="text" value="'.$uname.'" size="12" name="uname" />'
                   2814:                  ,'<input type="text" value="'.$id.'" size="12" name="id" /> '
1.446     bisitz   2815:                  ,$chooseopt));
1.209     www      2816: }
                   2817: 
1.562     damieng  2818: # Prints HTML to select parameters from a list of all parameters.
                   2819: # Uses parmmenu and parmboxes.
                   2820: # Used by table and overview modes.
1.468     amueller 2821: #
1.562     damieng  2822: # @param {Apache2::RequestRec} $r - the Apache request
                   2823: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2824: # @param {array reference} $pscat - list of selected parameter names
                   2825: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2826: # @param {string} [$divid] - name used to give an id to the HTML element for the scroll box
1.209     www      2827: sub displaymenu {
1.581     raeburn  2828:     my ($r,$allparms,$pscat,$keyorder,$divid)=@_;
1.510     www      2829: 
1.445     neumanie 2830:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.510     www      2831:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameters to View')));
                   2832: 
1.581     raeburn  2833:     &parmmenu($r);
1.536     raeburn  2834:     $r->print(&Apache::loncommon::start_scrollbox('480px','440px','200px',$divid));
1.510     www      2835:     &parmboxes($r,$allparms,$pscat,$keyorder);
                   2836:     $r->print(&Apache::loncommon::end_scrollbox());
                   2837: 
                   2838:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.453     schualex 2839:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.510     www      2840:  
1.209     www      2841: }
                   2842: 
1.562     damieng  2843: # Prints HTML to select a map.
                   2844: # Used by table mode and overview mode.
                   2845: #
                   2846: # @param {Apache2::RequestRec} $r - the Apache request
1.566     damieng  2847: # @param {hash reference} $allmaps - hash map pc -> map src
                   2848: # @param {string} $pschp - selected map pc, or 'all'
1.562     damieng  2849: # @param {hash reference} $maptitles - hash map id or src -> map title
1.566     damieng  2850: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.610     raeburn  2851: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
1.445     neumanie 2852: sub mapmenu {
1.610     raeburn  2853:     my ($r,$allmaps,$pschp,$maptitles,$symbp,$parmlev)=@_;
1.468     amueller 2854:     my %allmaps_inverted = reverse %$allmaps;
1.461     neumanie 2855:     my $navmap = Apache::lonnavmaps::navmap->new();
                   2856:     my $tree=[];
                   2857:     my $treeinfo={};
                   2858:     if (defined($navmap)) {
1.499     raeburn  2859:         my $it=$navmap->getIterator(undef,undef,undef,1,1,undef);
1.461     neumanie 2860:         my $curRes;
                   2861:         my $depth = 0;
1.468     amueller 2862:         my %parent = ();
                   2863:         my $startcount = 5;
                   2864:         my $lastcontainer = $startcount;
                   2865: # preparing what is to show ...
1.461     neumanie 2866:         while ($curRes = $it->next()) {
                   2867:             if ($curRes == $it->BEGIN_MAP()) {
                   2868:                 $depth++;
1.468     amueller 2869:                 $parent{$depth}= $lastcontainer;
1.461     neumanie 2870:             }
                   2871:             if ($curRes == $it->END_MAP()) {
                   2872:                 $depth--;
1.468     amueller 2873:                 $lastcontainer = $parent{$depth};
1.461     neumanie 2874:             }
                   2875:             if (ref($curRes)) {
1.468     amueller 2876:                 my $symb = $curRes->symb();
                   2877:                 my $ressymb = $symb;
1.461     neumanie 2878:                 if (($curRes->is_sequence()) || ($curRes->is_page())) {
                   2879:                     my $type = 'sequence';
                   2880:                     if ($curRes->is_page()) {
                   2881:                         $type = 'page';
                   2882:                     }
                   2883:                     my $id= $curRes->id();
1.468     amueller 2884:                     my $srcf = $curRes->src();
                   2885:                     my $resource_name = &Apache::lonnet::gettitle($srcf);
                   2886:                     if(!exists($treeinfo->{$id})) {
                   2887:                         push(@$tree,$id);
1.473     amueller 2888:                         my $enclosing_map_folder = &Apache::lonnet::declutter($curRes->enclosing_map_src());        
1.468     amueller 2889:                         $treeinfo->{$id} = {
1.461     neumanie 2890:                                     depth => $depth,
                   2891:                                     type  => $type,
1.468     amueller 2892:                                     name  => $resource_name,
                   2893:                                     enclosing_map_folder => $enclosing_map_folder,
1.461     neumanie 2894:                                     };
1.462     neumanie 2895:                     }
1.461     neumanie 2896:                 }
                   2897:             }
                   2898:         }
1.462     neumanie 2899:     }
1.473     amueller 2900: # Show it ...    
1.610     raeburn  2901:     my $rowattr = ' id="mapmenu"';
                   2902:     if ($parmlev eq 'general') {
                   2903:         $rowattr .= ' style="display:none"';
                   2904:     }
                   2905:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Enclosing Map or Folder'),'','',$rowattr));
1.461     neumanie 2906:     if ((ref($tree) eq 'ARRAY') && (ref($treeinfo) eq 'HASH')) {
                   2907:         my $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.497     bisitz   2908:         my $whitespace =
                   2909:             '<img src="'
                   2910:            .&Apache::loncommon::lonhttpdurl('/adm/lonIcons/whitespace_21.gif')
                   2911:            .'" alt="" />';
                   2912: 
1.498     bisitz   2913:         # Info about selectable folders/maps
                   2914:         $r->print(
                   2915:             '<div class="LC_info">'
1.508     www      2916:            .&mt('You can only select maps and folders which have modifiable settings.')
                   2917:            .' '.&Apache::loncommon::help_open_topic('Parameter_Set_Folder') 
1.498     bisitz   2918:            .'</div>'
                   2919:         );
                   2920: 
1.536     raeburn  2921:         $r->print(&Apache::loncommon::start_scrollbox('700px','680px','400px','mapmenuscroll'));
1.523     raeburn  2922:         $r->print(&Apache::loncommon::start_data_table(undef,'mapmenuinner'));
1.497     bisitz   2923: 
1.498     bisitz   2924:         # Display row: "All Maps or Folders"
                   2925:         $r->print(
1.523     raeburn  2926:             &Apache::loncommon::start_data_table_row(undef,'picklevel')
1.498     bisitz   2927:            .'<td>'
                   2928:            .'<label>'
                   2929:            .'<input type="radio" name="pschp"'
1.497     bisitz   2930:         );
                   2931:         $r->print(' checked="checked"') if ($pschp eq 'all' || !$pschp);
1.498     bisitz   2932:         $r->print(
                   2933:             ' value="all" />&nbsp;'.$icon.'&nbsp;'
                   2934:            .&mt('All Maps or Folders')
                   2935:            .'</label>'
                   2936:            .'<hr /></td>'
                   2937:            .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2938:         );
1.497     bisitz   2939: 
1.532     raeburn  2940:         # Display row: "Main Content"
1.468     amueller 2941:         if (exists($$allmaps{1})) {
1.498     bisitz   2942:             $r->print(
                   2943:                 &Apache::loncommon::start_data_table_row()
                   2944:                .'<td>'
                   2945:                .'<label>'
                   2946:                .'<input type="radio" name="pschp" value="1"'
1.468     amueller 2947:             );
1.497     bisitz   2948:             $r->print(' checked="checked"') if ($pschp eq '1');
1.498     bisitz   2949:             $r->print(
                   2950:                 '/>&nbsp;'.$icon.'&nbsp;'
                   2951:                .$$maptitles{1}
                   2952:                .($$allmaps{1} !~/^uploaded/?' ['.$$allmaps{1}.']':'')
                   2953:                .'</label>'
                   2954:                .'</td>'
                   2955:                .&Apache::loncommon::end_data_table_row()
1.468     amueller 2956:             );
                   2957:         }
1.497     bisitz   2958: 
                   2959:         # Display rows for all course maps and folders
1.468     amueller 2960:         foreach my $id (@{$tree}) {
                   2961:             my ($mapid,$resid)=split(/\./,$id);
1.464     bisitz   2962:             # Indentation
1.468     amueller 2963:             my $depth = $treeinfo->{$id}->{'depth'};
1.464     bisitz   2964:             my $indent;
                   2965:             for (my $i = 0; $i < $depth; $i++) {
                   2966:                 $indent.= $whitespace;
                   2967:             }
1.461     neumanie 2968:             $icon =  '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.468     amueller 2969:             if ($treeinfo->{$id}->{'type'} eq 'page') {
1.461     neumanie 2970:                 $icon = '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" />';
                   2971:             }
1.468     amueller 2972:             my $symb_name = $$symbp{$id};
                   2973:             my ($front, $tail) = split (/___${resid}___/, $symb_name);
                   2974:             $symb_name = $tail;
1.498     bisitz   2975:             $r->print(
                   2976:                 &Apache::loncommon::start_data_table_row()
                   2977:                .'<td>'
                   2978:                .'<label>'
1.463     bisitz   2979:             );
1.498     bisitz   2980:             # Only offer radio button for folders/maps which can be parameterized
                   2981:             if ($allmaps_inverted{$symb_name}) {
                   2982:                 $r->print(
                   2983:                     '<input type ="radio" name="pschp"'
                   2984:                    .' value="'.$allmaps_inverted{$symb_name}.'"'
                   2985:                 );
                   2986:                 $r->print(' checked="checked"') if ($allmaps_inverted{$symb_name} eq $pschp);
                   2987:                 $r->print('/>');
                   2988:             } else {
                   2989:                 $r->print($whitespace);
1.461     neumanie 2990:             }
1.498     bisitz   2991:             $r->print(
                   2992:                 $indent.$icon.'&nbsp;'
                   2993:                .$treeinfo->{$id}->{name}
                   2994:                .($$allmaps{$mapid}!~/^uploaded/?' ['.$$allmaps{$mapid}.']':'')
                   2995:                .'</label>'
                   2996:                .'</td>'
                   2997:                .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2998:             );
1.461     neumanie 2999:         }
1.497     bisitz   3000: 
1.523     raeburn  3001:         $r->print(&Apache::loncommon::end_data_table().
                   3002:                   '<br style="line-height:2px;" />'.
                   3003:                   &Apache::loncommon::end_scrollbox());
1.209     www      3004:     }
                   3005: }
                   3006: 
1.563     damieng  3007: # Prints HTML to select the parameter level (resource, map/folder or course).
                   3008: # Used by table and overview modes.
                   3009: #
                   3010: # @param {Apache2::RequestRec} $r - the Apache request
                   3011: # @param {hash reference} $alllevs - all parameter levels, hash English title -> value
                   3012: # @param {string} $parmlev - selected level value (full|map|general), or ''
1.209     www      3013: sub levelmenu {
1.446     bisitz   3014:     my ($r,$alllevs,$parmlev)=@_;
                   3015: 
1.548     raeburn  3016:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameter Level').
                   3017:                                                 &Apache::loncommon::help_open_topic('Course_Parameter_Levels')));
1.474     amueller 3018:     $r->print('<select id="parmlev" name="parmlev" onchange="showHide_courseContent()">');
1.548     raeburn  3019:     foreach my $lev (reverse(sort(keys(%{$alllevs})))) {
                   3020:         $r->print('<option value="'.$$alllevs{$lev}.'"');
                   3021:         if ($parmlev eq $$alllevs{$lev}) {
                   3022:             $r->print(' selected="selected"');
                   3023:         }
                   3024:         $r->print('>'.&mt($lev).'</option>');
1.208     www      3025:     }
1.446     bisitz   3026:     $r->print("</select>");
1.208     www      3027: }
                   3028: 
1.211     www      3029: 
1.563     damieng  3030: # Returns HTML to select a section (with a select HTML element).
                   3031: # Used by overview mode.
                   3032: #
                   3033: # @param {array reference} $selectedsections - list of selected section ids
                   3034: # @returns {string}
1.211     www      3035: sub sectionmenu {
1.553     raeburn  3036:     my ($selectedsections)=@_;
1.300     albertel 3037:     my %sectionhash = &Apache::loncommon::get_sections();
1.553     raeburn  3038:     return '' if (!%sectionhash);
1.300     albertel 3039: 
1.552     raeburn  3040:     my (@possibles,$disabled);
                   3041:     if ($env{'request.course.sec'} ne '') {
                   3042:         @possibles = ($env{'request.course.sec'});
                   3043:         $selectedsections = [$env{'request.course.sec'}];
                   3044:         $disabled = ' disabled="disabled"';
                   3045:     } else {
                   3046:         @possibles = ('all',sort(keys(%sectionhash)));
                   3047:     }
1.553     raeburn  3048:     my $output = '<select name="Section" multiple="multiple" size="8"'.$disabled.'>';
1.552     raeburn  3049:     foreach my $s (@possibles) {
1.553     raeburn  3050:         $output .= '    <option value="'.$s.'"';
                   3051:         if ((@{$selectedsections}) && (grep(/^\Q$s\E$/,@{$selectedsections}))) {  
                   3052:             $output .= ' selected="selected"';
1.473     amueller 3053:         }
1.553     raeburn  3054:         $output .= '>'."$s</option>\n";
1.300     albertel 3055:     }
1.553     raeburn  3056:     $output .= "</select>\n";
                   3057:     return $output;
1.269     raeburn  3058: }
                   3059: 
1.563     damieng  3060: # Returns HTML to select a group (with a select HTML element).
                   3061: # Used by overview mode.
                   3062: #
                   3063: # @param {array reference} $selectedgroups - list of selected group names
                   3064: # @returns {string}
1.269     raeburn  3065: sub groupmenu {
1.553     raeburn  3066:     my ($selectedgroups)=@_;
                   3067:     my %grouphash;
                   3068:     if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   3069:         %grouphash = &Apache::longroup::coursegroups();
                   3070:     } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  3071:          map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  3072:     }
                   3073:     return '' if (!%grouphash);
1.299     albertel 3074: 
1.553     raeburn  3075:     my $output = '<select name="Group" multiple="multiple" size="8">';
1.299     albertel 3076:     foreach my $group (sort(keys(%grouphash))) {
1.553     raeburn  3077:         $output .= '    <option value="'.$group.'"';
                   3078:         if ((@{$selectedgroups}) && (grep(/^\Q$group\E$/,\@{$selectedgroups}))) {
                   3079:             $output .=  ' selected="selected"';
1.473     amueller 3080:         }
1.553     raeburn  3081:         $output .= '>'."$group</option>\n";
1.211     www      3082:     }
1.553     raeburn  3083:     $output .= "</select>\n";
                   3084:     return $output;
1.211     www      3085: }
                   3086: 
1.563     damieng  3087: # Returns an array with the given parameter split by comma.
                   3088: # Used by assessparms (table mode).
                   3089: #
                   3090: # @param {string} $keyp - the string to split
                   3091: # @returns {Array<string>}
1.210     www      3092: sub keysplit {
                   3093:     my $keyp=shift;
                   3094:     return (split(/\,/,$keyp));
                   3095: }
                   3096: 
1.563     damieng  3097: # Returns the keys in $name, sorted using $keyorder.
                   3098: # Parameters are sorted by key, which means they are sorted by part first, then by name.
                   3099: # Used by assessparms (table mode) for resource level.
                   3100: #
                   3101: # @param {hash reference} $name - parameter key -> parameter name
                   3102: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3103: # @returns {Array<string>}
1.210     www      3104: sub keysinorder {
                   3105:     my ($name,$keyorder)=@_;
                   3106:     return sort {
1.560     damieng  3107:         $$keyorder{$a} <=> $$keyorder{$b};
1.548     raeburn  3108:     } (keys(%{$name}));
1.210     www      3109: }
                   3110: 
1.563     damieng  3111: # Returns the keys in $name, sorted using $keyorder to sort parameters by name first, then by part.
                   3112: # Used by assessparms (table mode) for map and general levels.
                   3113: #
                   3114: # @param {hash reference} $name - parameter key -> parameter name
                   3115: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3116: # @returns {Array<string>}
1.236     albertel 3117: sub keysinorder_bytype {
                   3118:     my ($name,$keyorder)=@_;
                   3119:     return sort {
1.563     damieng  3120:         my $ta=(split('_',$a))[-1]; # parameter name
1.560     damieng  3121:         my $tb=(split('_',$b))[-1];
                   3122:         if ($$keyorder{'parameter_0_'.$ta} == $$keyorder{'parameter_0_'.$tb}) {
                   3123:             return ($a cmp $b);
                   3124:         }
                   3125:         $$keyorder{'parameter_0_'.$ta} <=> $$keyorder{'parameter_0_'.$tb};
1.548     raeburn  3126:     } (keys(%{$name}));
1.236     albertel 3127: }
                   3128: 
1.563     damieng  3129: # Returns the keys in $name, sorted using $keyorder to sort parameters by name.
                   3130: # Used by defaultsetter (parameter settings default actions).
                   3131: #
                   3132: # @param {hash reference} $name - hash parameter name -> parameter title
                   3133: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3134: # @returns {Array<string>}
1.211     www      3135: sub keysindisplayorder {
                   3136:     my ($name,$keyorder)=@_;
                   3137:     return sort {
1.560     damieng  3138:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.548     raeburn  3139:     } (keys(%{$name}));
1.211     www      3140: }
                   3141: 
1.563     damieng  3142: # Prints HTML with a choice to sort results by realm or student first.
                   3143: # Used by overview mode.
                   3144: #
                   3145: # @param {Apache2::RequestRec} $r - the Apache request
                   3146: # @param {string} $sortorder - realmstudent|studentrealm
1.608     raeburn  3147: # @param {string} $context - newoverview|overview
1.214     www      3148: sub sortmenu {
1.608     raeburn  3149:     my ($r,$sortorder,$context)=@_;
                   3150:     my %text;
                   3151:     if ($context eq 'newoverview') {
                   3152:         %text = &Apache::lonlocal::texthash (
                   3153:                    realmstudent => 'Sort by location in course first, then student (group/section)',
                   3154:                    studentrealm => 'Sort by student (group/section) first, then location in course',
                   3155:         );
                   3156:     } else {
                   3157:         %text = &Apache::lonlocal::texthash (
                   3158:                    realmstudent => 'Sort by realm first, then student (group/section)',
                   3159:                    studentrealm => 'Sort by student (group/section) first, then realm',
                   3160:         );
1.214     www      3161:     }
1.608     raeburn  3162:     my %sortchecked = (
                   3163:        realmstudent => ' checked="checked"',
                   3164:        studentrealm => '',
                   3165:     );
1.214     www      3166:     if ($sortorder eq 'studentrealm') {
1.608     raeburn  3167:         $sortchecked{'studentrealm'} = $sortchecked{'realmstudent'};
                   3168:         $sortchecked{'realmstudent'} = '';
                   3169:     }
                   3170:     foreach my $sorttype ('realmstudent','studentrealm') {
                   3171:         $r->print('<br /><label><input type="radio" name="sortorder" value="'.$sorttype.'"'.$sortchecked{$sorttype}.' />'.
                   3172:                   $text{$sorttype}.'</label>');
1.214     www      3173:     }
                   3174: }
                   3175: 
1.563     damieng  3176: # Returns a hash parameter key -> order (integer) giving the order for some parameters.
                   3177: #
                   3178: # @returns {hash}
1.211     www      3179: sub standardkeyorder {
                   3180:     return ('parameter_0_opendate' => 1,
1.473     amueller 3181:         'parameter_0_duedate' => 2,
                   3182:         'parameter_0_answerdate' => 3,
                   3183:         'parameter_0_interval' => 4,
                   3184:         'parameter_0_weight' => 5,
                   3185:         'parameter_0_maxtries' => 6,
                   3186:         'parameter_0_hinttries' => 7,
                   3187:         'parameter_0_contentopen' => 8,
                   3188:         'parameter_0_contentclose' => 9,
                   3189:         'parameter_0_type' => 10,
                   3190:         'parameter_0_problemstatus' => 11,
                   3191:         'parameter_0_hiddenresource' => 12,
                   3192:         'parameter_0_hiddenparts' => 13,
                   3193:         'parameter_0_display' => 14,
                   3194:         'parameter_0_ordered' => 15,
                   3195:         'parameter_0_tol' => 16,
                   3196:         'parameter_0_sig' => 17,
                   3197:         'parameter_0_turnoffunit' => 18,
1.521     raeburn  3198:         'parameter_0_discussend' => 19,
                   3199:         'parameter_0_discusshide' => 20,
                   3200:         'parameter_0_discussvote' => 21,
1.560     damieng  3201:         'parameter_0_printstartdate'  =>  22,
                   3202:         'parameter_0_printenddate' =>  23);
1.211     www      3203: }
                   3204: 
1.59      matthew  3205: 
1.560     damieng  3206: # Table mode UI.
1.563     damieng  3207: # If nothing is selected, prints HTML forms to select resources, parts, parameters, user, group and section.
                   3208: # Otherwise, prints the parameter table, with a link to change the selection unless a single resource is selected.
                   3209: #
                   3210: # Parameters used from the request:
                   3211: # action - handler action (see handler), usermenu is checking for value 'settable'
                   3212: # cgroup - selected group
                   3213: # command - 'set': direct access to table mode for a resource
                   3214: # csec - selected section
                   3215: # dis - set when the "Update Display" button was used, used only to discard command 'set'
                   3216: # hideparmsel - can be 'hidden' to hide the parameter selection div initially and display the "Change Parameter Selection" link instead (which displays the div)
                   3217: # id - student/employee ID
                   3218: # parmlev - selected level (full|map|general)
                   3219: # part - selected part (unused ?)
                   3220: # pres_marker - &&&-separated parameter identifiers, "resource id&part_parameter name&level"
                   3221: # pres_type - &&&-separated parameter types
                   3222: # pres_value - &&&-separated parameter values
                   3223: # prevvisit - '1' if the user has submitted the form before
                   3224: # pscat (multiple values) - selected parameter names
1.566     damieng  3225: # pschp - selected map pc, or 'all'
1.563     damieng  3226: # psprt (multiple values) - list of selected parameter parts
                   3227: # filter - part of or whole parameter name, to be filtered out when parameters are displayed (unused ?)
                   3228: # recent_* (* = parameter type) - recent values entered by the user for parameter types
                   3229: # symb - resource symb (when a single resource is selected)
                   3230: # udom - selected user domain
                   3231: # uname - selected user name
                   3232: # url - used only with command 'set', the resource url
                   3233: #
                   3234: # @param {Apache2::RequestRec} $r - the Apache request
1.568     raeburn  3235: # @param $parm_permission - ref to hash of permissions
                   3236: #                           if $parm_permission->{'edit'} is true, editing is allowed.
1.30      www      3237: sub assessparms {
1.1       www      3238: 
1.568     raeburn  3239:     my ($r,$parm_permission) = @_;
1.201     www      3240: 
1.512     foxr     3241: 
                   3242: # -------------------------------------------------------- Variable declaration
1.566     damieng  3243:     my @ids=(); # resource and map ids
                   3244:     my %symbp=(); # hash map pc or resource/map id -> map src.'___(all)' or resource symb
                   3245:     my %mapp=(); # hash map pc or resource/map id -> enclosing map src
                   3246:     my %typep=(); # hash resource/map id -> resource type (file extension)
                   3247:     my %keyp=(); # hash resource/map id -> comma-separated list of parameter keys
                   3248:     my %uris=(); # hash resource/map id -> resource src
                   3249:     my %maptitles=(); # hash map pc or src -> map title
                   3250:     my %allmaps=(); # hash map pc -> map src
1.582     raeburn  3251:     my %allmaps_inverted=(); # hash map src -> map pc
1.563     damieng  3252:     my %alllevs=(); # hash English level title -> value
                   3253: 
                   3254:     my $uname; # selected user name
                   3255:     my $udom; # selected user domain
                   3256:     my $uhome; # server with the user's files, or 'no_host'
                   3257:     my $csec; # selected section name
                   3258:     my $cgroup; # selected group name
                   3259:     my @usersgroups = (); # list of the user groups
1.582     raeburn  3260:     my $numreclinks = 0;
1.446     bisitz   3261: 
1.190     albertel 3262:     my $coursename=$env{'course.'.$env{'request.course.id'}.'.description'};
1.187     www      3263: 
1.57      albertel 3264:     $alllevs{'Resource Level'}='full';
1.215     www      3265:     $alllevs{'Map/Folder Level'}='map';
1.57      albertel 3266:     $alllevs{'Course Level'}='general';
                   3267: 
1.563     damieng  3268:     my %allparms; # hash parameter name -> parameter title
                   3269:     my %allparts; # hash parameter part -> part title
1.512     foxr     3270: # ------------------------------------------------------------------------------
                   3271: 
1.210     www      3272: #
                   3273: # Order in which these parameters will be displayed
                   3274: #
1.211     www      3275:     my %keyorder=&standardkeyorder();
                   3276: 
1.512     foxr     3277: #    @ids=();
                   3278: #    %symbp=();       # These seem defined above already.
                   3279: #    %typep=();
1.43      albertel 3280: 
                   3281:     my $message='';
                   3282: 
1.190     albertel 3283:     $csec=$env{'form.csec'};
1.552     raeburn  3284:     if ($env{'request.course.sec'} ne '') {
                   3285:         $csec = $env{'request.course.sec'};    
                   3286:     }
                   3287: 
1.553     raeburn  3288: # Check group privs.
1.269     raeburn  3289:     $cgroup=$env{'form.cgroup'};
1.553     raeburn  3290:     my $noeditgrp; 
                   3291:     if ($cgroup ne '') {
                   3292:         unless (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   3293:             if (($env{'request.course.groups'} eq '') || 
1.585     raeburn  3294:                 (!grep(/^\Q$cgroup\E$/,split(/:/,$env{'request.course.groups'})))) {
1.553     raeburn  3295:                 $noeditgrp = 1;
                   3296:             }
                   3297:         }
                   3298:     }
1.188     www      3299: 
1.190     albertel 3300:     if      ($udom=$env{'form.udom'}) {
                   3301:     } elsif ($udom=$env{'request.role.domain'}) {
                   3302:     } elsif ($udom=$env{'user.domain'}) {
1.172     albertel 3303:     } else {
1.473     amueller 3304:         $udom=$r->dir_config('lonDefDomain');
1.172     albertel 3305:     }
1.468     amueller 3306:     
1.43      albertel 3307: 
1.134     albertel 3308:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
1.190     albertel 3309:     my $pschp=$env{'form.pschp'};
1.506     www      3310: 
                   3311: 
1.134     albertel 3312:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      3313:     if (!@psprt) { $psprt[0]='all'; }
1.506     www      3314:     if (($env{'form.part'}) && ($psprt[0] ne 'all')) { $psprt[0]=$env{'form.part'}; }
1.57      albertel 3315: 
1.43      albertel 3316:     my $pssymb='';
1.57      albertel 3317:     my $parmlev='';
1.446     bisitz   3318: 
1.190     albertel 3319:     unless ($env{'form.parmlev'}) {
1.57      albertel 3320:         $parmlev = 'map';
                   3321:     } else {
1.190     albertel 3322:         $parmlev = $env{'form.parmlev'};
1.57      albertel 3323:     }
1.26      www      3324: 
1.29      www      3325: # ----------------------------------------------- Was this started from grades?
                   3326: 
1.560     damieng  3327:     if (($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   3328:             (!$env{'form.dis'})) {
1.473     amueller 3329:         my $url=$env{'form.url'};
                   3330:         $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
                   3331:         $pssymb=&Apache::lonnet::symbread($url);
                   3332:         if (!@pscat) { @pscat=('all'); }
                   3333:         $pschp='';
1.57      albertel 3334:         $parmlev = 'full';
1.190     albertel 3335:     } elsif ($env{'form.symb'}) {
1.473     amueller 3336:         $pssymb=$env{'form.symb'};
                   3337:         if (!@pscat) { @pscat=('all'); }
                   3338:         $pschp='';
1.57      albertel 3339:         $parmlev = 'full';
1.43      albertel 3340:     } else {
1.473     amueller 3341:         $env{'form.url'}='';
1.43      albertel 3342:     }
                   3343: 
1.190     albertel 3344:     my $id=$env{'form.id'};
1.43      albertel 3345:     if (($id) && ($udom)) {
1.555     raeburn  3346:         $uname=(&Apache::lonnet::idget($udom,[$id],'ids'))[1];
1.473     amueller 3347:         if ($uname) {
                   3348:             $id='';
                   3349:         } else {
                   3350:             $message=
1.540     bisitz   3351:                 '<p class="LC_warning">'.
                   3352:                 &mt('Unknown ID [_1] at domain [_2]',
                   3353:                     "'".$id."'","'".$udom."'").
                   3354:                 '</p>';
1.473     amueller 3355:         }
1.43      albertel 3356:     } else {
1.473     amueller 3357:         $uname=$env{'form.uname'};
1.43      albertel 3358:     }
                   3359:     unless ($udom) { $uname=''; }
                   3360:     $uhome='';
                   3361:     if ($uname) {
1.473     amueller 3362:         $uhome=&Apache::lonnet::homeserver($uname,$udom);
1.43      albertel 3363:         if ($uhome eq 'no_host') {
1.473     amueller 3364:             $message=
1.540     bisitz   3365:                 '<p class="LC_warning">'.
                   3366:                 &mt('Unknown user [_1] at domain [_2]',
                   3367:                     "'".$uname."'","'".$udom."'").
                   3368:                 '</p>';
1.473     amueller 3369:             $uname='';
1.12      www      3370:         } else {
1.473     amueller 3371:             $csec=&Apache::lonnet::getsection($udom,$uname,
                   3372:                           $env{'request.course.id'});
                   3373:             if ($csec eq '-1') {
1.596     raeburn  3374:                 my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   3375:                 if ($env{'form.userroles'} eq 'any') {
                   3376:                     if (($env{'user.name'} eq $uname) && ($env{'user.domain'} eq $udom)) {
                   3377:                         $csec = $env{'request.course.sec'};
                   3378:                         $message = '<span class="LC_info">';
                   3379:                         if ($crstype eq 'Community') {
                   3380:                             $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
                   3381:                                             $uname,$udom);
                   3382:                         } else {
                   3383:                             $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
                   3384:                                             $uname,$udom);
                   3385:                         }
                   3386:                         $message .= '</span>';
                   3387:                     } else {
                   3388:                         my @possroles = ('in','ep','ta','cr');
                   3389:                         if ($crstype eq 'Community') {
                   3390:                             unshift(@possroles,'co');
                   3391:                         } else {
                   3392:                             unshift(@possroles,'cc');
                   3393:                         }
                   3394:                         my %not_student_roles =
                   3395:                             &Apache::lonnet::get_my_roles($uname,$udom,'userroles',['active'],
                   3396:                                                           \@possroles,[$udom],1,1);
                   3397:                         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   3398:                         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   3399:                         my %sections_by_role;
                   3400:                         foreach my $role (keys(%not_student_roles)) {
                   3401:                             if ($role =~ /^\Q$cnum:$cdom:\E([^:]+):(|[^:]+)$/) {
                   3402:                                 my ($rolename,$sec) = ($1,$2);
                   3403:                                 if ($rolename =~ m{^cr/}) {
                   3404:                                     $rolename = 'cr';
                   3405:                                 }
                   3406:                                 push(@{$sections_by_role{$rolename}},$sec);
                   3407:                             }
                   3408:                         }
                   3409:                         my $numroles = scalar(keys(%sections_by_role));
                   3410:                         if ($numroles) {
                   3411:                             foreach my $role (@possroles) {
                   3412:                                 if (ref($sections_by_role{$role}) eq 'ARRAY') {
                   3413:                                     my @secs = sort { $a <=> $b } @{$sections_by_role{$role}};
                   3414:                                     $csec = $secs[0];
                   3415:                                     last;
                   3416:                                 }
                   3417:                             }
                   3418:                         }
                   3419:                         if ($csec eq '-1') {
                   3420:                             $message = '<span class="LC_warning">';
                   3421:                             if ($crstype eq 'Community') {
                   3422:                                 $message .= &mt('User [_1] at domain [_2] does not have a role in this community',
                   3423:                                                 $uname,$udom);
                   3424:                             } else {
                   3425:                                 $message .= &mt('User [_1] at domain [_2] does not have a role in this course',
                   3426:                                                 $uname,$udom);
                   3427:                             }
                   3428:                             $message .= '</span>';
                   3429:                             $uname='';
                   3430:                             if ($env{'request.course.sec'} ne '') {
                   3431:                                 $csec=$env{'request.course.sec'};
                   3432:                             } else {
                   3433:                                 $csec=$env{'form.csec'};
                   3434:                             }
                   3435:                             $cgroup=$env{'form.cgroup'};
                   3436:                         } else {
                   3437:                             $message = '<span class="LC_info">';
                   3438:                             if ($crstype eq 'Community') {
                   3439:                                 $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
                   3440:                                          $uname,$udom);
                   3441:                             } else {
                   3442:                                 $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
                   3443:                                                 $uname,$udom);
                   3444:                             }
                   3445:                             $message .= '</span>';
                   3446:                         }
                   3447:                     }
1.594     raeburn  3448:                 } else {
1.596     raeburn  3449:                     $message = '<span class="LC_warning">';
                   3450:                     if ($crstype eq 'Community') {
                   3451:                         $message .= &mt('User [_1] at domain [_2] does not have a member role in this community',
                   3452:                                          $uname,$udom);
                   3453:                     } else {
                   3454:                          $message .= &mt('User [_1] at domain [_2] does not have a student role in this course',
                   3455:                                          $uname,$udom);
                   3456:                     }
                   3457:                     $message .= '</span>';
                   3458:                     $uname='';
                   3459:                     if ($env{'request.course.sec'} ne '') {
                   3460:                         $csec=$env{'request.course.sec'};
                   3461:                     } else {
                   3462:                         $csec=$env{'form.csec'};
                   3463:                     }
                   3464:                     $cgroup=$env{'form.cgroup'};
1.594     raeburn  3465:                 }
                   3466:             } elsif ($env{'request.course.sec'} ne '') {
                   3467:                 if ($csec ne $env{'request.course.sec'}) {
1.596     raeburn  3468:                     $message='<span class="LC_warning">'.
1.594     raeburn  3469:                               &mt("User '[_1]' at domain '[_2]' not in section '[_3]'",
                   3470:                                   $uname,$udom,$env{'request.course.sec'}).
                   3471:                               '</span>';
                   3472:                     $uname='';
                   3473:                     $csec=$env{'request.course.sec'};
                   3474:                 }
1.269     raeburn  3475:                 $cgroup=$env{'form.cgroup'};
1.596     raeburn  3476:             }
                   3477:             if ($uname ne '') {
1.473     amueller 3478:                 my %name=&Apache::lonnet::userenvironment($udom,$uname,
                   3479:                   ('firstname','middlename','lastname','generation','id'));
1.596     raeburn  3480:                 $message .= "\n<p>\n".&mt('Full Name').': '
                   3481:                             .$name{'firstname'}.' '.$name{'middlename'}.' '
                   3482:                             .$name{'lastname'}.' '.$name{'generation'}
                   3483:                             ."<br />\n".&mt('Student/Employee ID').': '.$name{'id'}.'</p>';
                   3484:                 @usersgroups = &Apache::lonnet::get_users_groups(
                   3485:                                    $udom,$uname,$env{'request.course.id'});
                   3486:                 if (@usersgroups > 0) {
                   3487:                     unless (grep(/^\Q$cgroup\E$/,@usersgroups)) {
                   3488:                         $cgroup = $usersgroups[0];
                   3489:                     }
                   3490:                 } else {
                   3491:                     $cgroup = '';
1.297     raeburn  3492:                 }
1.269     raeburn  3493:             }
1.12      www      3494:         }
1.43      albertel 3495:     }
1.2       www      3496: 
1.43      albertel 3497:     unless ($csec) { $csec=''; }
1.269     raeburn  3498:     unless ($cgroup) { $cgroup=''; }
1.12      www      3499: 
1.14      www      3500: # --------------------------------------------------------- Get all assessments
1.446     bisitz   3501:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 3502:                 \%mapp, \%symbp,\%maptitles,\%uris,
1.603     raeburn  3503:                 \%keyorder,undef,$pssymb);
1.63      bowersj2 3504: 
1.582     raeburn  3505:     %allmaps_inverted = reverse(%allmaps);
                   3506: 
1.57      albertel 3507:     $mapp{'0.0'} = '';
                   3508:     $symbp{'0.0'} = '';
1.99      albertel 3509: 
1.14      www      3510: # ---------------------------------------------------------- Anything to store?
1.568     raeburn  3511:     if ($env{'form.pres_marker'} && $parm_permission->{'edit'}) {
1.205     www      3512:         my @markers=split(/\&\&\&/,$env{'form.pres_marker'});
                   3513:         my @values=split(/\&\&\&/,$env{'form.pres_value'});
                   3514:         my @types=split(/\&\&\&/,$env{'form.pres_type'});
1.500     raeburn  3515:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   3516:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.504     raeburn  3517:         my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   3518:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   3519:         my $totalstored = 0;
1.605     raeburn  3520:         my $totalskippeduser = 0;
1.546     raeburn  3521:         my $now = time;
1.473     amueller 3522:         for (my $i=0;$i<=$#markers;$i++) {
1.557     raeburn  3523:             my ($needsrelease,$needsnewer,$name,$namematch);
1.556     raeburn  3524:             if (($env{'request.course.sec'} ne '') && ($markers[$i] =~ /\&(9|10|11|12)$/)) {
1.552     raeburn  3525:                 next if ($csec ne $env{'request.course.sec'});
                   3526:             }
1.556     raeburn  3527:             if ($markers[$i] =~ /\&(8|7|6|5)$/) {
1.553     raeburn  3528:                 next if ($noeditgrp);
1.605     raeburn  3529:             } elsif ($markers[$i] =~ /\&(4|3|2|1)$/) {
                   3530:                 if ($uname eq '') {
                   3531:                     $totalskippeduser ++;
                   3532:                     next;
                   3533:                 }
1.557     raeburn  3534:             }
                   3535:             if ($markers[$i] =~ /\&(17|11|7|3)$/) {
                   3536:                 $namematch = 'maplevelrecurse';
                   3537:             }
1.556     raeburn  3538:             if ($markers[$i] =~ /^[\d.]+\&0_availablestudent\&(1|2|3|4)$/) {
1.437     raeburn  3539:                 my (@ok_slots,@fail_slots,@del_slots);
                   3540:                 my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
                   3541:                 my ($level,@all) =
                   3542:                     &parmval_by_symb('0.availablestudent',$pssymb,'',$uname,$udom,
                   3543:                                      $csec,$cgroup,$courseopt);
                   3544:                 foreach my $slot_name (split(/:/,$values[$i])) {
                   3545:                     next if ($slot_name eq '');
                   3546:                     if (&update_slots($slot_name,$cdom,$cnum,$pssymb,$uname,$udom) eq 'ok') {
                   3547:                         push(@ok_slots,$slot_name);
                   3548: 
                   3549:                     } else {
                   3550:                         push(@fail_slots,$slot_name);
                   3551:                     }
                   3552:                 }
                   3553:                 if (@ok_slots) {
                   3554:                     $values[$i] = join(':',@ok_slots);
                   3555:                 } else {
                   3556:                     $values[$i] = '';
                   3557:                 }
                   3558:                 if ($all[$level] ne '') {
                   3559:                     my @existing = split(/:/,$all[$level]);
                   3560:                     foreach my $slot_name (@existing) {
                   3561:                         if (!grep(/^\Q$slot_name\E$/,split(/:/,$values[$i]))) {
                   3562:                             if (&delete_slots($slot_name,$cdom,$cnum,$uname,$udom,$pssymb) eq 'ok') {
                   3563:                                 push(@del_slots,$slot_name);
                   3564:                             }
                   3565:                         }
                   3566:                     }
                   3567:                 }
1.554     raeburn  3568:             } elsif ($markers[$i] =~ /_(type|lenient|retrypartial|discussvote|examcode|printstartdate|printenddate|acc|interval)\&\d+$/) {
1.514     raeburn  3569:                 $name = $1;
1.533     raeburn  3570:                 my $val = $values[$i];
1.549     raeburn  3571:                 my $valmatch = '';
1.533     raeburn  3572:                 if ($name eq 'examcode') {
1.544     raeburn  3573:                     if (&Apache::lonnet::validCODE($values[$i])) {
                   3574:                         $val = 'valid';
                   3575:                     }
1.546     raeburn  3576:                 } elsif ($name eq 'printstartdate') {
                   3577:                     if ($val =~ /^\d+$/) {
                   3578:                         if ($val > $now) {
                   3579:                             $val = 'future';
                   3580:                         }
                   3581:                     } 
                   3582:                 } elsif ($name eq 'printenddate') {
                   3583:                     if ($val =~ /^\d+$/) {
                   3584:                         if ($val < $now) {
                   3585:                             $val = 'past';
                   3586:                         }
                   3587:                     }
1.549     raeburn  3588:                 } elsif (($name eq 'lenient') || ($name eq 'acc')) {
                   3589:                     my $stringtype = &get_stringtype($name);
                   3590:                     my $stringmatch = &standard_string_matches($stringtype);
                   3591:                     if (ref($stringmatch) eq 'ARRAY') {
                   3592:                         foreach my $item (@{$stringmatch}) {
                   3593:                             if (ref($item) eq 'ARRAY') {
                   3594:                                 my ($regexpname,$pattern) = @{$item};
                   3595:                                 if ($pattern ne '') {
                   3596:                                     if ($val =~ /$pattern/) {
                   3597:                                         $valmatch = $regexpname;
                   3598:                                         $val = '';
                   3599:                                         last;
                   3600:                                     }
                   3601:                                 }
                   3602:                             }
                   3603:                         }
                   3604:                     }
1.554     raeburn  3605:                 } elsif ($name eq 'interval') {
                   3606:                     my $intervaltype = &get_intervaltype($name);
                   3607:                     my $intervalmatch = &standard_interval_matches($intervaltype);
                   3608:                     if (ref($intervalmatch) eq 'ARRAY') {
                   3609:                         foreach my $item (@{$intervalmatch}) {
                   3610:                             if (ref($item) eq 'ARRAY') {
                   3611:                                 my ($regexpname,$pattern) = @{$item};
                   3612:                                 if ($pattern ne '') {
                   3613:                                     if ($val =~ /$pattern/) {
                   3614:                                         $valmatch = $regexpname;
                   3615:                                         $val = '';
                   3616:                                         last;
                   3617:                                     }
                   3618:                                 }
                   3619:                             }
                   3620:                         }
                   3621:                     }
1.533     raeburn  3622:                 }
1.504     raeburn  3623:                 $needsrelease =
1.557     raeburn  3624:                     $Apache::lonnet::needsrelease{"parameter:$name:$val:$valmatch:"};
1.504     raeburn  3625:                 if ($needsrelease) {
1.505     raeburn  3626:                     unless ($got_chostname) {
1.514     raeburn  3627:                         ($chostname,$cmajor,$cminor) = &parameter_release_vars();
1.504     raeburn  3628:                         $got_chostname = 1;
1.546     raeburn  3629:                     } 
1.557     raeburn  3630:                     $needsnewer = &parameter_releasecheck($name,$val,$valmatch,undef,
1.514     raeburn  3631:                                                           $needsrelease,
                   3632:                                                           $cmajor,$cminor);
1.500     raeburn  3633:                 }
1.437     raeburn  3634:             }
1.504     raeburn  3635:             if ($needsnewer) {
1.557     raeburn  3636:                 undef($namematch);
                   3637:             } else {
                   3638:                 my $currneeded;
                   3639:                 if ($needsrelease) {
                   3640:                     $currneeded = $needsrelease;
                   3641:                 }
                   3642:                 if ($namematch) {
                   3643:                     $needsrelease =
                   3644:                         $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   3645:                     if (($needsrelease) && (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   3646:                         unless ($got_chostname) {
                   3647:                             ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   3648:                             $got_chostname = 1;
                   3649:                         }
                   3650:                         $needsnewer = &parameter_releasecheck(undef,undef,undef,$namematch,
                   3651:                                                               $needsrelease,
                   3652:                                                               $cmajor,$cminor);
                   3653:                     } else {
                   3654:                         undef($namematch);
                   3655:                     }
                   3656:                 }
                   3657:             }
                   3658:             if ($needsnewer) {
                   3659:                 $message .= &oldversion_warning($name,$namematch,$values[$i],$chostname,$cmajor,
1.504     raeburn  3660:                                                 $cminor,$needsrelease);
                   3661:             } else {
                   3662:                 $message.=&storeparm(split(/\&/,$markers[$i]),
                   3663:                                      $values[$i],
                   3664:                                      $types[$i],
                   3665:                                      $uname,$udom,$csec,$cgroup);
                   3666:                 $totalstored ++;
                   3667:             }
1.473     amueller 3668:         }
1.68      www      3669: # ---------------------------------------------------------------- Done storing
1.504     raeburn  3670:         if ($totalstored) {
                   3671:             $message.='<p class="LC_warning">'
1.605     raeburn  3672:                      .&mt('Changes for [quant,_1,parameter] saved.',$totalstored)
                   3673:                      .'<br />'
1.504     raeburn  3674:                      .&mt('Changes can take up to 10 minutes before being active for all students.')
                   3675:                      .&Apache::loncommon::help_open_topic('Caching')
                   3676:                      .'</p>';
1.605     raeburn  3677:         } else {
                   3678:             $message.='<p class="LC_info">'.&mt('No parameter changes saved.').'</p>';
                   3679:         }
                   3680:         if ($totalskippeduser) {
                   3681:             $message .= '<p class="LC_warning">';
                   3682:             if ($uhome eq 'no_host') {
                   3683:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the username or ID was invalid.',
                   3684:                                 $totalskippeduser);
                   3685:             } elsif ($env{'form.userroles'} eq 'any') {
                   3686:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user does not have a course role.',
                   3687:                                 $totalskippeduser);
                   3688:             } else {
                   3689:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user is not a student.',
                   3690:                                 $totalskippeduser);
                   3691:             }
                   3692:             $message .= '</p>';
1.504     raeburn  3693:         }
1.68      www      3694:     }
1.584     raeburn  3695: 
1.57      albertel 3696: #----------------------------------------------- if all selected, fill in array
1.563     damieng  3697:     if ($pscat[0] eq "all") {
                   3698:         @pscat = (keys(%allparms));
                   3699:     }
                   3700:     if (!@pscat) {
                   3701:         @pscat=('duedate','opendate','answerdate','weight','maxtries','type','problemstatus')
                   3702:     };
                   3703:     if ($psprt[0] eq "all" || !@psprt) {
                   3704:         @psprt = (keys(%allparts));
                   3705:     }
1.2       www      3706: # ------------------------------------------------------------------ Start page
1.63      bowersj2 3707: 
1.531     raeburn  3708:     my $crstype = &Apache::loncommon::course_type();
                   3709:     &startpage($r,$pssymb,$crstype);
1.57      albertel 3710: 
1.548     raeburn  3711:     foreach my $item ('tolerance','date_default','date_start','date_end',
1.589     raeburn  3712:             'date_interval','int','float','string','string_lenient',
                   3713:             'string_examcode','string_deeplink','string_discussvote',
                   3714:             'string_useslots','string_problemstatus','string_ip',
1.621   ! raeburn  3715:             'string_questiontype','string_tex') {
1.473     amueller 3716:         $r->print('<input type="hidden" value="'.
1.563     damieng  3717:             &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').
                   3718:             '" name="recent_'.$item.'" />');
1.44      albertel 3719:     }
1.446     bisitz   3720: 
1.459     bisitz   3721:     # ----- Start Parameter Selection
                   3722: 
1.606     raeburn  3723:     # Hide parm selection and possibly table?
                   3724:     my ($tablejs,$tabledivsty);
                   3725:     if (((($env{'form.uname'} ne '') || ($env{'form.id'} ne '')) && ($uname eq '')) &&
                   3726:         ($env{'form.dis'}) && ($pssymb eq '')) {
                   3727:         $tablejs = 'document.getElementById('."'parmtable'".').style.display = "";';
                   3728:         $tabledivsty = ' style="display:none"';
                   3729:     }
1.459     bisitz   3730:     $r->print(<<ENDPARMSELSCRIPT);
                   3731: <script type="text/javascript">
                   3732: // <![CDATA[
                   3733: function parmsel_show() {
1.562     damieng  3734:     document.getElementById('parmsel').style.display = "";
                   3735:     document.getElementById('parmsellink').style.display = "none";
1.606     raeburn  3736:     $tablejs
1.459     bisitz   3737: }
                   3738: // ]]>
                   3739: </script>
                   3740: ENDPARMSELSCRIPT
1.474     amueller 3741:     
1.445     neumanie 3742:     if (!$pssymb) {
1.563     damieng  3743:         # No single resource selected, print forms to select things (hidden after first selection)
1.486     www      3744:         my $parmselhiddenstyle=' style="display:none"';
                   3745:         if($env{'form.hideparmsel'} eq 'hidden') {
                   3746:            $r->print('<div id="parmsel"'.$parmselhiddenstyle.'>');
                   3747:         } else  {
                   3748:            $r->print('<div id="parmsel">');
                   3749:         }
                   3750: 
1.491     bisitz   3751:         # Step 1
1.523     raeburn  3752:         $r->print(&Apache::lonhtmlcommon::topic_bar(1,&mt('Resource Specification'),'parmstep1'));
                   3753:         $r->print('
1.474     amueller 3754: <script type="text/javascript">
1.523     raeburn  3755: // <![CDATA['.
                   3756:                  &showhide_js().'
1.474     amueller 3757: // ]]>
                   3758: </script>
1.523     raeburn  3759: ');
                   3760:         $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.209     www      3761:         &levelmenu($r,\%alllevs,$parmlev);
1.491     bisitz   3762:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.610     raeburn  3763:         &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.491     bisitz   3764:         $r->print(&Apache::lonhtmlcommon::row_closure());
                   3765:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
                   3766:         &partmenu($r,\%allparts,\@psprt);
1.474     amueller 3767:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3768:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3769: 
                   3770:         # Step 2
1.523     raeburn  3771:         $r->print(&Apache::lonhtmlcommon::topic_bar(2,&mt('Parameter Specification'),'parmstep2'));
1.581     raeburn  3772:         &displaymenu($r,\%allparms,\@pscat,\%keyorder,'parmmenuscroll');
1.491     bisitz   3773: 
                   3774:         # Step 3
1.523     raeburn  3775:         $r->print(&Apache::lonhtmlcommon::topic_bar(3,&mt('User Specification (optional)'),'parmstep3'));
1.486     www      3776:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3777:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3778:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3779:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3780: 
                   3781:         # Update Display Button
1.486     www      3782:         $r->print('<p>'
                   3783:              .'<input type="submit" name="dis"'
1.511     www      3784:              .' value="'.&mt('Update Display').'" />'
1.486     www      3785:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
                   3786:              .'</p>');
                   3787:         $r->print('</div>');
1.491     bisitz   3788: 
1.486     www      3789:         # Offer link to display parameter selection again
                   3790:         $r->print('<p id="parmsellink"');
                   3791:         if ($env{'form.hideparmsel'} ne 'hidden') {
                   3792:            $r->print($parmselhiddenstyle);
                   3793:         }
                   3794:         $r->print('>'
                   3795:              .'<a href="javascript:parmsel_show()">'
                   3796:              .&mt('Change Parameter Selection')
                   3797:              .'</a>'
                   3798:              .'</p>');
1.44      albertel 3799:     } else {
1.478     amueller 3800:         # parameter screen for a single resource. 
1.486     www      3801:         my ($map,$iid,$resource)=&Apache::lonnet::decode_symb($pssymb);
1.473     amueller 3802:         my $title = &Apache::lonnet::gettitle($pssymb);
1.501     bisitz   3803:         $r->print(&mt('Specific Resource: [_1] ([_2])',
                   3804:                          $title,'<span class="LC_filename">'.$resource.'</span>').
1.472     amueller 3805:                 '<input type="hidden" value="'.$pssymb.'" name="symb" />'.
1.486     www      3806:                   '<br />');
                   3807:         $r->print(&Apache::lonhtmlcommon::topic_bar('',&mt('Additional Display Specification (optional)')));
                   3808:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3809:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3810:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3811:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   3812:         $r->print('<p>'
1.459     bisitz   3813:              .'<input type="submit" name="dis"'
1.511     www      3814:              .' value="'.&mt('Update Display').'" />'
1.459     bisitz   3815:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
1.486     www      3816:              .'</p>');
1.459     bisitz   3817:     }
1.478     amueller 3818:     
1.486     www      3819:     # ----- End Parameter Selection
1.57      albertel 3820: 
1.459     bisitz   3821:     # Display Messages
                   3822:     $r->print('<div>'.$message.'</div>');
1.210     www      3823: 
1.57      albertel 3824: 
                   3825:     my @temp_pscat;
                   3826:     map {
                   3827:         my $cat = $_;
                   3828:         push(@temp_pscat, map { $_.'.'.$cat } @psprt);
                   3829:     } @pscat;
                   3830: 
                   3831:     @pscat = @temp_pscat;
                   3832: 
1.548     raeburn  3833: 
1.209     www      3834:     if (($env{'form.prevvisit'}) || ($pschp) || ($pssymb)) {
1.10      www      3835: # ----------------------------------------------------------------- Start Table
1.57      albertel 3836:         my @catmarker=map { tr|.|_|; 'parameter_'.$_; } @pscat;
1.190     albertel 3837:         my $csuname=$env{'user.name'};
                   3838:         my $csudom=$env{'user.domain'};
1.568     raeburn  3839:         my $readonly = 1;
                   3840:         if ($parm_permission->{'edit'}) {
                   3841:             undef($readonly); 
                   3842:         }
1.606     raeburn  3843:         $r->print('<div id="parmtable"'.$tabledivsty.'>');
1.57      albertel 3844: 
1.203     www      3845:         if ($parmlev eq 'full') {
1.506     www      3846: #
                   3847: # This produces the cascading table output of parameters
                   3848: #
1.578     raeburn  3849:             my $coursespan=$csec?8:5;
                   3850:             my $userspan=3;
1.560     damieng  3851:             if ($cgroup ne '') {
1.578     raeburn  3852:                 $coursespan += 3;
1.560     damieng  3853:             }
1.473     amueller 3854: 
1.560     damieng  3855:             $r->print(&Apache::loncommon::start_data_table());
                   3856:             #
                   3857:             # This produces the headers
                   3858:             #
                   3859:             $r->print('<tr><td colspan="5"></td>');
                   3860:             $r->print('<th colspan="'.($coursespan).'">'.&mt('Any User').'</th>');
                   3861:             if ($uname) {
1.473     amueller 3862:                 if (@usersgroups > 1) {
1.560     damieng  3863:                     $userspan ++;
                   3864:                 }
                   3865:                 $r->print('<th colspan="'.$userspan.'" rowspan="2">');
                   3866:                 $r->print(&mt('User [_1] at Domain [_2]',"'".$uname."'","'".$udom."'").'</th>');
                   3867:             }
                   3868:             my %lt=&Apache::lonlocal::texthash(
1.473     amueller 3869:                 'pie'    => "Parameter in Effect",
                   3870:                 'csv'    => "Current Session Value",
1.472     amueller 3871:                 'rl'     => "Resource Level",
1.473     amueller 3872:                 'ic'     => 'in Course',
                   3873:                 'aut'    => "Assessment URL and Title",
                   3874:                 'type'   => 'Type',
                   3875:                 'emof'   => "Enclosing Map or Folder",
                   3876:                 'part'   => 'Part',
1.472     amueller 3877:                 'pn'     => 'Parameter Name',
1.473     amueller 3878:                 'def'    => 'default',
                   3879:                 'femof'  => 'from Enclosing Map or Folder',
                   3880:                 'gen'    => 'general',
                   3881:                 'foremf' => 'for Enclosing Map or Folder',
                   3882:                 'fr'     => 'for Resource'
                   3883:             );
1.560     damieng  3884:             $r->print(<<ENDTABLETWO);
1.419     bisitz   3885: <th rowspan="3">$lt{'pie'}</th>
1.501     bisitz   3886: <th rowspan="3">$lt{'csv'}<br />($csuname:$csudom)</th>
1.578     raeburn  3887: </tr><tr><td colspan="5"></td><th colspan="2">$lt{'ic'}</th><th colspan="2">$lt{'rl'}</th>
1.419     bisitz   3888: <th colspan="1">$lt{'ic'}</th>
1.182     albertel 3889: 
1.10      www      3890: ENDTABLETWO
1.560     damieng  3891:             if ($csec) {
1.578     raeburn  3892:                 $r->print('<th colspan="3">'.
1.560     damieng  3893:                 &mt("in Section")." $csec</th>");
                   3894:             }
                   3895:             if ($cgroup) {
1.578     raeburn  3896:                 $r->print('<th colspan="3">'.
1.472     amueller 3897:                 &mt("in Group")." $cgroup</th>");
1.560     damieng  3898:             }
                   3899:             $r->print(<<ENDTABLEHEADFOUR);
1.133     www      3900: </tr><tr><th>$lt{'aut'}</th><th>$lt{'type'}</th>
                   3901: <th>$lt{'emof'}</th><th>$lt{'part'}</th><th>$lt{'pn'}</th>
1.578     raeburn  3902: <th>$lt{'gen'}</th><th>$lt{'foremf'}</th>
1.192     albertel 3903: <th>$lt{'def'}</th><th>$lt{'femof'}</th><th>$lt{'fr'}</th>
1.10      www      3904: ENDTABLEHEADFOUR
1.57      albertel 3905: 
1.560     damieng  3906:             if ($csec) {
1.578     raeburn  3907:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3908:             }
1.473     amueller 3909: 
1.560     damieng  3910:             if ($cgroup) {
1.578     raeburn  3911:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3912:             }
                   3913: 
                   3914:             if ($uname) {
                   3915:                 if (@usersgroups > 1) {
                   3916:                     $r->print('<th>'.&mt('Control by other group?').'</th>');
                   3917:                 }
1.578     raeburn  3918:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3919:             }
                   3920: 
                   3921:             $r->print('</tr>');
1.506     www      3922: #
                   3923: # Done with the headers
                   3924: # 
1.560     damieng  3925:             my $defbgone='';
                   3926:             my $defbgtwo='';
                   3927:             my $defbgthree = '';
1.57      albertel 3928: 
1.560     damieng  3929:             foreach my $rid (@ids) {
1.57      albertel 3930: 
                   3931:                 my ($inmapid)=($rid=~/\.(\d+)$/);
1.446     bisitz   3932:                 if ((!$pssymb &&
1.560     damieng  3933:                         (($pschp eq 'all') || ($allmaps{$pschp} eq $mapp{$rid})))
                   3934:                         ||
                   3935:                         ($pssymb && $pssymb eq $symbp{$rid})) {
1.4       www      3936: # ------------------------------------------------------ Entry for one resource
1.473     amueller 3937:                     if ($defbgone eq '#E0E099') {
                   3938:                         $defbgone='#E0E0DD';
1.57      albertel 3939:                     } else {
1.419     bisitz   3940:                         $defbgone='#E0E099';
1.57      albertel 3941:                     }
1.419     bisitz   3942:                     if ($defbgtwo eq '#FFFF99') {
1.473     amueller 3943:                         $defbgtwo='#FFFFDD';
1.57      albertel 3944:                     } else {
1.473     amueller 3945:                         $defbgtwo='#FFFF99';
1.57      albertel 3946:                     }
1.419     bisitz   3947:                     if ($defbgthree eq '#FFBB99') {
                   3948:                         $defbgthree='#FFBBDD';
1.269     raeburn  3949:                     } else {
1.419     bisitz   3950:                         $defbgthree='#FFBB99';
1.269     raeburn  3951:                     }
                   3952: 
1.57      albertel 3953:                     my $thistitle='';
                   3954:                     my %name=   ();
                   3955:                     undef %name;
                   3956:                     my %part=   ();
                   3957:                     my %display=();
                   3958:                     my %type=   ();
                   3959:                     my %default=();
1.196     www      3960:                     my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  3961:                     my $toolsymb;
                   3962:                     if ($uri =~ /ext\.tool$/) {
                   3963:                         $toolsymb = $symbp{$rid};
                   3964:                     }
1.57      albertel 3965: 
1.506     www      3966:                     my $filter=$env{'form.filter'};
1.548     raeburn  3967:                     foreach my $tempkeyp (&keysplit($keyp{$rid})) {
1.57      albertel 3968:                         if (grep $_ eq $tempkeyp, @catmarker) {
1.584     raeburn  3969:                             my $parmname=&Apache::lonnet::metadata($uri,$tempkeyp.'.name',$toolsymb);
1.560     damieng  3970:     # We may only want certain parameters listed
                   3971:                             if ($filter) {
                   3972:                                 unless ($filter=~/\Q$parmname\E/) { next; }
                   3973:                             }
                   3974:                             $name{$tempkeyp}=$parmname;
1.584     raeburn  3975:                             $part{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.part',$toolsymb);
1.560     damieng  3976: 
1.584     raeburn  3977:                             my $parmdis=&Apache::lonnet::metadata($uri,$tempkeyp.'.display',$toolsymb);
1.560     damieng  3978:                             if ($allparms{$name{$tempkeyp}} ne '') {
                   3979:                                 my $identifier;
                   3980:                                 if ($parmdis =~ /(\s*\[Part.*)$/) {
                   3981:                                     $identifier = $1;
                   3982:                                 }
                   3983:                                 $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   3984:                             } else {
                   3985:                                 $display{$tempkeyp} = $parmdis;
                   3986:                             }
                   3987:                             unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   3988:                             $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
1.584     raeburn  3989:                             $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp,$toolsymb);
                   3990:                             $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.type',$toolsymb);
                   3991:                             $thistitle=&Apache::lonnet::metadata($uri,$tempkeyp.'.title',$toolsymb);
1.57      albertel 3992:                         }
                   3993:                     }
1.548     raeburn  3994:                     my $totalparms=scalar(keys(%name));
1.57      albertel 3995:                     if ($totalparms>0) {
1.560     damieng  3996:                         my $firstrow=1;
1.473     amueller 3997:                         my $title=&Apache::lonnet::gettitle($symbp{$rid});
1.582     raeburn  3998:                         my $navmap = Apache::lonnavmaps::navmap->new();
                   3999:                         my @recurseup;
                   4000:                         if (ref($navmap) && $mapp{$rid}) {
                   4001:                             @recurseup = $navmap->recurseup_maps($mapp{$rid});
                   4002:                         }
1.419     bisitz   4003:                         $r->print('<tr><td style="background-color:'.$defbgone.';"'.
1.57      albertel 4004:                              ' rowspan='.$totalparms.
1.419     bisitz   4005:                              '><tt><font size="-1">'.
1.57      albertel 4006:                              join(' / ',split(/\//,$uri)).
                   4007:                              '</font></tt><p><b>'.
1.154     albertel 4008:                              "<a href=\"javascript:openWindow('".
1.473     amueller 4009:                           &Apache::lonnet::clutter($uri).'?symb='.
                   4010:                           &escape($symbp{$rid}).
1.336     albertel 4011:                              "', 'metadatafile', '450', '500', 'no', 'yes');\"".
                   4012:                              " target=\"_self\">$title");
1.57      albertel 4013: 
                   4014:                         if ($thistitle) {
1.473     amueller 4015:                             $r->print(' ('.$thistitle.')');
1.57      albertel 4016:                         }
                   4017:                         $r->print('</a></b></td>');
1.419     bisitz   4018:                         $r->print('<td style="background-color:'.$defbgtwo.';"'.
1.57      albertel 4019:                                       ' rowspan='.$totalparms.'>'.$typep{$rid}.
                   4020:                                       '</td>');
                   4021: 
1.419     bisitz   4022:                         $r->print('<td style="background-color:'.$defbgone.';"'.
1.57      albertel 4023:                                       ' rowspan='.$totalparms.
1.238     www      4024:                                       '>'.$maptitles{$mapp{$rid}}.'</td>');
1.548     raeburn  4025:                         foreach my $item (&keysinorder_bytype(\%name,\%keyorder)) {
1.57      albertel 4026:                             unless ($firstrow) {
                   4027:                                 $r->print('<tr>');
                   4028:                             } else {
                   4029:                                 undef $firstrow;
                   4030:                             }
1.548     raeburn  4031:                             &print_row($r,$item,\%part,\%name,\%symbp,$rid,\%default,
1.57      albertel 4032:                                        \%type,\%display,$defbgone,$defbgtwo,
1.269     raeburn  4033:                                        $defbgthree,$parmlev,$uname,$udom,$csec,
1.582     raeburn  4034:                                        $cgroup,\@usersgroups,$noeditgrp,$readonly,
                   4035:                                        \@recurseup,\%maptitles,\%allmaps_inverted,
                   4036:                                        \$numreclinks);
1.57      albertel 4037:                         }
                   4038:                     }
                   4039:                 }
                   4040:             } # end foreach ids
1.43      albertel 4041: # -------------------------------------------------- End entry for one resource
1.517     www      4042:             $r->print(&Apache::loncommon::end_data_table);
1.203     www      4043:         } # end of  full
1.57      albertel 4044: #--------------------------------------------------- Entry for parm level map
                   4045:         if ($parmlev eq 'map') {
1.419     bisitz   4046:             my $defbgone = '#E0E099';
                   4047:             my $defbgtwo = '#FFFF99';
                   4048:             my $defbgthree = '#FFBB99';
1.57      albertel 4049: 
                   4050:             my %maplist;
                   4051: 
                   4052:             if ($pschp eq 'all') {
1.446     bisitz   4053:                 %maplist = %allmaps;
1.57      albertel 4054:             } else {
                   4055:                 %maplist = ($pschp => $mapp{$pschp});
                   4056:             }
                   4057: 
                   4058: #-------------------------------------------- for each map, gather information
                   4059:             my $mapid;
1.607     raeburn  4060:             foreach $mapid (sort { $a <=> $b } keys(%maplist)) {
1.60      albertel 4061:                 my $maptitle = $maplist{$mapid};
1.57      albertel 4062: 
                   4063: #-----------------------  loop through ids and get all parameter types for map
                   4064: #-----------------------------------------          and associated information
                   4065:                 my %name = ();
                   4066:                 my %part = ();
                   4067:                 my %display = ();
                   4068:                 my %type = ();
                   4069:                 my %default = ();
                   4070:                 my $map = 0;
                   4071: 
1.473     amueller 4072: #        $r->print("Catmarker: @catmarker<br />\n");
1.446     bisitz   4073: 
1.548     raeburn  4074:                 foreach my $id (@ids) {
                   4075:                     ($map)=($id =~ /([\d]*?)\./);
                   4076:                     my $rid = $id;
1.446     bisitz   4077: 
1.57      albertel 4078: #                  $r->print("$mapid:$map:   $rid <br /> \n");
                   4079: 
1.560     damieng  4080:                     if ($map eq $mapid) {
1.473     amueller 4081:                         my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  4082:                         my $toolsymb;
                   4083:                         if ($uri =~ /ext\.tool$/) {
                   4084:                             $toolsymb = $symbp{$rid};
                   4085:                         }
1.582     raeburn  4086: 
1.57      albertel 4087: #                    $r->print("Keys: $keyp{$rid} <br />\n");
                   4088: 
                   4089: #--------------------------------------------------------------------
                   4090: # @catmarker contains list of all possible parameters including part #s
                   4091: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   4092: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   4093: # When storing information, store as part 0
                   4094: # When requesting information, request from full part
                   4095: #-------------------------------------------------------------------
1.548     raeburn  4096:                         foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   4097:                             my $tempkeyp = $fullkeyp;
                   4098:                             $tempkeyp =~ s/_\w+_/_0_/;
1.473     amueller 4099: 
1.548     raeburn  4100:                             if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 4101:                                 $part{$tempkeyp}="0";
1.584     raeburn  4102:                                 $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
                   4103:                                 my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473     amueller 4104:                                 if ($allparms{$name{$tempkeyp}} ne '') {
                   4105:                                     my $identifier;
                   4106:                                     if ($parmdis =~ /(\s*\[Part.*)$/) {
                   4107:                                         $identifier = $1;
                   4108:                                     }
                   4109:                                     $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   4110:                                 } else {
                   4111:                                     $display{$tempkeyp} = $parmdis;
                   4112:                                 }
                   4113:                                 unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   4114:                                 $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   4115:                                 $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584     raeburn  4116:                                 $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
                   4117:                                 $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.473     amueller 4118:                               }
                   4119:                         } # end loop through keys
1.560     damieng  4120:                     }
1.57      albertel 4121:                 } # end loop through ids
1.446     bisitz   4122: 
1.57      albertel 4123: #---------------------------------------------------- print header information
1.133     www      4124:                 my $foldermap=&mt($maptitle=~/^uploaded/?'Folder':'Map');
1.82      www      4125:                 my $showtitle=$maptitles{$maptitle}.($maptitle!~/^uploaded/?' ['.$maptitle.']':'');
1.401     bisitz   4126:                 my $tmp="";
1.57      albertel 4127:                 if ($uname) {
1.473     amueller 4128:                     my $person=&Apache::loncommon::plainname($uname,$udom);
1.401     bisitz   4129:                     $tmp.=&mt("User")." <font color=\"red\"><i>$uname \($person\) </i></font> ".
                   4130:                         &mt('in')." \n";
1.57      albertel 4131:                 } else {
1.401     bisitz   4132:                     $tmp.="<font color=\"red\"><i>".&mt('all').'</i></font> '.&mt('users in')." \n";
1.57      albertel 4133:                 }
1.269     raeburn  4134:                 if ($cgroup) {
1.401     bisitz   4135:                     $tmp.=&mt("Group")." <font color=\"red\"><i>$cgroup".
                   4136:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  4137:                     $csec = '';
                   4138:                 } elsif ($csec) {
1.401     bisitz   4139:                     $tmp.=&mt("Section")." <font color=\"red\"><i>$csec".
                   4140:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  4141:                 }
1.401     bisitz   4142:                 $r->print('<div align="center"><h4>'
                   4143:                          .&mt('Set Defaults for All Resources in [_1]Specifically for [_2][_3]'
1.404     bisitz   4144:                              ,$foldermap.'<br /><font color="red"><i>'.$showtitle.'</i></font><br />'
1.401     bisitz   4145:                              ,$tmp
                   4146:                              ,'<font color="red"><i>'.$coursename.'</i></font>'
                   4147:                              )
                   4148:                          ."<br /></h4>\n"
1.422     bisitz   4149:                 );
1.57      albertel 4150: #---------------------------------------------------------------- print table
1.419     bisitz   4151:                 $r->print('<p>'.&Apache::loncommon::start_data_table()
                   4152:                          .&Apache::loncommon::start_data_table_header_row()
                   4153:                          .'<th>'.&mt('Parameter Name').'</th>'
1.578     raeburn  4154:                          .'<th>'.&mt('Value').'</th>'
1.419     bisitz   4155:                          .'<th>'.&mt('Parameter in Effect').'</th>'
                   4156:                          .&Apache::loncommon::end_data_table_header_row()
                   4157:                 );
1.57      albertel 4158: 
1.582     raeburn  4159:                 my $navmap = Apache::lonnavmaps::navmap->new();
                   4160:                 my @recurseup;
                   4161:                 if (ref($navmap)) {
                   4162:                      my $mapres = $navmap->getByMapPc($mapid);
                   4163:                      if (ref($mapres)) {
                   4164:                          @recurseup = $navmap->recurseup_maps($mapres->src());
                   4165:                      }
                   4166:                 }
                   4167: 
                   4168: 
1.548     raeburn  4169:                 foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.473     amueller 4170:                     $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  4171:                     &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.269     raeburn  4172:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
1.568     raeburn  4173:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
1.582     raeburn  4174:                            $readonly,\@recurseup,\%maptitles,\%allmaps_inverted,
                   4175:                            \$numreclinks);
1.57      albertel 4176:                 }
1.422     bisitz   4177:                 $r->print(&Apache::loncommon::end_data_table().'</p>'
                   4178:                          .'</div>'
                   4179:                 );
1.57      albertel 4180:             } # end each map
                   4181:         } # end of $parmlev eq map
                   4182: #--------------------------------- Entry for parm level general (Course level)
                   4183:         if ($parmlev eq 'general') {
1.473     amueller 4184:             my $defbgone = '#E0E099';
1.419     bisitz   4185:             my $defbgtwo = '#FFFF99';
                   4186:             my $defbgthree = '#FFBB99';
1.57      albertel 4187: 
                   4188: #-------------------------------------------- for each map, gather information
                   4189:             my $mapid="0.0";
                   4190: #-----------------------  loop through ids and get all parameter types for map
                   4191: #-----------------------------------------          and associated information
                   4192:             my %name = ();
                   4193:             my %part = ();
                   4194:             my %display = ();
                   4195:             my %type = ();
                   4196:             my %default = ();
1.446     bisitz   4197: 
1.548     raeburn  4198:             foreach $id (@ids) {
                   4199:                 my $rid = $id;
1.446     bisitz   4200: 
1.196     www      4201:                 my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  4202:                 my $toolsymb;
                   4203:                 if ($uri =~ /ext\.tool$/) {
                   4204:                     $toolsymb = $symbp{$rid};
                   4205:                 }
1.57      albertel 4206: 
                   4207: #--------------------------------------------------------------------
                   4208: # @catmarker contains list of all possible parameters including part #s
                   4209: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   4210: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   4211: # When storing information, store as part 0
                   4212: # When requesting information, request from full part
                   4213: #-------------------------------------------------------------------
1.548     raeburn  4214:                 foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   4215:                     my $tempkeyp = $fullkeyp;
                   4216:                     $tempkeyp =~ s/_\w+_/_0_/;
                   4217:                     if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 4218:                         $part{$tempkeyp}="0";
1.584     raeburn  4219:                         $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
                   4220:                         my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473     amueller 4221:                         if ($allparms{$name{$tempkeyp}} ne '') {
                   4222:                             my $identifier;
                   4223:                             if ($parmdis =~ /(\s*\[Part.*)$/) {
                   4224:                                 $identifier = $1;
                   4225:                             }
                   4226:                             $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   4227:                         } else {
                   4228:                             $display{$tempkeyp} = $parmdis;
                   4229:                         }
                   4230:                         unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   4231:                         $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   4232:                         $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584     raeburn  4233:                         $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
                   4234:                         $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.560     damieng  4235:                     }
1.57      albertel 4236:                 } # end loop through keys
                   4237:             } # end loop through ids
1.446     bisitz   4238: 
1.57      albertel 4239: #---------------------------------------------------- print header information
1.473     amueller 4240:             my $setdef=&mt("Set Defaults for All Resources in Course");
1.57      albertel 4241:             $r->print(<<ENDMAPONE);
1.419     bisitz   4242: <center>
                   4243: <h4>$setdef
1.135     albertel 4244: <font color="red"><i>$coursename</i></font><br />
1.57      albertel 4245: ENDMAPONE
                   4246:             if ($uname) {
1.473     amueller 4247:                 my $person=&Apache::loncommon::plainname($uname,$udom);
1.135     albertel 4248:                 $r->print(" ".&mt("User")."<font color=\"red\"> <i>$uname \($person\) </i></font> \n");
1.57      albertel 4249:             } else {
1.135     albertel 4250:                 $r->print("<i><font color=\"red\"> ".&mt("ALL")."</i> ".&mt("USERS")."</font> \n");
1.57      albertel 4251:             }
1.446     bisitz   4252: 
1.135     albertel 4253:             if ($csec) {$r->print(&mt("Section")."<font color=\"red\"> <i>$csec</i></font>\n")};
1.306     albertel 4254:             if ($cgroup) {$r->print(&mt("Group")."<font color=\"red\"> <i>$cgroup</i></font>\n")};
1.135     albertel 4255:             $r->print("</h4>\n");
1.57      albertel 4256: #---------------------------------------------------------------- print table
1.419     bisitz   4257:             $r->print('<p>'.&Apache::loncommon::start_data_table()
                   4258:                      .&Apache::loncommon::start_data_table_header_row()
                   4259:                      .'<th>'.&mt('Parameter Name').'</th>'
                   4260:                      .'<th>'.&mt('Default Value').'</th>'
                   4261:                      .'<th>'.&mt('Parameter in Effect').'</th>'
                   4262:                      .&Apache::loncommon::end_data_table_header_row()
                   4263:             );
1.57      albertel 4264: 
1.548     raeburn  4265:             foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.419     bisitz   4266:                 $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  4267:                 &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.568     raeburn  4268:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
                   4269:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
                   4270:                            $readonly);
1.57      albertel 4271:             }
1.419     bisitz   4272:             $r->print(&Apache::loncommon::end_data_table()
                   4273:                      .'</p>'
                   4274:                      .'</center>'
                   4275:             );
1.57      albertel 4276:         } # end of $parmlev eq general
1.606     raeburn  4277:         $r->print('</div>');
1.43      albertel 4278:     }
1.507     www      4279:     $r->print('</form>');
1.582     raeburn  4280:     if ($numreclinks) {
                   4281:         $r->print(<<"END");
                   4282: <form name="recurseform" action="/adm/parmset?action=settable" method="post">
                   4283: <input type="hidden" name="pschp" />
                   4284: <input type="hidden" name="pscat" />
                   4285: <input type="hidden" name="psprt" />
                   4286: <input type="hidden" name="hideparmsel" value="hidden" />
                   4287: </form>
                   4288: <script type="text/javascript">
                   4289: function pjumprec(rid,name,part) {
                   4290:     document.forms.recurseform.pschp.value = rid;
                   4291:     document.forms.recurseform.pscat.value = name;
                   4292:     document.forms.recurseform.psprt.value = part;
                   4293:     document.forms.recurseform.submit();
                   4294:     return false;
                   4295: }
                   4296: </script>
                   4297: END
                   4298:     }
1.507     www      4299:     &endSettingsScreen($r);
                   4300:     $r->print(&Apache::loncommon::end_page());
1.57      albertel 4301: } # end sub assessparms
1.30      www      4302: 
1.560     damieng  4303: 
                   4304: 
1.120     www      4305: ##################################################
1.560     damieng  4306: # OVERVIEW MODE
1.207     www      4307: ##################################################
1.124     www      4308: 
1.563     damieng  4309: my $tableopen; # boolean, true if HTML table is already opened
                   4310: 
                   4311: # Returns HTML with the HTML table start tag and header, unless the table is already opened.
                   4312: # @param {boolean} $readonly - true if values cannot be edited (otherwise more columns are added)
                   4313: # @returns {string}
1.124     www      4314: sub tablestart {
1.576     raeburn  4315:     my ($readonly,$is_map) = @_;
1.124     www      4316:     if ($tableopen) {
1.552     raeburn  4317:         return '';
1.124     www      4318:     } else {
1.552     raeburn  4319:         $tableopen=1;
                   4320:         my $output = &Apache::loncommon::start_data_table().'<tr><th>'.&mt('Parameter').'</th>';
                   4321:         if ($readonly) {
                   4322:             $output .= '<th>'.&mt('Current value').'</th>';
                   4323:         } else {
1.576     raeburn  4324:             $output .= '<th>'.&mt('Delete').'</th>'.
                   4325:                        '<th>'.&mt('Set to ...').'</th>';
                   4326:             if ($is_map) {
                   4327:                 $output .= '<th>'.&mt('Recursive?').'</th>';
                   4328:             }
1.552     raeburn  4329:         }
                   4330:         $output .= '</tr>';
                   4331:         return $output;
1.124     www      4332:     }
                   4333: }
                   4334: 
1.563     damieng  4335: # Returns HTML with the HTML table end tag, unless the table is not opened.
                   4336: # @returns {string}
1.124     www      4337: sub tableend {
                   4338:     if ($tableopen) {
1.560     damieng  4339:         $tableopen=0;
                   4340:         return &Apache::loncommon::end_data_table();
1.124     www      4341:     } else {
1.560     damieng  4342:         return'';
1.124     www      4343:     }
                   4344: }
                   4345: 
1.563     damieng  4346: # Reads course and user information.
                   4347: # 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).
                   4348: # The key for student data is modified with '[useropt:'.username.':'.userdomain.'].'.
                   4349: # If the context is looking for a list, returns a list with the scalar data and the class list.
                   4350: # @param {string} $crs - course number
                   4351: # @param {string} $dom - course domain
                   4352: # @returns {hash reference|Array}
1.207     www      4353: sub readdata {
                   4354:     my ($crs,$dom)=@_;
                   4355: # Read coursedata
                   4356:     my $resourcedata=&Apache::lonnet::get_courseresdata($crs,$dom);
                   4357: # Read userdata
                   4358: 
                   4359:     my $classlist=&Apache::loncoursedata::get_classlist();
1.548     raeburn  4360:     foreach my $user (keys(%$classlist)) {
                   4361:         if ($user=~/^($match_username)\:($match_domain)$/) {
                   4362:             my ($tuname,$tudom)=($1,$2);
                   4363:             my $useropt=&Apache::lonnet::get_userresdata($tuname,$tudom);
                   4364:             foreach my $userkey (keys(%{$useropt})) {
                   4365:                 if ($userkey=~/^\Q$env{'request.course.id'}\E/) {
1.207     www      4366:                     my $newkey=$userkey;
1.548     raeburn  4367:                     $newkey=~s/^($env{'request.course.id'}\.)/$1\[useropt\:$tuname\:$tudom\]\./;
                   4368:                     $$resourcedata{$newkey}=$$useropt{$userkey};
                   4369:                 }
                   4370:             }
1.473     amueller 4371:         }
                   4372:     }
1.552     raeburn  4373:     if (wantarray) {
                   4374:         return ($resourcedata,$classlist);
                   4375:     } else {
                   4376:         return $resourcedata;
                   4377:     }
1.207     www      4378: }
                   4379: 
                   4380: 
1.563     damieng  4381: # Stores parameter data, using form parameters directly.
                   4382: #
                   4383: # Uses the following form parameters. The variable part in the names is a resourcedata key (except for a modification for user data).
1.588     raeburn  4384: # set_* (except settext, setipallow, setipdeny, setdeeplink) - set a parameter value
1.563     damieng  4385: # del_* - remove a parameter
                   4386: # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)
                   4387: # dateinterval_* - set a date interval parameter (value refers to more form parameters)
                   4388: # key_* - date values
                   4389: # days_* - for date intervals
                   4390: # hours_* - for date intervals
                   4391: # minutes_* - for date intervals
                   4392: # seconds_* - for date intervals
                   4393: # done_* - for date intervals
                   4394: # typeof_* - parameter type
                   4395: # 
                   4396: # @param {Apache2::RequestRec} $r - the Apache request
                   4397: # @param {string} $crs - course number
                   4398: # @param {string} $dom - course domain
1.208     www      4399: sub storedata {
                   4400:     my ($r,$crs,$dom)=@_;
1.207     www      4401: # Set userlevel immediately
                   4402: # Do an intermediate store of course level
                   4403:     my $olddata=&readdata($crs,$dom);
1.124     www      4404:     my %newdata=();
                   4405:     undef %newdata;
                   4406:     my @deldata=();
1.576     raeburn  4407:     my @delrec=();
                   4408:     my @delnonrec=();
1.124     www      4409:     undef @deldata;
1.504     raeburn  4410:     my ($got_chostname,$chostname,$cmajor,$cminor);
1.546     raeburn  4411:     my $now = time;
1.560     damieng  4412:     foreach my $key (keys(%env)) {
                   4413:         if ($key =~ /^form\.([a-z]+)\_(.+)$/) {
                   4414:             my $cmd=$1;
                   4415:             my $thiskey=$2;
1.576     raeburn  4416:             my ($altkey,$recursive,$tkey,$tkeyrec,$tkeynonrec);
1.588     raeburn  4417:             next if ($cmd eq 'rec' || $cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny' || $cmd eq 'setdeeplink');
1.576     raeburn  4418:             if ((($cmd eq 'set') || ($cmd eq 'datepointer') || ($cmd eq 'dateinterval') || ($cmd eq 'del')) && 
                   4419:                  ($thiskey =~ /(?:sequence|page)\Q___(all)\E/)) {
                   4420:                 unless ($thiskey =~ /(encrypturl|hiddenresource)$/) {
                   4421:                     $altkey = $thiskey;
                   4422:                     $altkey =~ s/\Q___(all)\E/___(rec)/;
                   4423:                     if ($env{'form.rec_'.$thiskey}) {
                   4424:                         $recursive = 1;
                   4425:                     }
                   4426:                 }
                   4427:             }
1.560     damieng  4428:             my ($tuname,$tudom)=&extractuser($thiskey);
1.473     amueller 4429:             if ($tuname) {
1.576     raeburn  4430:                 $tkey=$thiskey;
1.560     damieng  4431:                 $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
1.576     raeburn  4432:                 if ($altkey) {
                   4433:                     $tkeynonrec = $tkey; 
                   4434:                     $tkeyrec = $altkey;
                   4435:                     $tkeyrec=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
                   4436:                 }
1.560     damieng  4437:             }
                   4438:             if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {
1.563     damieng  4439:                 my ($data, $typeof, $text, $name, $valchk, $valmatch, $namematch);
                   4440:                 if ($cmd eq 'set') {
                   4441:                     $data=$env{$key};
                   4442:                     $valmatch = '';
                   4443:                     $valchk = $data;
                   4444:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4445:                     $text = &mt('Saved modified parameter for');
                   4446:                     if ($typeof eq 'string_questiontype') {
                   4447:                         $name = 'type';
1.588     raeburn  4448:                     } elsif (($typeof eq 'string_lenient') || ($typeof eq 'string_deeplink')) {
                   4449:                         ($name) = ($typeof =~ /^string_(lenient|deeplink)$/);
1.563     damieng  4450:                         my $stringmatch = &standard_string_matches($typeof);
                   4451:                         if (ref($stringmatch) eq 'ARRAY') {
                   4452:                             foreach my $item (@{$stringmatch}) {
                   4453:                                 if (ref($item) eq 'ARRAY') {
                   4454:                                     my ($regexpname,$pattern) = @{$item};
                   4455:                                     if ($pattern ne '') {
                   4456:                                         if ($data =~ /$pattern/) {
                   4457:                                             $valmatch = $regexpname;
                   4458:                                             $valchk = '';
                   4459:                                             last;
                   4460:                                         }
1.560     damieng  4461:                                     }
1.549     raeburn  4462:                                 }
                   4463:                             }
                   4464:                         }
1.563     damieng  4465:                     } elsif ($typeof eq 'string_discussvote') {
                   4466:                         $name = 'discussvote';
                   4467:                     } elsif ($typeof eq 'string_examcode') {
                   4468:                         $name = 'examcode';
                   4469:                         if (&Apache::lonnet::validCODE($data)) {
                   4470:                             $valchk = 'valid';
                   4471:                         }
                   4472:                     } elsif ($typeof eq 'string_yesno') {
                   4473:                         if ($thiskey =~ /\.retrypartial$/) {
                   4474:                             $name = 'retrypartial';
                   4475:                         }
1.621   ! raeburn  4476:                     } elsif ($typeof eq 'string_tex') {
        !          4477:                         $name = 'texdisplay';
1.549     raeburn  4478:                     }
1.563     damieng  4479:                 } elsif ($cmd eq 'datepointer') {
                   4480:                     $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key});
                   4481:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4482:                     $text = &mt('Saved modified date for');
                   4483:                     if ($typeof eq 'date_start') {
                   4484:                         if ($thiskey =~ /\.printstartdate$/) {
                   4485:                             $name = 'printstartdate';
                   4486:                             if (($data) && ($data > $now)) {
                   4487:                                 $valchk = 'future';
                   4488:                             }
1.560     damieng  4489:                         }
1.563     damieng  4490:                     } elsif ($typeof eq 'date_end') {
                   4491:                         if ($thiskey =~ /\.printenddate$/) {
                   4492:                             $name = 'printenddate';
                   4493:                             if (($data) && ($data < $now)) {
                   4494:                                 $valchk = 'past';
                   4495:                             }
1.560     damieng  4496:                         }
1.504     raeburn  4497:                     }
1.563     damieng  4498:                 } elsif ($cmd eq 'dateinterval') {
                   4499:                     $data=&get_date_interval_from_form($thiskey);
                   4500:                     if ($thiskey =~ /\.interval$/) {
                   4501:                         $name = 'interval';
                   4502:                         my $intervaltype = &get_intervaltype($name);
                   4503:                         my $intervalmatch = &standard_interval_matches($intervaltype);
                   4504:                         if (ref($intervalmatch) eq 'ARRAY') {
                   4505:                             foreach my $item (@{$intervalmatch}) {
                   4506:                                 if (ref($item) eq 'ARRAY') {
                   4507:                                     my ($regexpname,$pattern) = @{$item};
                   4508:                                     if ($pattern ne '') {
                   4509:                                         if ($data =~ /$pattern/) {
                   4510:                                             $valmatch = $regexpname;
                   4511:                                             $valchk = '';
                   4512:                                             last;
                   4513:                                         }
1.560     damieng  4514:                                     }
1.554     raeburn  4515:                                 }
                   4516:                             }
                   4517:                         }
                   4518:                     }
1.563     damieng  4519:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4520:                     $text = &mt('Saved modified date for');
1.554     raeburn  4521:                 }
1.576     raeburn  4522:                 if ($recursive) {
1.563     damieng  4523:                     $namematch = 'maplevelrecurse';
1.560     damieng  4524:                 }
1.563     damieng  4525:                 if (($name ne '') || ($namematch ne '')) {
                   4526:                     my ($needsrelease,$needsnewer);
                   4527:                     if ($name ne '') {
                   4528:                         $needsrelease = $Apache::lonnet::needsrelease{"parameter:$name:$valchk:$valmatch:"};
1.560     damieng  4529:                         if ($needsrelease) {
                   4530:                             unless ($got_chostname) {
1.563     damieng  4531:                                 ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.560     damieng  4532:                                 $got_chostname = 1;
                   4533:                             }
1.563     damieng  4534:                             $needsnewer = &parameter_releasecheck($name,$valchk,$valmatch,undef,
                   4535:                                                                 $needsrelease,
                   4536:                                                                 $cmajor,$cminor);
                   4537:                         }
                   4538:                     }
                   4539:                     if ($namematch ne '') {
                   4540:                         if ($needsnewer) {
                   4541:                             undef($namematch);
1.560     damieng  4542:                         } else {
1.563     damieng  4543:                             my $currneeded;
                   4544:                             if ($needsrelease) {
                   4545:                                 $currneeded = $needsrelease;
                   4546:                             }
                   4547:                             $needsrelease =
                   4548:                                 $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   4549:                             if (($needsrelease) &&
                   4550:                                     (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   4551:                                 unless ($got_chostname) {
                   4552:                                     ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   4553:                                     $got_chostname = 1;
                   4554:                                 }
                   4555:                                 $needsnewer = &parameter_releasecheck(undef,$valchk,$valmatch,
                   4556:                                     $namematch, $needsrelease,$cmajor,$cminor);
                   4557:                             } else {
                   4558:                                 undef($namematch);
                   4559:                             }
1.560     damieng  4560:                         }
1.557     raeburn  4561:                     }
1.563     damieng  4562:                     if ($needsnewer) {
                   4563:                         $r->print('<br />'.&oldversion_warning($name,$namematch,$data,
                   4564:                                                             $chostname,$cmajor,
                   4565:                                                             $cminor,$needsrelease));
                   4566:                         next;
                   4567:                     }
1.504     raeburn  4568:                 }
1.576     raeburn  4569:                 my ($reconlychg,$haschange,$storekey);
                   4570:                 if ($tuname) {
                   4571:                     my $ustorekey;
                   4572:                     if ($altkey) {
                   4573:                         if ($recursive) {
                   4574:                             if (exists($$olddata{$thiskey})) {
                   4575:                                 if ($$olddata{$thiskey} eq $data) {
                   4576:                                     $reconlychg = 1;
                   4577:                                 }
                   4578:                                 &Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname);
                   4579:                             }
                   4580:                             if (exists($$olddata{$altkey})) {
                   4581:                                 if (defined($data) && $$olddata{$altkey} ne $data) {
                   4582:                                     $haschange = 1;
                   4583:                                 }
                   4584:                             } elsif ((!$reconlychg) && ($data ne '')) {
                   4585:                                 $haschange = 1;
                   4586:                             }
                   4587:                             $ustorekey = $tkeyrec;
                   4588:                         } else {
                   4589:                             if (exists($$olddata{$altkey})) {
                   4590:                                 if ($$olddata{$altkey} eq $data) {
                   4591:                                     $reconlychg = 1;
                   4592:                                 }
                   4593:                                 &Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname);
                   4594:                             }
                   4595:                             if (exists($$olddata{$thiskey})) {
                   4596:                                 if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4597:                                     $haschange = 1;
                   4598:                                 }
                   4599:                             } elsif ((!$reconlychg) && ($data ne '')) {
                   4600:                                 $haschange = 1;
                   4601:                             }
                   4602:                             $ustorekey = $tkeynonrec;
                   4603:                         }
                   4604:                     } else {
                   4605:                         if (exists($$olddata{$tkey})) {
                   4606:                             if (defined($data) && $$olddata{$tkey} ne $data) {
                   4607:                                 $haschange = 1;
                   4608:                             }
                   4609:                             $ustorekey = $tkey;
                   4610:                         }
                   4611:                     }
                   4612:                     if ($haschange || $reconlychg)  {
                   4613:                         unless ($env{'form.del_'.$thiskey}) {
                   4614:                             if (&Apache::lonnet::put('resourcedata',{$ustorekey=>$data,
                   4615:                                                                      $ustorekey.'.type' => $typeof},
                   4616:                                                                      $tudom,$tuname) eq 'ok') {
                   4617:                                 &log_parmset({$ustorekey=>$data,$ustorekey.'.type' => $typeof},0,$tuname,$tudom);
                   4618:                                 $r->print('<br />'.$text.' '.
                   4619:                                           &Apache::loncommon::plainname($tuname,$tudom));
                   4620:                             } else {
                   4621:                                 $r->print('<div class="LC_error">'.
                   4622:                                           &mt('Error saving parameters').'</div>');
                   4623:                             }
                   4624:                             &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   4625:                         }
                   4626:                     }
                   4627:                 } else {
                   4628:                     if ($altkey) {
                   4629:                         if ($recursive) {
                   4630:                             if (exists($$olddata{$thiskey})) {
                   4631:                                 if ($$olddata{$thiskey} eq $data) {
                   4632:                                     $reconlychg = 1;
                   4633:                                 }
                   4634:                                 push(@delnonrec,($thiskey,$thiskey.'.type'));
                   4635:                             }
                   4636:                             if (exists($$olddata{$altkey})) {
                   4637:                                 if (defined($data) && $$olddata{$altkey} ne $data) {
                   4638:                                     $haschange = 1;
                   4639:                                 }
                   4640:                             } elsif (($data ne '') && (!$reconlychg)) {
                   4641:                                 $haschange = 1;
                   4642:                             }
                   4643:                             $storekey = $altkey;
1.563     damieng  4644:                         } else {
1.576     raeburn  4645:                             if (exists($$olddata{$altkey})) {
                   4646:                                 if ($$olddata{$altkey} eq $data) {
                   4647:                                     $reconlychg = 1;
                   4648:                                 }
                   4649:                                 push(@delrec,($altkey,$altkey.'.type'));
                   4650:                             } 
                   4651:                             if (exists($$olddata{$thiskey})) {
                   4652:                                 if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4653:                                     $haschange = 1;
                   4654:                                 }
                   4655:                             } elsif (($data ne '') && (!$reconlychg)) {
                   4656:                                 $haschange = 1;
                   4657:                             }
                   4658:                             $storekey = $thiskey;
1.563     damieng  4659:                         }
1.560     damieng  4660:                     } else {
1.576     raeburn  4661:                         if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4662:                             $haschange = 1;
                   4663:                             $storekey = $thiskey;
                   4664:                         }
                   4665:                     }
                   4666:                 }
                   4667:                 if ($reconlychg || $haschange) {
                   4668:                     unless ($env{'form.del_'.$thiskey}) {
                   4669:                         $newdata{$storekey}=$data;
                   4670:                         $newdata{$storekey.'.type'}=$typeof;
1.560     damieng  4671:                     }
                   4672:                 }
                   4673:             } elsif ($cmd eq 'del') {
                   4674:                 if ($tuname) {
1.576     raeburn  4675:                     my $error;
                   4676:                     if ($altkey) {  
                   4677:                         if (exists($$olddata{$altkey})) {
                   4678:                             if (&Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname) eq 'ok') {
                   4679:                                 &log_parmset({$tkeyrec=>''},1,$tuname,$tudom);
                   4680:                                 if ($recursive) {
                   4681:                                     $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4682:                                 }
                   4683:                             } elsif ($recursive) {
                   4684:                                 $error = 1;
                   4685:                             }
                   4686:                         }
                   4687:                         if (exists($$olddata{$thiskey})) {
                   4688:                             if (&Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname) eq 'ok') {
                   4689:                                 &log_parmset({$tkeynonrec=>''},1,$tuname,$tudom);
                   4690:                                 unless ($recursive) {
                   4691:                                     $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4692:                                 }
                   4693:                             } elsif (!$recursive) {
                   4694:                                 $error = 1;
                   4695:                             }
                   4696:                         }
1.560     damieng  4697:                     } else {
1.576     raeburn  4698:                         if (exists($$olddata{$thiskey})) {
                   4699:                             if (&Apache::lonnet::del('resourcedata',[$tkey,$tkey.'.type'],$tudom,$tuname) eq 'ok') {
                   4700:                                 &log_parmset({$tkey=>''},1,$tuname,$tudom);
                   4701:                                 $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4702:                             } else {
                   4703:                                 $error = 1;
                   4704:                             }
                   4705:                         }
                   4706:                     }
                   4707:                     if ($error) { 
1.560     damieng  4708:                         $r->print('<div class="LC_error">'.
                   4709:                             &mt('Error deleting parameters').'</div>');
                   4710:                     }
                   4711:                     &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   4712:                 } else {
1.576     raeburn  4713:                     if ($altkey) {
                   4714:                         if (exists($$olddata{$altkey})) {
                   4715:                             unless (grep(/^\Q$altkey\E$/,@delrec)) {
                   4716:                                 push(@deldata,($altkey,$altkey.'.type'));
                   4717:                             }
                   4718:                         }
                   4719:                         if (exists($$olddata{$thiskey})) {
                   4720:                             unless (grep(/^\Q$thiskey\E$/,@delnonrec)) {
                   4721:                                 push(@deldata,($thiskey,$thiskey.'.type'));
                   4722:                             }
                   4723:                         }
                   4724:                     } elsif (exists($$olddata{$thiskey})) {
                   4725:                         push(@deldata,($thiskey,$thiskey.'.type'));
                   4726:                     }
1.560     damieng  4727:                 }
1.473     amueller 4728:             }
                   4729:         }
                   4730:     }
1.207     www      4731: # Store all course level
1.144     www      4732:     my $delentries=$#deldata+1;
1.576     raeburn  4733:     my @alldels;
                   4734:     if (@delrec) {
                   4735:         push(@alldels,@delrec);
                   4736:     }
                   4737:     if (@delnonrec) {
                   4738:         push(@alldels,@delnonrec);
                   4739:     }
                   4740:     if (@deldata) {
                   4741:         push(@alldels,@deldata);
                   4742:     }
1.548     raeburn  4743:     my @newdatakeys=keys(%newdata);
1.144     www      4744:     my $putentries=$#newdatakeys+1;
1.576     raeburn  4745:     my ($delresult,$devalidate);
                   4746:     if (@alldels) {
                   4747:         if (&Apache::lonnet::del('resourcedata',\@alldels,$dom,$crs) eq 'ok') {
                   4748:             my %loghash=map { $_ => '' } @alldels;
1.560     damieng  4749:             &log_parmset(\%loghash,1);
1.576     raeburn  4750:             if ($delentries) {
                   4751:                 $r->print('<h2>'.&mt('Deleted [quant,_1,parameter]',$delentries/2).'</h2>');
                   4752:             }
                   4753:         } elsif ($delentries) {
1.560     damieng  4754:             $r->print('<div class="LC_error">'.
                   4755:                 &mt('Error deleting parameters').'</div>');
                   4756:         }
1.576     raeburn  4757:         $devalidate = 1; 
1.144     www      4758:     }
                   4759:     if ($putentries) {
1.560     damieng  4760:         if (&Apache::lonnet::put('resourcedata',\%newdata,$dom,$crs) eq 'ok') {
                   4761:                     &log_parmset(\%newdata,0);
                   4762:             $r->print('<h3>'.&mt('Saved [quant,_1,parameter]',$putentries/2).'</h3>');
                   4763:         } else {
                   4764:             $r->print('<div class="LC_error">'.
                   4765:                 &mt('Error saving parameters').'</div>');
                   4766:         }
1.576     raeburn  4767:         $devalidate = 1; 
                   4768:     }
                   4769:     if ($devalidate) {
1.560     damieng  4770:         &Apache::lonnet::devalidatecourseresdata($crs,$dom);
1.144     www      4771:     }
1.208     www      4772: }
1.207     www      4773: 
1.563     damieng  4774: # Returns the username and domain from a key created in readdata from a resourcedata key.
                   4775: #
                   4776: # @param {string} $key - the key
                   4777: # @returns {Array}
1.208     www      4778: sub extractuser {
                   4779:     my $key=shift;
1.350     albertel 4780:     return ($key=~/^$env{'request.course.id'}.\[useropt\:($match_username)\:($match_domain)\]\./);
1.208     www      4781: }
1.206     www      4782: 
1.563     damieng  4783: # Parses a parameter key and returns the components.
                   4784: #
                   4785: # @param {string} $key - 
                   4786: # @param {hash reference} $listdata - 
                   4787: # @return {Array} - (student, resource, part, parameter)
1.381     albertel 4788: sub parse_listdata_key {
                   4789:     my ($key,$listdata) = @_;
                   4790:     # split into student/section affected, and
                   4791:     # the realm (folder/resource part and parameter
1.446     bisitz   4792:     my ($student,$realm) =
1.473     amueller 4793:     ($key=~/^\Q$env{'request.course.id'}\E\.\[([^\.]+)\]\.(.+)$/);
1.381     albertel 4794:     # if course wide student would be undefined
                   4795:     if (!defined($student)) {
1.560     damieng  4796:         ($realm)=($key=~/^\Q$env{'request.course.id'}\E\.(.+)$/);
1.381     albertel 4797:     }
                   4798:     # strip off the .type if it's not the Question type parameter
                   4799:     if ($realm=~/\.type$/ && !exists($listdata->{$key.'.type'})) {
1.560     damieng  4800:         $realm=~s/\.type//;
1.381     albertel 4801:     }
                   4802:     # split into resource+part and parameter name
1.388     albertel 4803:     my ($res,    $parm) = ($realm=~/^(.*)\.(.*)$/);
                   4804:        ($res, my $part) = ($res  =~/^(.*)\.(.*)$/);
1.381     albertel 4805:     return ($student,$res,$part,$parm);
                   4806: }
                   4807: 
1.563     damieng  4808: # Prints HTML with forms for the given parameter data in overview mode (newoverview or overview).
                   4809: #
                   4810: # @param {Apache2::RequestRec} $r - the Apache request
                   4811: # @param {hash reference} $resourcedata - parameter data returned by readdata
                   4812: # @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
                   4813: # @param {string} $sortorder - realmstudent|studentrealm
                   4814: # @param {string} $caller - name of the calling sub (overview|newoverview)
                   4815: # @param {hash reference} $classlist - from loncoursedata::get_classlist
1.568     raeburn  4816: # @param {boolean} $readonly - true if editing not allowed
1.608     raeburn  4817: # @param {string} $parmlev - full|map
                   4818: # @param {hash reference} $hash_for_realm - keys: realm, values: numeric order  
                   4819: # @param {string} $pschp - selected map pc, or 'all'
1.563     damieng  4820: # @returns{integer} - number of $listdata parameters processed
1.208     www      4821: sub listdata {
1.608     raeburn  4822:     my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly,$parmlev,$hash_for_realm,$pschp)=@_;
1.552     raeburn  4823:     
1.207     www      4824: # Start list output
1.206     www      4825: 
1.122     www      4826:     my $oldsection='';
                   4827:     my $oldrealm='';
                   4828:     my $oldpart='';
1.123     www      4829:     my $pointer=0;
1.124     www      4830:     $tableopen=0;
1.145     www      4831:     my $foundkeys=0;
1.248     albertel 4832:     my %keyorder=&standardkeyorder();
1.594     raeburn  4833:     my $readonlyall = $readonly;
1.381     albertel 4834: 
1.552     raeburn  4835:     my ($secidx,%grouphash);
                   4836:     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4837:         $secidx = &Apache::loncoursedata::CL_SECTION();
1.553     raeburn  4838:         if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   4839:             %grouphash = &Apache::longroup::coursegroups();
                   4840:         } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  4841:             map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  4842:         }
1.552     raeburn  4843:     }
                   4844: 
1.576     raeburn  4845:     foreach my $key (sort {
1.560     damieng  4846:         my ($astudent,$ares,$apart,$aparm) = &parse_listdata_key($a,$listdata);
                   4847:         my ($bstudent,$bres,$bpart,$bparm) = &parse_listdata_key($b,$listdata);
1.608     raeburn  4848:         my ($aid,$bid);
                   4849:         if ($caller eq 'newoverview') {
                   4850:             if (ref($hash_for_realm) eq 'HASH') {
                   4851:                 if (($parmlev eq 'map') && ($pschp eq 'all')) {
                   4852:                     my ($aurl) = ($ares =~ /^(.+\.(?:sequence|page))___\(all\)$/);
                   4853:                     my ($burl) = ($bres =~ /^(.+\.(?:sequence|page))___\(all\)$/);
                   4854:                     $aid = $hash_for_realm->{$aurl};
                   4855:                     $bid = $hash_for_realm->{$burl};
                   4856:                 } elsif ($parmlev eq 'full') {
                   4857:                     $aid = $hash_for_realm->{$ares};
                   4858:                     $bid = $hash_for_realm->{$bres};
                   4859:                 }
                   4860:             }
                   4861:         }
1.381     albertel 4862: 
1.560     damieng  4863:         # get the numerical order for the param
                   4864:         $aparm=$keyorder{'parameter_0_'.$aparm};
                   4865:         $bparm=$keyorder{'parameter_0_'.$bparm};
1.381     albertel 4866: 
1.560     damieng  4867:         my $result=0;
1.381     albertel 4868: 
1.560     damieng  4869:         if ($sortorder eq 'realmstudent') {
1.381     albertel 4870:             if ($ares     ne $bres    ) {
1.608     raeburn  4871:                 if ($caller eq 'newoverview') {
                   4872:                     if (ref($hash_for_realm) eq 'HASH') {
                   4873:                         if (($parmlev eq 'map') && ($pschp eq 'all')) {
                   4874:                             $result = ($aid <=> $bid);
                   4875:                         } elsif ($parmlev eq 'full') {
                   4876:                             $result = ($aid <=> $bid);
                   4877:                         } else {
                   4878:                             $result = ($ares cmp $bres);
                   4879:                         }
                   4880:                     } else {
                   4881:                         $result = ($ares cmp $bres);
                   4882:                     }
                   4883:                 } else {
                   4884:                     $result = ($ares cmp $bres);
                   4885:                 }
1.446     bisitz   4886:             } elsif ($astudent ne $bstudent) {
1.560     damieng  4887:                 $result = ($astudent cmp $bstudent);
                   4888:             } elsif ($apart    ne $bpart   ) {
                   4889:                 $result = ($apart    cmp $bpart);
                   4890:             }
                   4891:         } else {
                   4892:             if      ($astudent ne $bstudent) {
                   4893:                 $result = ($astudent cmp $bstudent);
                   4894:             } elsif ($ares     ne $bres    ) {
1.608     raeburn  4895:                 if ($caller eq 'newoverview') {
                   4896:                     if (ref($hash_for_realm) eq 'HASH') {
                   4897:                         if (($parmlev eq 'map') && ($pschp eq 'all')) {
                   4898:                             $result = ($aid <=> $bid);
                   4899:                         } elsif ($parmlev eq 'full') {
                   4900:                             $result = ($aid <=> $bid);
                   4901:                         } else {
                   4902:                             $result = ($ares cmp $bres);
                   4903:                         }
                   4904:                     } else {
                   4905:                         $result = ($ares cmp $bres);
                   4906:                     }
                   4907:                 } else {
                   4908:                     $result = ($ares cmp $bres);
                   4909:                 }
1.560     damieng  4910:             } elsif ($apart    ne $bpart   ) {
                   4911:                 $result = ($apart    cmp $bpart);
                   4912:             }
1.473     amueller 4913:         }
1.446     bisitz   4914: 
1.560     damieng  4915:         if (!$result) {
1.381     albertel 4916:             if (defined($aparm) && defined($bparm)) {
1.560     damieng  4917:                 $result = ($aparm <=> $bparm);
1.381     albertel 4918:             } elsif (defined($aparm)) {
1.560     damieng  4919:                 $result = -1;
1.381     albertel 4920:             } elsif (defined($bparm)) {
1.560     damieng  4921:                 $result = 1;
                   4922:             }
1.473     amueller 4923:         }
1.381     albertel 4924: 
1.560     damieng  4925:         $result;
                   4926:         
1.576     raeburn  4927:     } keys(%{$listdata})) { # foreach my $key
                   4928:         my $thiskey = $key;
1.560     damieng  4929:         if ($$listdata{$thiskey.'.type'}) {
                   4930:             my $thistype=$$listdata{$thiskey.'.type'};
                   4931:             if ($$resourcedata{$thiskey.'.type'}) {
                   4932:                 $thistype=$$resourcedata{$thiskey.'.type'};
                   4933:             }
                   4934:             my ($middle,$part,$name)=
1.572     damieng  4935:                 ($thiskey=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.560     damieng  4936:             my $section=&mt('All Students');
1.594     raeburn  4937:             $readonly = $readonlyall;
1.599     raeburn  4938:             my $userscope;
1.576     raeburn  4939:             my $showval = $$resourcedata{$thiskey}; 
1.560     damieng  4940:             if ($middle=~/^\[(.*)\]/) {
                   4941:                 my $issection=$1;
                   4942:                 if ($issection=~/^useropt\:($match_username)\:($match_domain)/) {
                   4943:                     my ($stuname,$studom) = ($1,$2);
                   4944:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4945:                         if (ref($classlist) eq 'HASH') {
                   4946:                             if (ref($classlist->{$stuname.':'.$studom}) eq 'ARRAY') {
                   4947:                                 next unless ($classlist->{$stuname.':'.$studom}->[$secidx] eq $env{'request.course.sec'}); 
                   4948:                             }
                   4949:                         }
                   4950:                     }
                   4951:                     $section=&mt('User').": ".&Apache::loncommon::plainname($stuname,$studom);
1.599     raeburn  4952:                     $userscope = 1;
1.560     damieng  4953:                 } else {
                   4954:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4955:                         if (exists($grouphash{$issection})) {
                   4956:                             $section=&mt('Group').': '.$issection;
                   4957:                         } elsif ($issection eq $env{'request.course.sec'}) {
                   4958:                             $section = &mt('Section').': '.$issection;
                   4959:                         } else {
                   4960:                             next; 
1.552     raeburn  4961:                         }
1.560     damieng  4962:                     } else {
                   4963:                         $section=&mt('Group/Section').': '.$issection;
1.552     raeburn  4964:                     }
                   4965:                 }
1.560     damieng  4966:                 $middle=~s/^\[(.*)\]//;
                   4967:             } elsif (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4968:                 $readonly = 1;
                   4969:             }
                   4970:             $middle=~s/\.+$//;
                   4971:             $middle=~s/^\.+//;
                   4972:             my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.576     raeburn  4973:             my ($is_map,$is_recursive,$mapurl,$maplevel);
                   4974:             if ($caller eq 'overview') {
                   4975:                 if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   4976:                     $mapurl = $1;
                   4977:                     $maplevel = $2;
                   4978:                     $is_map = 1;
                   4979:                 }
                   4980:             } elsif ($caller eq 'newoverview') {
                   4981:                 if ($middle=~/^(.+)\_\_\_\((all)\)$/) {
                   4982:                     $mapurl = $1;
                   4983:                     $maplevel = $2;
                   4984:                     $is_map = 1;
                   4985:                 }
                   4986:             }
                   4987:             if ($is_map) {
1.560     damieng  4988:                 my $leveltitle = &mt('Folder/Map');
1.615     raeburn  4989:                 my $title = &Apache::lonnet::gettitle($mapurl);
1.608     raeburn  4990:                 if (ref($hash_for_realm) eq 'HASH') {
                   4991:                     if ($hash_for_realm->{$mapurl} eq '1') {
                   4992:                         $title = &mt('Main Content');
                   4993:                     }
                   4994:                 }
1.576     raeburn  4995:                 unless (($name eq 'hiddenresource') || ($name eq 'encrypturl')) {   
                   4996:                     if ($caller eq 'newoverview') {
                   4997:                         my $altkey = $thiskey;
                   4998:                         $altkey =~ s/\Q___(all)\E/___(rec)/;
                   4999:                         if ((exists($$resourcedata{$altkey})) & (!exists($$resourcedata{$thiskey}))) {
                   5000:                             $is_recursive = 1;
                   5001:                             if ($$resourcedata{$altkey.'.type'}) {
                   5002:                                 $thistype=$$resourcedata{$altkey.'.type'};
                   5003:                             }
                   5004:                             $showval = $$resourcedata{$altkey};
                   5005:                         }
                   5006:                     } elsif (($caller eq 'overview') && ($maplevel eq 'rec')) {
                   5007:                         $thiskey =~ s/\Q___(rec)\E/___(all)/;
                   5008:                         $is_recursive = 1;
                   5009:                     }
1.560     damieng  5010:                 }
1.608     raeburn  5011:                 $realm='<span class="LC_parm_scope_folder">'.$leveltitle.': '.$title.' <br /><span class="LC_parm_folder">('.$mapurl.')</span></span>';
1.560     damieng  5012:             } elsif ($middle) {
                   5013:                 my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
1.609     raeburn  5014:                 next if (($url =~ /\.(page|sequence)$/) && ($parmlev eq 'full') && ($caller eq 'newoverview'));
1.560     damieng  5015:                 $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   5016:                     ': '.&Apache::lonnet::gettitle($middle).
                   5017:                     ' <br /><span class="LC_parm_symb">('.$url.' in '.$map.' id: '.
                   5018:                     $id.')</span></span>';
                   5019:             }
                   5020:             if ($sortorder eq 'realmstudent') {
                   5021:                 if ($realm ne $oldrealm) {
                   5022:                     $r->print(&tableend()."\n<hr /><h1>$realm</h1>");
                   5023:                     $oldrealm=$realm;
                   5024:                     $oldsection='';
                   5025:                 }
                   5026:                 if ($section ne $oldsection) {
                   5027:                     $r->print(&tableend()."\n<h2>$section</h2>");
                   5028:                     $oldsection=$section;
                   5029:                     $oldpart='';
                   5030:                 }
1.552     raeburn  5031:             } else {
1.560     damieng  5032:                 if ($section ne $oldsection) {
                   5033:                     $r->print(&tableend()."\n<hr /><h1>$section</h1>");
                   5034:                     $oldsection=$section;
                   5035:                     $oldrealm='';
                   5036:                 }
                   5037:                 if ($realm ne $oldrealm) {
                   5038:                     $r->print(&tableend()."\n<h2>$realm</h2>");
                   5039:                     $oldrealm=$realm;
                   5040:                     $oldpart='';
1.552     raeburn  5041:                 }
                   5042:             }
1.560     damieng  5043:             if ($part ne $oldpart) {
                   5044:                 $r->print(&tableend().
                   5045:                     "\n".'<span class="LC_parm_part">'.&mt('Part').": $part</span>");
                   5046:                 $oldpart=$part;
1.556     raeburn  5047:             }
1.560     damieng  5048:     #
                   5049:     # Ready to print
                   5050:     #
1.470     raeburn  5051:             my $parmitem = &standard_parameter_names($name);
1.619     raeburn  5052:             my $advice;
                   5053:             if (($name eq 'mapalias') && ($middle) && (!$is_map)) {
                   5054:                 if ($middle =~ m{^uploaded/}) {
                   5055:                     $advice = &mt('Use Course Editor to set this.');
                   5056:                 } else {
                   5057:                     $advice = &mt('Use Resource Assembly Tool to set this.');
                   5058:                 }
                   5059:                 $advice = '<br /><span class="LC_fontsize_small LC_cusr_emph">'.$advice.'</span>';
                   5060:             }
1.576     raeburn  5061:             $r->print(&tablestart($readonly,$is_map).
1.560     damieng  5062:                 &Apache::loncommon::start_data_table_row().
                   5063:                 '<td><b>'.&mt($parmitem).
1.619     raeburn  5064:                 '</b>'.$advice.'</td>');
1.560     damieng  5065:             unless ($readonly) {
1.599     raeburn  5066:                 my $disabled;
                   5067:                 if (($name eq 'availablestudent') &&
                   5068:                     (($showval eq '') || ($userscope))) {
                   5069:                     $disabled = ' disabled="disabled"';
1.619     raeburn  5070:                 } elsif (($name eq 'mapalias') && ($showval eq '')) {
                   5071:                     $disabled = ' disabled="disabled"';
1.599     raeburn  5072:                 }
1.560     damieng  5073:                 $r->print('<td><input type="checkbox" name="del_'.
1.599     raeburn  5074:                         $thiskey.'"'.$disabled.' /></td>');
1.560     damieng  5075:             }
                   5076:             $r->print('<td>');
                   5077:             $foundkeys++;
                   5078:             if (&isdateparm($thistype)) {
                   5079:                 my $jskey='key_'.$pointer;
                   5080:                 my $state;
                   5081:                 $pointer++;
                   5082:                 if ($readonly) {
                   5083:                     $state = 'disabled';
                   5084:                 }
                   5085:                 $r->print(
                   5086:                     &Apache::lonhtmlcommon::date_setter('parmform',
                   5087:                                                         $jskey,
1.576     raeburn  5088:                                                         $showval,
1.560     damieng  5089:                                                         '',1,$state));
                   5090:                 unless  ($readonly) {
                   5091:                     $r->print(
                   5092:     '<input type="hidden" name="datepointer_'.$thiskey.'" value="'.$jskey.'" />'.
1.576     raeburn  5093:     (($showval!=0)?'<span class="LC_nobreak"><a href="/adm/parmset?&action=dateshift1&timebase='.$showval.'">'.
1.560     damieng  5094:     &mt('Shift all dates based on this date').'</a></span>':'').
1.576     raeburn  5095:     &date_sanity_info($showval)
1.560     damieng  5096:                     );
                   5097:                 }
                   5098:             } elsif ($thistype eq 'date_interval') {
                   5099:                 $r->print(&date_interval_selector($thiskey,$name,
1.576     raeburn  5100:                           $showval,$readonly));
1.560     damieng  5101:             } elsif ($thistype =~ m/^string/) {
1.599     raeburn  5102:                 if ($name eq 'availablestudent') {
                   5103:                     $readonly = 1;
1.619     raeburn  5104:                 } elsif (($name eq 'mapalias') && ($showval eq '')) {
                   5105:                     $readonly = 1;
1.599     raeburn  5106:                 }
1.560     damieng  5107:                 $r->print(&string_selector($thistype,$thiskey,
1.576     raeburn  5108:                           $showval,$name,$readonly));
1.560     damieng  5109:             } else {
1.576     raeburn  5110:                 $r->print(&default_selector($thiskey,$showval,$readonly));
1.552     raeburn  5111:             }
1.560     damieng  5112:             unless ($readonly) {
                   5113:                 $r->print('<input type="hidden" name="typeof_'.$thiskey.'" value="'.
                   5114:                         $thistype.'" />');
1.552     raeburn  5115:             }
1.576     raeburn  5116:             $r->print('</td>');
                   5117:             if ($is_map) {
                   5118:                 if (($name eq 'encrypturl') || ($name eq 'hiddenresource')) {
                   5119:                     $r->print('<td><table><tr><td>'.&mt('Yes').'</td></tr></table></td>');
                   5120:                 } else {
                   5121:                     my ($disabled,$recon,$recoff);
                   5122:                     if ($readonly) {
                   5123:                         $disabled = ' disabled="disabled"';
                   5124:                     }
                   5125:                     if ($is_recursive) {
                   5126:                         $recon = ' checked="checked"';
                   5127:                     } else {
                   5128:                         $recoff = ' checked="checked"';
                   5129:                     }
                   5130:                     $r->print('<td><table><tr><td><label><input type="radio" name="rec_'.$thiskey.'" value="1"'.$recon.$disabled.' />'.&mt('Yes').'</label>'.
                   5131:                               '</td><td><label><input type="radio" name="rec_'.$thiskey.'" value="0"'.$recoff.$disabled.' />'.&mt('No').'</label></td></tr></table></td>');
                   5132:                 }
                   5133:             }
                   5134:             $r->print(&Apache::loncommon::end_data_table_row());
1.473     amueller 5135:         }
1.121     www      5136:     }
1.208     www      5137:     return $foundkeys;
                   5138: }
                   5139: 
1.563     damieng  5140: # Returns a string representing the interval, directly using form data matching the given key.
                   5141: # The returned string may also include information related to proctored exams.
                   5142: # Format: seconds['_done'[':'done button title':']['_proctor'['_'proctor key]]]
                   5143: #
                   5144: # @param {string} $key - suffix for form fields related to the interval
                   5145: # @returns {string}
1.385     albertel 5146: sub get_date_interval_from_form {
                   5147:     my ($key) = @_;
                   5148:     my $seconds = 0;
1.611     raeburn  5149:     my $numnotnull = 0;
1.385     albertel 5150:     foreach my $which (['days', 86400],
1.473     amueller 5151:                ['hours', 3600],
                   5152:                ['minutes', 60],
                   5153:                ['seconds',  1]) {
1.560     damieng  5154:         my ($name, $factor) = @{ $which };
                   5155:         if (defined($env{'form.'.$name.'_'.$key})) {
1.611     raeburn  5156:             unless ($env{'form.'.$name.'_'.$key} eq '') {
                   5157:                 $numnotnull ++;
                   5158:                 $seconds += $env{'form.'.$name.'_'.$key} * $factor;
                   5159:             }
1.560     damieng  5160:         }
1.473     amueller 5161:     }
1.560     damieng  5162:     if (($key =~ /\.interval$/) &&
                   5163:             (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) {
1.559     raeburn  5164:         if ($env{'form.done_'.$key.'_buttontext'}) {
                   5165:             $env{'form.done_'.$key.'_buttontext'} =~ s/\://g;
                   5166:             $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':';
                   5167:             if ($env{'form.done_'.$key} eq '_done_proctor') {
                   5168:                 $seconds .= '_proctor';
                   5169:             }
                   5170:         } else {
                   5171:             $seconds .= $env{'form.done_'.$key}; 
                   5172:         }
                   5173:         if (($env{'form.done_'.$key} eq '_done_proctor') && 
1.560     damieng  5174:                 ($env{'form.done_'.$key.'_proctorkey'})) {
1.558     raeburn  5175:             $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};
                   5176:         }
1.554     raeburn  5177:     }
1.611     raeburn  5178:     return if (!$numnotnull);
1.385     albertel 5179:     return $seconds;
                   5180: }
                   5181: 
                   5182: 
1.563     damieng  5183: # Returns HTML to enter a text value for a parameter.
                   5184: #
                   5185: # @param {string} $thiskey - parameter key
                   5186: # @param {string} $showval - the current value
                   5187: # @param {boolean} $readonly - true if the field should not be made editable
                   5188: # @returns {string}
1.383     albertel 5189: sub default_selector {
1.552     raeburn  5190:     my ($thiskey, $showval, $readonly) = @_;
                   5191:     my $disabled;
                   5192:     if ($readonly) {
                   5193:         $disabled = ' disabled="disabled"';
                   5194:     }
                   5195:     return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'"'.$disabled.' />';
1.383     albertel 5196: }
                   5197: 
1.563     damieng  5198: # Returns HTML to enter allow/deny rules related to IP addresses.
                   5199: #
                   5200: # @param {string} $thiskey - parameter key
                   5201: # @param {string} $showval - the current value
                   5202: # @param {boolean} $readonly - true if the fields should not be made editable
                   5203: # @returns {string}
1.549     raeburn  5204: sub string_ip_selector {
1.552     raeburn  5205:     my ($thiskey, $showval, $readonly) = @_;
1.549     raeburn  5206:     my %access = (
                   5207:                    allow => [],
                   5208:                    deny  => [],
                   5209:                  );
                   5210:     if ($showval ne '') {
                   5211:         my @current;
                   5212:         if ($showval =~ /,/) {
                   5213:             @current = split(/,/,$showval);
                   5214:         } else {
                   5215:             @current = ($showval);
                   5216:         }
                   5217:         foreach my $item (@current) {
                   5218:             if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   5219:                 push(@{$access{'deny'}},$1);
                   5220:             } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   5221:                 push(@{$access{'allow'}},$item);
                   5222:             }
                   5223:         }
                   5224:     }
                   5225:     if (!@{$access{'allow'}}) {
                   5226:         @{$access{'allow'}} = ('');
                   5227:     }
                   5228:     if (!@{$access{'deny'}}) {
                   5229:         @{$access{'deny'}} = ('');
                   5230:     }
1.552     raeburn  5231:     my ($disabled,$addmore);
1.567     raeburn  5232:     if ($readonly) {
1.552     raeburn  5233:         $disabled=' disabled="disabled"';
                   5234:     } else {
                   5235:         $addmore = "\n".'<button class="LC_add_ipacc_button">'.&mt('Add more').'</button>';
                   5236:     }
1.549     raeburn  5237:     my $output = '<input type="hidden" name="set_'.$thiskey.'" />
                   5238: <table><tr><th>'.&mt('Allow from').'</th><th>'.&mt('Deny from').'</th></tr><tr>';
                   5239:     foreach my $acctype ('allow','deny') {
                   5240:         $output .= '
                   5241: <td valign="top">
                   5242: <div class="LC_string_ipacc_wrap" id="LC_string_ipacc_'.$acctype.'_'.$thiskey.'">
                   5243:   <div class="LC_string_ipacc_inner">'."\n";
                   5244:         my $num = 0;
                   5245:         foreach my $curr (@{$access{$acctype}}) {
1.552     raeburn  5246:             $output .= '<div><input type="text" name="setip'.$acctype.'_'.$thiskey.'" value="'.$curr.'"'.$disabled.' />';
1.549     raeburn  5247:             if ($num > 0) {
                   5248:                 $output .= '<a href="#" class="LC_remove_ipacc">'.&mt('Remove').'</a>'; 
                   5249:             }
                   5250:             $output .= '</div>'."\n";
                   5251:             $num ++;
                   5252:         }
                   5253:         $output .= '
1.552     raeburn  5254:   </div>'.$addmore.'
1.549     raeburn  5255: </div>
                   5256: </td>';
                   5257:    }
                   5258:    $output .= '
                   5259: </tr>
                   5260: </table>'."\n";
                   5261:     return $output;
                   5262: }
                   5263: 
1.588     raeburn  5264: sub string_deeplink_selector {
                   5265:     my ($thiskey, $showval, $readonly) = @_;
1.616     raeburn  5266:     my (@tables,%values,@current,%titles,%options,%optiontext,%defaults,
                   5267:         %selectnull,%domlti,%crslti,@possmenus,%components);
                   5268:     @tables = ('upper','lower');
                   5269:     %components = (
                   5270:                     upper => ['state','others','listing','scope'],
                   5271:                     lower => ['protect','menus','target','exit'],
                   5272:                   );   
1.588     raeburn  5273:     %titles = &Apache::lonlocal::texthash (
1.601     raeburn  5274:                   state   => 'Access status',
                   5275:                   others  => 'Hide other resources',
1.588     raeburn  5276:                   listing => 'In Contents and/or Gradebook',
                   5277:                   scope   => 'Access scope for link',
1.601     raeburn  5278:                   protect => 'Link protection',
1.597     raeburn  5279:                   menus   => 'Menu Items Displayed',
1.613     raeburn  5280:                   target  => 'Embedded?',
1.616     raeburn  5281:                   exit    => 'Exit Tool Button?',
1.588     raeburn  5282:               );
                   5283:     %options = (
1.601     raeburn  5284:                    state   => ['only','off','both'],
                   5285:                    others  => ['hide','unhide'],
1.588     raeburn  5286:                    listing => ['full','absent','grades','details','datestatus'],
                   5287:                    scope   => ['res','map','rec'],
1.601     raeburn  5288:                    protect => ['none','key','ltid','ltic'],
1.597     raeburn  5289:                    menus   => ['std','colls'],
1.613     raeburn  5290:                    target  => ['_self','_top'],
1.616     raeburn  5291:                    exit    => ['no','yes','url'],
1.588     raeburn  5292:                );
                   5293:     %optiontext = &Apache::lonlocal::texthash (
1.601     raeburn  5294:                     only       => 'deep only',
                   5295:                     off        => 'deeplink off',
                   5296:                     both       => 'regular + deep',
                   5297:                     hide       => 'Hidden',
                   5298:                     unhide     => 'Unhidden',
1.588     raeburn  5299:                     full       => 'Listed (linked) in both',
                   5300:                     absent     => 'Not listed',
                   5301:                     grades     => 'Listed in grades only',
                   5302:                     details    => 'Listed (unlinked) in both',
                   5303:                     datestatus => 'Listed (unlinked) inc. status in both',
                   5304:                     res        => 'resource only',
                   5305:                     map        => 'enclosing map/folder',
                   5306:                     rec        => 'recursive map/folder',
1.601     raeburn  5307:                     none       => 'not in use',
                   5308:                     key        => 'key access',
                   5309:                     ltic       => 'LTI access (course)',
                   5310:                     ltid       => 'LTI access (domain)' ,
1.597     raeburn  5311:                     std        => 'Standard (all menus)',
                   5312:                     colls      => 'Numbered collection',
1.614     raeburn  5313:                     _self      => 'Embedded',
1.613     raeburn  5314:                     _top       => 'Not embedded',
1.616     raeburn  5315:                     no         => 'Not in use',
                   5316:                     yes        => 'In use, no URL redirect',
                   5317:                     url        => 'In use, redirect to URL',  
1.597     raeburn  5318:                   );
                   5319:     %selectnull = &Apache::lonlocal::texthash (
1.601     raeburn  5320:                     ltic => 'Select Launcher',
                   5321:                     ltid => 'Select Launcher', 
1.597     raeburn  5322:                     colls => 'Select',
1.588     raeburn  5323:                   );
                   5324:     if ($showval =~ /,/) {
1.597     raeburn  5325:         %values=();
1.588     raeburn  5326:         @current = split(/,/,$showval);
1.601     raeburn  5327:         ($values{'state'}) = ($current[0] =~ /^(only|off|both)$/);
                   5328:         ($values{'others'}) = ($current[1] =~ /^(hide|unhide)$/);
                   5329:         ($values{'listing'}) = ($current[2] =~ /^(full|absent|grades|details|datestatus)$/);
                   5330:         ($values{'scope'}) = ($current[3] =~ /^(res|map|rec)$/);
                   5331:         ($values{'protect'}) = ($current[4] =~ /^(key:[a-zA-Z\d_.!\@#\$%^&*()+=-]+|ltic:\d+|ltid:\d+)$/);
                   5332:         ($values{'menus'}) = ($current[5] =~ /^(\d+)$/);
1.613     raeburn  5333:         ($values{'target'}) = ($current[6] =~ /^(_self|_top)$/);
1.616     raeburn  5334:         ($values{'exit'}) = ($current[7] =~ /^((?:(?:yes|url)(?:|\:[^:;"',]+))|no)$/);
1.588     raeburn  5335:     } else {
1.601     raeburn  5336:         $defaults{'state'} = 'off',
                   5337:         $defaults{'others'} = 'unhide',
1.588     raeburn  5338:         $defaults{'listing'} = 'full';
                   5339:         $defaults{'scope'} = 'res';
1.601     raeburn  5340:         $defaults{'protect'} = 'none';
1.597     raeburn  5341:         $defaults{'menus'} = '0';
1.613     raeburn  5342:         $defaults{'target'} = '_top';
1.616     raeburn  5343:         $defaults{'exit'} = 'yes';
1.588     raeburn  5344:     }
                   5345:     my $disabled;
                   5346:     if ($readonly) {
                   5347:         $disabled=' disabled="disabled"';
                   5348:     }
1.601     raeburn  5349:     my %courselti =
                   5350:         &Apache::lonnet::get_course_lti($env{'course.'.$env{'request.course.id'}.'.num'},
1.620     raeburn  5351:                                         $env{'course.'.$env{'request.course.id'}.'.domain'},
                   5352:                                         'provider');
1.601     raeburn  5353:     foreach my $item (keys(%courselti)) {
                   5354:         if (ref($courselti{$item}) eq 'HASH') {
                   5355:             $crslti{$item} = $courselti{$item}{'name'};
                   5356:         }
                   5357:     }
                   5358:     my %lti =
1.588     raeburn  5359:         &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604     raeburn  5360:                                         'linkprot');
1.588     raeburn  5361:     foreach my $item (keys(%lti)) {
1.604     raeburn  5362:         if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
                   5363:             $domlti{$item} = $lti{$item}{'name'};
1.588     raeburn  5364:         }
                   5365:     }
1.597     raeburn  5366:     if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
                   5367:         foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
                   5368:             my ($num,$value) = split(/\%/,$item);
                   5369:             if ($num =~ /^\d+$/) {
                   5370:                 push(@possmenus,$num);
                   5371:             }
                   5372:         }
                   5373:     }
                   5374: 
1.616     raeburn  5375:     my $output = '<input type="hidden" name="set_'.$thiskey.'" />';
                   5376:     foreach my $table ('upper','lower') {
                   5377:         next unless (ref($components{$table}) eq 'ARRAY');
                   5378:         $output .= '<table width="100%"><tr>';
                   5379:         foreach my $item (@{$components{$table}}) {
                   5380:             $output .= '<th>'.$titles{$item}.'</th>';
                   5381:         }
                   5382:         $output .= '</tr><tr>';
                   5383:         foreach my $item (@{$components{$table}}) {
                   5384:             $output .= '<td>';
                   5385:             if (($item eq 'protect') || ($item eq 'menus') || ($item eq 'exit')) {
                   5386:                 my $selected = $values{$item};
                   5387:                 foreach my $option (@{$options{$item}}) {
                   5388:                     if ($item eq 'protect') { 
                   5389:                         if ($option eq 'ltid') {
                   5390:                             next unless (keys(%domlti));
                   5391:                         } elsif ($option eq 'ltic') {
                   5392:                             next unless (keys(%crslti));
                   5393:                         }
                   5394:                     } elsif (($item eq 'menus') && ($option eq 'colls')) {
                   5395:                         next unless (@possmenus);
                   5396:                     }
                   5397:                     my $checked;
                   5398:                     if ($item eq 'menus') {
                   5399:                         if (($selected =~ /^\d+$/) && (@possmenus) &&
                   5400:                             (grep(/^\Q$selected\E$/,@possmenus))) {
                   5401:                             if ($option eq 'colls') {
                   5402:                                 $checked = ' checked="checked"';
                   5403:                             }
                   5404:                         } elsif (($option eq 'std') && ($selected == 0) && ($selected ne '')) {
1.597     raeburn  5405:                             $checked = ' checked="checked"';
                   5406:                         }
1.616     raeburn  5407:                     } elsif ($selected =~ /^\Q$option\E/) {
1.597     raeburn  5408:                         $checked = ' checked="checked"';
                   5409:                     }
1.616     raeburn  5410:                     my $onclick;
                   5411:                     unless ($readonly) {
                   5412:                         my $esc_key = &js_escape($thiskey);
                   5413:                         $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"';
                   5414:                     }
                   5415:                     $output .= '<span class="LC_nobreak"><label>'.
                   5416:                                '<input type="radio" name="deeplink_'.$item.'_'.$thiskey.'" value="'.$option.'"'.$onclick.$disabled.$checked.' />'."\n".
                   5417:                                $optiontext{$option}.'</label>';
                   5418:                     if (($item eq 'protect') && ($option eq 'key')) {
                   5419:                         my $visibility="hidden";
                   5420:                         my $currkey;
                   5421:                         if ($checked) {
                   5422:                             $visibility = "text";
                   5423:                             $currkey = (split(/\:/,$values{$item}))[1];
                   5424:                         }
                   5425:                         $output .= '&nbsp;'.
                   5426:                                    '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="10"'.$disabled.' />';
                   5427:                     } elsif (($option eq 'ltic') || ($option eq 'ltid') || ($option eq 'colls')) {
                   5428:                         my $display="none";
                   5429:                         my ($current,$blankcheck,@possibles);
                   5430:                         if ($checked) {
                   5431:                             $display = 'inline-block';
                   5432:                             if (($option eq 'ltic') || ($option eq 'ltid'))  {
                   5433:                                 $current = (split(/\:/,$selected))[1];
                   5434:                             } else {
                   5435:                                 $current = $selected;
                   5436:                             }
1.597     raeburn  5437:                         } else {
1.616     raeburn  5438:                             $blankcheck = ' selected="selected"';
1.597     raeburn  5439:                         }
1.601     raeburn  5440:                         if ($option eq 'ltid') {
1.616     raeburn  5441:                             @possibles = keys(%domlti);
1.601     raeburn  5442:                         } elsif ($option eq 'ltic') {
1.616     raeburn  5443:                             @possibles = keys(%crslti); 
                   5444:                         } else {
                   5445:                             @possibles = @possmenus;
                   5446:                         }
                   5447:                         $output .= '<div id="deeplinkdiv_'.$option.'_'.$item.'_'.$thiskey.'"'.
                   5448:                                    ' style="display: '.$display.'">&nbsp;<select name="'.
                   5449:                                    'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>';
                   5450:                         if (@possibles > 1) {
                   5451:                             $output .= '<option value=""'.$blankcheck.'>'.$selectnull{$option}.
                   5452:                                        '</option>'."\n";
                   5453:                         }
                   5454:                         foreach my $poss (sort { $a <=> $b } @possibles) {
                   5455:                             my $selected;
                   5456:                             if (($poss == $current) || (scalar(@possibles) ==1)) {
                   5457:                                 $selected = ' selected="selected"';
                   5458:                             }
                   5459:                             my $shown = $poss;
                   5460:                             if ($option eq 'ltid') {
                   5461:                                 $shown = $domlti{$poss};
                   5462:                             } elsif ($option eq 'ltic') {
                   5463:                                 $shown = $crslti{$poss};
                   5464:                             }
                   5465:                             $output .= '<option value="'.$poss.'"'.$selected.'>'.$shown.'</option>';
                   5466:                         }
                   5467:                         $output .= '</select></div>';
                   5468:                     }
                   5469:                     $output .= '</span> ';
                   5470:                 }
                   5471:                 if ($item eq 'exit') {
                   5472:                     my $exitsty = 'none';
                   5473:                     my $displayval;
                   5474:                     if ($values{$item} =~ /^(yes|url)/) { 
                   5475:                         $exitsty = 'inline-block';
                   5476:                         my $currval = (split(/\:/,$values{$item}))[1];
                   5477:                         if ($currval eq '') {
                   5478:                             $displayval = 'Exit Tool';
                   5479:                         } else {
                   5480:                             $displayval = $currval;
1.597     raeburn  5481:                         }
1.588     raeburn  5482:                     }
1.616     raeburn  5483:                     $output .= '<div id="deeplinkdiv_'.$item.'_'.$thiskey.'"'.
                   5484:                                ' style="display: '.$exitsty.'"><br />'.&mt('Button text').': '.
                   5485:                                '<input type="text" name="deeplink_exittext_'.$thiskey.'"'.
                   5486:                                ' id="deeplink_exittext_'.$thiskey.'" value="'.$displayval.'"'.
                   5487:                                ' size="10"'.$disabled.' /></div>';
1.588     raeburn  5488:                 }
1.616     raeburn  5489:             } else {
                   5490:                 my $selected = $values{$item};
                   5491:                 my $defsel;
                   5492:                 if ($selected eq '') {
                   5493:                     $defsel = ' selected="selected"';
                   5494:                 }
                   5495:                 $output .= '<select name="deeplink_'.$item.'_'.$thiskey.'"'.$disabled.'>'."\n".
                   5496:                            '<option value=""'.$defsel.'>'.&mt('Please select').'</option>'."\n";
                   5497:                 foreach my $option (@{$options{$item}}) {
                   5498:                     $output .= '<option value="'.$option.'"';
                   5499:                     if ($option eq $selected) {
                   5500:                         $output .= ' selected="selected"';
                   5501:                     }
                   5502:                     $output .= '>'.$optiontext{$option}.'</option>';
1.588     raeburn  5503:                 }
1.616     raeburn  5504:                 $output .= '</select>';
1.588     raeburn  5505:             }
1.616     raeburn  5506:             $output .= '</td>';
                   5507:         }
                   5508:         $output .= '</tr></table>'."\n";
                   5509:         if ($table eq 'upper') {
                   5510:             $output .= '<br />';
1.588     raeburn  5511:         }
                   5512:     }
                   5513:     return $output;
                   5514: }
                   5515: 
1.560     damieng  5516: 
                   5517: { # block using some constants related to parameter types (overview mode)
                   5518: 
1.446     bisitz   5519: my %strings =
1.383     albertel 5520:     (
                   5521:      'string_yesno'
                   5522:              => [[ 'yes', 'Yes' ],
1.560     damieng  5523:                  [ 'no', 'No' ]],
1.383     albertel 5524:      'string_problemstatus'
                   5525:              => [[ 'yes', 'Yes' ],
1.473     amueller 5526:          [ 'answer', 'Yes, and show correct answer if they exceed the maximum number of tries.' ],
                   5527:          [ 'no', 'No, don\'t show correct/incorrect feedback.' ],
                   5528:          [ 'no_feedback_ever', 'No, show no feedback at all.' ]],
1.504     raeburn  5529:      'string_questiontype'
                   5530:              => [[ 'problem', 'Standard Problem'],
                   5531:                  [ 'survey', 'Survey'],
                   5532:                  [ 'anonsurveycred', 'Anonymous Survey (credit for submission)'],
1.530     bisitz   5533:                  [ 'exam', 'Bubblesheet Exam'],
1.504     raeburn  5534:                  [ 'anonsurvey', 'Anonymous Survey'],
                   5535:                  [ 'randomizetry', 'New Randomization Each N Tries (default N=1)'],
                   5536:                  [ 'practice', 'Practice'],
                   5537:                  [ 'surveycred', 'Survey (credit for submission)']],
1.514     raeburn  5538:      'string_lenient'
                   5539:              => [['yes', 'Yes' ],
                   5540:                  [ 'no', 'No' ],
1.549     raeburn  5541:                  [ 'default', 'Default - only bubblesheet grading is lenient' ],
                   5542:                  [ 'weighted', 'Yes, weighted (optionresponse in checkbox mode)' ]],
1.521     raeburn  5543:      'string_discussvote'
                   5544:              => [['yes','Yes'],
                   5545:                  ['notended','Yes, unless discussion ended'],
                   5546:                  ['no','No']],
1.549     raeburn  5547:      'string_ip'
                   5548:              => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
1.587     raeburn  5549:                  ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']], 
                   5550:      'string_deeplink'
1.616     raeburn  5551:              => [['on','Set choices for link protection, resource listing, access scope, shown menu items, embedding, and exit link']],
1.621   ! raeburn  5552:      'string_tex'
        !          5553:              => [['tth', 'tth (TeX to HTML)'],
        !          5554:                  ['mathjax', 'MathJax']],
1.587     raeburn  5555:     );
                   5556:    
1.383     albertel 5557: 
1.549     raeburn  5558: my %stringmatches = (
                   5559:          'string_lenient'
                   5560:               => [['weighted','^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$'],],
                   5561:          'string_ip'
                   5562:               => [['_allowfrom_','[^\!]+'],
                   5563:                   ['_denyfrom_','\!']],
1.588     raeburn  5564:          'string_deeplink'
1.616     raeburn  5565:               => [['on','^(only|off|both)\,(hide|unhide)\,(full|absent|grades|details|datestatus)\,(res|map|rec)\,(none|key\:\w+|ltic\:\d+|ltid\:\d+)\,(\d+|)\,_(self|top),(yes|url|no)(|:[^:;\'",]+)$']],
1.549     raeburn  5566:     );
                   5567: 
                   5568: my %stringtypes = (
                   5569:                     type         => 'string_questiontype',
                   5570:                     lenient      => 'string_lenient',
                   5571:                     retrypartial => 'string_yesno',
                   5572:                     discussvote  => 'string_discussvote',
                   5573:                     examcode     => 'string_examcode',
                   5574:                     acc          => 'string_ip',
1.587     raeburn  5575:                     deeplink     => 'string_deeplink',
1.621   ! raeburn  5576:                     texdisplay   => 'string_tex',
1.549     raeburn  5577:                   );
                   5578: 
1.563     damieng  5579: # Returns the possible values and titles for a given string type, or undef if there are none.
                   5580: # Used by courseprefs.
                   5581: #
                   5582: # @param {string} $string_type - a parameter type for strings
                   5583: # @returns {array reference} - 2D array, containing values and English titles
1.505     raeburn  5584: sub standard_string_options {
                   5585:     my ($string_type) = @_;
                   5586:     if (ref($strings{$string_type}) eq 'ARRAY') {
                   5587:         return $strings{$string_type};
                   5588:     }
                   5589:     return;
                   5590: }
1.383     albertel 5591: 
1.563     damieng  5592: # Returns regular expressions to match kinds of string types, or undef if there are none.
                   5593: #
                   5594: # @param {string} $string_type - a parameter type for strings
                   5595: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.549     raeburn  5596: sub standard_string_matches {
                   5597:     my ($string_type) = @_;
                   5598:     if (ref($stringmatches{$string_type}) eq 'ARRAY') {
                   5599:         return $stringmatches{$string_type};
                   5600:     }
                   5601:     return;
                   5602: }
                   5603: 
1.563     damieng  5604: # Returns a parameter type for a given parameter with a string type, or undef if not known.
                   5605: #
                   5606: # @param {string} $name - parameter name
                   5607: # @returns {string}
1.549     raeburn  5608: sub get_stringtype {
                   5609:     my ($name) = @_;
                   5610:     if (exists($stringtypes{$name})) {
                   5611:         return $stringtypes{$name};
                   5612:     }
                   5613:     return;
                   5614: }
                   5615: 
1.563     damieng  5616: # Returns HTML to edit a string parameter.
                   5617: #
                   5618: # @param {string} $thistype - parameter type
                   5619: # @param {string} $thiskey - parameter key
                   5620: # @param {string} $showval - parameter current value
                   5621: # @param {string} $name - parameter name
                   5622: # @param {boolean} $readonly - true if the values should not be made editable
                   5623: # @returns {string}
1.383     albertel 5624: sub string_selector {
1.552     raeburn  5625:     my ($thistype, $thiskey, $showval, $name, $readonly) = @_;
1.446     bisitz   5626: 
1.383     albertel 5627:     if (!exists($strings{$thistype})) {
1.552     raeburn  5628:         return &default_selector($thiskey,$showval,$readonly);
1.383     albertel 5629:     }
                   5630: 
1.504     raeburn  5631:     my %skiptype;
1.514     raeburn  5632:     if (($thistype eq 'string_questiontype') || 
1.560     damieng  5633:             ($thistype eq 'string_lenient') ||
                   5634:             ($thistype eq 'string_discussvote') ||
                   5635:             ($thistype eq 'string_ip') ||
1.588     raeburn  5636:             ($thistype eq 'string_deeplink') ||
1.621   ! raeburn  5637:             ($thistype eq 'string_tex') ||
1.560     damieng  5638:             ($name eq 'retrypartial')) {
1.504     raeburn  5639:         my ($got_chostname,$chostname,$cmajor,$cminor); 
                   5640:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   5641:             next unless (ref($possibilities) eq 'ARRAY');
1.514     raeburn  5642:             my ($parmval, $description) = @{ $possibilities };
1.549     raeburn  5643:             my $parmmatch;
                   5644:             if (ref($stringmatches{$thistype}) eq 'ARRAY') {
                   5645:                 foreach my $item (@{$stringmatches{$thistype}}) {
                   5646:                     if (ref($item) eq 'ARRAY') {
                   5647:                         if ($parmval eq $item->[0]) {
                   5648:                             $parmmatch = $parmval;
                   5649:                             $parmval = '';
                   5650:                             last;
                   5651:                         }
                   5652:                     }
                   5653:                 }
                   5654:             }
                   5655:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"}; 
1.504     raeburn  5656:             if ($needsrelease) {
                   5657:                 unless ($got_chostname) {
1.514     raeburn  5658:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.504     raeburn  5659:                     $got_chostname = 1;
                   5660:                 }
1.557     raeburn  5661:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.549     raeburn  5662:                                                        $needsrelease,$cmajor,$cminor);
1.504     raeburn  5663:                 if ($needsnewer) {
1.549     raeburn  5664:                     if ($parmmatch ne '') {
                   5665:                         $skiptype{$parmmatch} = 1;
                   5666:                     } elsif ($parmval ne '') {
                   5667:                         $skiptype{$parmval} = 1;
                   5668:                     }
1.504     raeburn  5669:                 }
                   5670:             }
                   5671:         }
                   5672:     }
1.549     raeburn  5673: 
                   5674:     if ($thistype eq 'string_ip') {
1.552     raeburn  5675:         return &string_ip_selector($thiskey,$showval,$readonly); 
1.588     raeburn  5676:     } elsif ($thistype eq 'string_deeplink') {
                   5677:         return &string_deeplink_selector($thiskey,$showval,$readonly);
1.549     raeburn  5678:     }
1.504     raeburn  5679: 
1.552     raeburn  5680:     my ($result,$disabled);
                   5681: 
                   5682:     if ($readonly) {
                   5683:         $disabled = ' disabled="disabled"';
                   5684:     }
1.504     raeburn  5685:     my $numinrow = 3;
                   5686:     if ($thistype eq 'string_problemstatus') {
                   5687:         $numinrow = 2;
                   5688:     } elsif ($thistype eq 'string_questiontype') {
                   5689:         if (keys(%skiptype) > 0) {
                   5690:              $numinrow = 4;
                   5691:         }
                   5692:     }
                   5693:     my $rem;
                   5694:     if (ref($strings{$thistype}) eq 'ARRAY') {
                   5695:         my $i=0;
                   5696:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   5697:             next unless (ref($possibilities) eq 'ARRAY');
                   5698:             my ($name, $description) = @{ $possibilities };
1.549     raeburn  5699:             next if ($skiptype{$name});
1.504     raeburn  5700:             $rem = $i%($numinrow);
                   5701:             if ($rem == 0) {
                   5702:                 if ($i > 0) {
                   5703:                     $result .= '</tr>';
                   5704:                 }
                   5705:                 $result .= '<tr>';
                   5706:             }
1.549     raeburn  5707:             my $colspan;
                   5708:             if ($i == @{ $strings{$thistype} }-1) {
                   5709:                 $rem = @{ $strings{$thistype} }%($numinrow);
                   5710:                 if ($rem) {
                   5711:                     my $colsleft = $numinrow - $rem;
                   5712:                     if ($colsleft) {
                   5713:                         $colspan = $colsleft+1;
                   5714:                         $colspan = ' colspan="'.$colspan.'"';
                   5715:                     }
                   5716:                 }
                   5717:             }
                   5718:             my ($add,$onchange,$css_class);
                   5719:             if ($thistype eq 'string_lenient') {
                   5720:                 if ($name eq 'weighted') {
                   5721:                     my $display;
                   5722:                     my %relatives = &Apache::lonlocal::texthash(
                   5723:                                         corrchkd     => 'Correct (checked)',
                   5724:                                         corrunchkd   => 'Correct (unchecked)',
                   5725:                                         incorrchkd   => 'Incorrect (checked)',
                   5726:                                         incorrunchkd => 'Incorrect (unchecked)',
                   5727:                     );
                   5728:                     my %textval = (
                   5729:                                     corrchkd     => '1.0',
                   5730:                                     corrunchkd   => '1.0',
                   5731:                                     incorrchkd   => '0.0',
                   5732:                                     incorrunchkd => '0.0',
                   5733:                     );
                   5734:                     if ($showval =~ /^([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)$/) {
                   5735:                         $textval{'corrchkd'} = $1;
                   5736:                         $textval{'corrunchkd'} = $2;
                   5737:                         $textval{'incorrchkd'} = $3;
                   5738:                         $textval{'incorrunchkd'} = $4;
                   5739:                         $display = 'inline';
                   5740:                         $showval = $name;
                   5741:                     } else {
                   5742:                         $display = 'none';
                   5743:                     }
                   5744:                     $add = ' <div id="LC_parmtext_'.$thiskey.'" style="display:'.$display.'"><table>'.
                   5745:                            '<tr><th colspan="2">'.&mt("Foil's submission status").'</th><th>'.&mt('Points').'</th></tr>';  
                   5746:                     foreach my $reltype ('corrchkd','corrunchkd','incorrchkd','incorrunchkd') {
                   5747:                         $add .= '<tr><td>&nbsp;</td><td>'.$relatives{$reltype}.'</td>'."\n".
                   5748:                                 '<td><input type="text" name="settext_'.$thiskey.'"'.
1.552     raeburn  5749:                                 ' value="'.$textval{$reltype}.'" size="3"'.$disabled.' />'.
1.549     raeburn  5750:                                 '</td></tr>';
                   5751:                     }
                   5752:                     $add .= '</table></div>'."\n";
                   5753:                 }
                   5754:                 $onchange = ' onclick="javascript:toggleParmTextbox(this.form,'."'$thiskey'".');"';
                   5755:                 $css_class = ' class="LC_lenient_radio"';
                   5756:             }
                   5757:             $result .= '<td class="LC_left_item"'.$colspan.'>'.
1.504     raeburn  5758:                        '<span class="LC_nobreak"><label>'.
                   5759:                        '<input type="radio" name="set_'.$thiskey.
1.552     raeburn  5760:                        '" value="'.$name.'"'.$onchange.$css_class.$disabled;
1.504     raeburn  5761:             if ($showval eq $name) {
                   5762:                 $result .= ' checked="checked"';
                   5763:             }
1.549     raeburn  5764:             $result .= ' />'.&mt($description).'</label>'.$add.'</span></td>';
1.504     raeburn  5765:             $i++;
                   5766:         }
                   5767:         $result .= '</tr>';
1.473     amueller 5768:     }
1.504     raeburn  5769:     if ($result) {
                   5770:         $result = '<table border="0">'.$result.'</table>';
1.383     albertel 5771:     }
                   5772:     return $result;
                   5773: }
                   5774: 
1.554     raeburn  5775: my %intervals =
                   5776:     (
                   5777:      'date_interval'
                   5778:              => [[ 'done', 'Yes' ],
1.558     raeburn  5779:                  [ 'done_proctor', 'Yes, with proctor key'],                  
1.554     raeburn  5780:                  [ '', 'No' ]],
                   5781:     );
                   5782: 
                   5783: my %intervalmatches = (
                   5784:          'date_interval'
1.559     raeburn  5785:               => [['done','\d+_done(|\:[^\:]+\:)$'],
                   5786:                   ['done_proctor','\d+_done(|\:[^\:]+\:)_proctor_']],
1.554     raeburn  5787:     );
                   5788: 
                   5789: my %intervaltypes = (
                   5790:                       interval => 'date_interval',
                   5791:     );
                   5792: 
1.563     damieng  5793: # Returns regular expressions to match kinds of interval type, or undef if there are none.
                   5794: #
                   5795: # @param {string} $interval_type - a parameter type for intervals
                   5796: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.554     raeburn  5797: sub standard_interval_matches {
                   5798:     my ($interval_type) = @_;
                   5799:     if (ref($intervalmatches{$interval_type}) eq 'ARRAY') {
                   5800:         return $intervalmatches{$interval_type};
                   5801:     }
                   5802:     return;
                   5803: }
                   5804: 
1.563     damieng  5805: # Returns a parameter type for a given parameter with an interval type, or undef if not known.
                   5806: #
                   5807: # @param {string} $name - parameter name
                   5808: # @returns {string}
1.554     raeburn  5809: sub get_intervaltype {
                   5810:     my ($name) = @_;
                   5811:     if (exists($intervaltypes{$name})) {
                   5812:         return $intervaltypes{$name};
                   5813:     }
                   5814:     return;
                   5815: }
                   5816: 
1.563     damieng  5817: # Returns the possible values and titles for a given interval type, or undef if there are none.
                   5818: # Used by courseprefs.
                   5819: #
                   5820: # @param {string} $interval_type - a parameter type for intervals
                   5821: # @returns {array reference} - 2D array, containing values and English titles
1.554     raeburn  5822: sub standard_interval_options {
                   5823:     my ($interval_type) = @_;
                   5824:     if (ref($intervals{$interval_type}) eq 'ARRAY') {
                   5825:         return $intervals{$interval_type};
                   5826:     }
                   5827:     return;
                   5828: }
                   5829: 
1.563     damieng  5830: # Returns HTML to edit a date interval parameter.
                   5831: #
                   5832: # @param {string} $thiskey - parameter key
                   5833: # @param {string} $name - parameter name
                   5834: # @param {string} $showval - parameter current value
                   5835: # @param {boolean} $readonly - true if the values should not be made editable
                   5836: # @returns {string}
1.554     raeburn  5837: sub date_interval_selector {
                   5838:     my ($thiskey, $name, $showval, $readonly) = @_;
                   5839:     my ($result,%skipval);
                   5840:     if ($name eq 'interval') {
                   5841:         my $intervaltype = &get_intervaltype($name);
                   5842:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   5843:         foreach my $possibilities (@{ $intervals{$intervaltype} }) {
                   5844:             next unless (ref($possibilities) eq 'ARRAY');
                   5845:             my ($parmval, $description) = @{ $possibilities };
                   5846:             my $parmmatch;
                   5847:             if (ref($intervalmatches{$intervaltype}) eq 'ARRAY') {
                   5848:                 foreach my $item (@{$intervalmatches{$intervaltype}}) {
                   5849:                     if (ref($item) eq 'ARRAY') {
                   5850:                         if ($parmval eq $item->[0]) {
                   5851:                             $parmmatch = $parmval;
                   5852:                             $parmval = '';
                   5853:                             last;
                   5854:                         }
                   5855:                     }
                   5856:                 }
                   5857:             }
                   5858:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
                   5859:             if ($needsrelease) {
                   5860:                 unless ($got_chostname) {
                   5861:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
                   5862:                     $got_chostname = 1;
                   5863:                 }
1.557     raeburn  5864:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.554     raeburn  5865:                                                        $needsrelease,$cmajor,$cminor);
                   5866:                 if ($needsnewer) {
                   5867:                     if ($parmmatch ne '') {
                   5868:                         $skipval{$parmmatch} = 1;
                   5869:                     } elsif ($parmval ne '') {
                   5870:                         $skipval{$parmval} = 1;
                   5871:                     }
                   5872:                 }
                   5873:             }
                   5874:         }
                   5875:     }
                   5876: 
                   5877:     my $currval = $showval;
                   5878:     foreach my $which (['days', 86400, 31],
                   5879:                ['hours', 3600, 23],
                   5880:                ['minutes', 60, 59],
                   5881:                ['seconds',  1, 59]) {
1.560     damieng  5882:         my ($name, $factor, $max) = @{ $which };
                   5883:         my $amount = int($showval/$factor);
                   5884:         $showval  %= $factor;
                   5885:         my %select = ((map {$_ => $_} (0..$max)),
                   5886:                 'select_form_order' => [0..$max]);
1.611     raeburn  5887:         if ($currval eq '') {
                   5888:             unshift(@{$select{'select_form_order'}},'');
                   5889:             $select{''} = '';
                   5890:             $amount = '';
                   5891:         }
1.560     damieng  5892:         $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
                   5893:                             \%select,'',$readonly);
                   5894:         $result .= ' '.&mt($name);
1.554     raeburn  5895:     }
                   5896:     if ($name eq 'interval') {
                   5897:         unless ($skipval{'done'}) {
                   5898:             my $checkedon = '';
1.611     raeburn  5899:             my $checkedoff = '';
1.558     raeburn  5900:             my $checkedproc = '';
                   5901:             my $currproctorkey = '';
                   5902:             my $currprocdisplay = 'hidden';
1.559     raeburn  5903:             my $currdonetext = &mt('Done');
                   5904:             if ($currval =~ /^(?:\d+)_done$/) {
                   5905:                 $checkedon = ' checked="checked"';
                   5906:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {
                   5907:                 $currdonetext = $1;
1.554     raeburn  5908:                 $checkedon = ' checked="checked"';
1.558     raeburn  5909:             } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {
                   5910:                 $currproctorkey = $1;
                   5911:                 $checkedproc = ' checked="checked"';
                   5912:                 $currprocdisplay = 'text';
1.559     raeburn  5913:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {
                   5914:                 $currdonetext = $1;
                   5915:                 $currproctorkey = $2;
                   5916:                 $checkedproc = ' checked="checked"';
                   5917:                 $currprocdisplay = 'text';
1.611     raeburn  5918:             } elsif ($currval ne '') {
                   5919:                 $checkedoff = ' checked="checked"';
                   5920:             } else {
                   5921:                 $currdonetext = '';
1.554     raeburn  5922:             }
1.558     raeburn  5923:             my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';
1.567     raeburn  5924:             my $disabled;
                   5925:             if ($readonly) {
                   5926:                 $disabled = ' disabled="disabled"';
                   5927:             }
1.558     raeburn  5928:             $result .= '<br /><span class="LC_nobreak">'.&mt('Include "done" button').
1.567     raeburn  5929:                        '<label><input type="radio" value="" name="done_'.$thiskey.'"'.$checkedoff.$onclick.$disabled.' />'.
1.558     raeburn  5930:                        &mt('No').'</label>'.('&nbsp;'x2).
1.567     raeburn  5931:                        '<label><input type="radio" value="_done" name="done_'.$thiskey.'"'.$checkedon.$onclick.$disabled.' />'.
1.558     raeburn  5932:                        &mt('Yes').'</label>'.('&nbsp;'x2).
1.567     raeburn  5933:                        '<label><input type="radio" value="_done_proctor" name="done_'.$thiskey.'"'.$checkedproc.$onclick.$disabled.' />'.
1.558     raeburn  5934:                        &mt('Yes, with proctor key').'</label>'.
                   5935:                        '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.
1.567     raeburn  5936:                        'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.
1.559     raeburn  5937:                        '<span class="LC_nobreak">'.&mt('Button text').': '.
1.611     raeburn  5938:                        '<input type="text" name="done_'.$thiskey.'_buttontext" id="done_'.$thiskey.'_buttontext" value="'.
                   5939:                        &HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';
1.554     raeburn  5940:         }
                   5941:     }
                   5942:     unless ($readonly) {
                   5943:         $result .= '<input type="hidden" name="dateinterval_'.$thiskey.'" />';
                   5944:     }
                   5945:     return $result;
                   5946: }
                   5947: 
1.563     damieng  5948: # Returns HTML with a warning if a parameter requires a more recent version of LON-CAPA.
                   5949: #
                   5950: # @param {string} $name - parameter name
                   5951: # @param {string} $namematch - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   5952: # @param {string} $value - parameter value
                   5953: # @param {string} $chostname - course server name
                   5954: # @param {integer} $cmajor - major version number
                   5955: # @param {integer} $cminor - minor version number
                   5956: # @param {string} $needsrelease - release version needed (major.minor)
                   5957: # @returns {string}
1.549     raeburn  5958: sub oldversion_warning {
1.557     raeburn  5959:     my ($name,$namematch,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
                   5960:     my $standard_name = &standard_parameter_names($name);
                   5961:     if ($namematch) {
                   5962:         my $level = &standard_parameter_levels($namematch);
                   5963:         my $msg = '';
                   5964:         if ($level) {
                   5965:             $msg = &mt('[_1] was [_2]not[_3] set at the level of: [_4].',
                   5966:                        $standard_name,'<b>','</b>','"'.$level.'"');
                   5967:         } else {
                   5968:             $msg = &mt('[_1] was [_2]not[_3] set.',
                   5969:                       $standard_name,'<b>','</b>');
                   5970:         }
                   5971:         return '<p class="LC_warning">'.$msg.'<br />'.
                   5972:                &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   5973:                    $cmajor.'.'.$cminor,$chostname,
                   5974:                    $needsrelease).
                   5975:                    '</p>';
                   5976:     }
1.549     raeburn  5977:     my $desc;
                   5978:     my $stringtype = &get_stringtype($name);
                   5979:     if ($stringtype ne '') {
                   5980:         if ($name eq 'examcode') {
                   5981:             $desc = $value;
                   5982:         } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
                   5983:             foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
                   5984:                 next unless (ref($possibilities) eq 'ARRAY');
                   5985:                 my ($parmval, $description) = @{ $possibilities };
                   5986:                 my $parmmatch;
                   5987:                 if (ref($stringmatches{$stringtypes{$name}}) eq 'ARRAY') {
                   5988:                     foreach my $item (@{$stringmatches{$stringtypes{$name}}}) {
                   5989:                         if (ref($item) eq 'ARRAY') {
                   5990:                             my ($regexpname,$pattern) = @{$item};
                   5991:                             if ($parmval eq $regexpname) {
                   5992:                                 if ($value =~ /$pattern/) {
                   5993:                                     $desc = $description; 
                   5994:                                     $parmmatch = 1;
                   5995:                                     last;
                   5996:                                 }
                   5997:                             }
                   5998:                         }
                   5999:                     }
                   6000:                     last if ($parmmatch);
                   6001:                 } elsif ($parmval eq $value) {
                   6002:                     $desc = $description;
                   6003:                     last;
                   6004:                 }
                   6005:             }
                   6006:         }
                   6007:     } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
                   6008:         my $now = time;
                   6009:         if ($value =~ /^\d+$/) {
                   6010:             if ($name eq 'printstartdate') {
                   6011:                 if ($value > $now) {
                   6012:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   6013:                 }
                   6014:             } elsif ($name eq 'printenddate') {
                   6015:                 if ($value < $now) {
                   6016:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   6017:                 }
                   6018:             }
                   6019:         }
                   6020:     }
                   6021:     return '<p class="LC_warning">'.
1.557     raeburn  6022:        &mt('[_1] was [_2]not[_3] set to [_4].',
                   6023:            $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
                   6024:        &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   6025:        $cmajor.'.'.$cminor,$chostname,
                   6026:        $needsrelease).
                   6027:        '</p>';
1.549     raeburn  6028: }
                   6029: 
1.560     damieng  6030: } # end of block using some constants related to parameter types
                   6031: 
1.549     raeburn  6032: 
1.563     damieng  6033: 
                   6034: # Shifts all start and end dates in the current course by $shift.
1.389     www      6035: #
1.563     damieng  6036: # @param {integer} $shift - time to shift, in seconds
                   6037: # @returns {string} - error name or 'ok'
1.389     www      6038: sub dateshift {
1.594     raeburn  6039:     my ($shift,$numchanges)=@_;
1.389     www      6040:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6041:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594     raeburn  6042:     my $sec = $env{'request.course.sec'};
1.595     raeburn  6043:     my $secgrpregex;
                   6044:     if ($sec ne '') {
                   6045:         my @groups;
                   6046:         if ($env{'request.course.groups'} ne '') {
                   6047:             @groups = split(/:/,$env{'request.course.groups'});
                   6048:         }
                   6049:         if (@groups) {
                   6050:             $secgrpregex = '(?:'.join('|',($sec,@groups)).')';
                   6051:         } else {
                   6052:             $secgrpregex = $sec;
                   6053:         }
                   6054:     }
1.389     www      6055:     my %data=&Apache::lonnet::dump('resourcedata',$dom,$crs);
                   6056: # ugly retro fix for broken version of types
1.548     raeburn  6057:     foreach my $key (keys(%data)) {
1.389     www      6058:         if ($key=~/\wtype$/) {
                   6059:             my $newkey=$key;
                   6060:             $newkey=~s/type$/\.type/;
                   6061:             $data{$newkey}=$data{$key};
                   6062:             delete $data{$key};
                   6063:         }
                   6064:     }
1.391     www      6065:     my %storecontent=();
1.389     www      6066: # go through all parameters and look for dates
1.548     raeburn  6067:     foreach my $key (keys(%data)) {
1.389     www      6068:        if ($data{$key.'.type'}=~/^date_(start|end)$/) {
1.594     raeburn  6069:           if ($sec ne '') {
1.595     raeburn  6070:               next unless ($key =~ /^$env{'request.course.id'}\.\[$secgrpregex\]\./);
1.594     raeburn  6071:           }
1.389     www      6072:           my $newdate=$data{$key}+$shift;
1.594     raeburn  6073:           $$numchanges ++;
1.391     www      6074:           $storecontent{$key}=$newdate;
1.389     www      6075:        }
                   6076:     }
1.391     www      6077:     my $reply=&Apache::lonnet::cput
                   6078:                 ('resourcedata',\%storecontent,$dom,$crs);
                   6079:     if ($reply eq 'ok') {
                   6080:        &log_parmset(\%storecontent);
                   6081:     }
                   6082:     &Apache::lonnet::devalidatecourseresdata($crs,$dom);
                   6083:     return $reply;
1.389     www      6084: }
                   6085: 
1.563     damieng  6086: # Overview mode UI to edit course parameters.
                   6087: #
                   6088: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      6089: sub newoverview {
1.568     raeburn  6090:     my ($r,$parm_permission) = @_;
1.280     albertel 6091: 
1.208     www      6092:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6093:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6094:     my $crstype =  $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  6095:     my $readonly = 1;
                   6096:     if ($parm_permission->{'edit'}) {
                   6097:         undef($readonly);
                   6098:     }
1.414     droeschl 6099:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 6100:         text=>"Overview Mode"});
1.523     raeburn  6101: 
                   6102:     my %loaditems = (
1.549     raeburn  6103:                       'onload'   => "showHide_courseContent(); resize_scrollbox('mapmenuscroll','1','1'); showHideLenient();",
1.523     raeburn  6104:                     );
                   6105:     my $js = '
                   6106: <script type="text/javascript">
                   6107: // <![CDATA[
                   6108: '.
                   6109:             &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".
                   6110:             &showhide_js()."\n".
1.549     raeburn  6111:             &toggleparmtextbox_js()."\n".
                   6112:             &validateparms_js()."\n".
                   6113:             &ipacc_boxes_js()."\n".
1.558     raeburn  6114:             &done_proctor_js()."\n".
1.588     raeburn  6115:             &deeplink_js()."\n".
1.523     raeburn  6116: '// ]]>
                   6117: </script>
                   6118: ';
1.549     raeburn  6119: 
1.523     raeburn  6120:     my $start_page = &Apache::loncommon::start_page('Set Parameters',$js,
                   6121:                                                     {'add_entries' => \%loaditems,});
1.298     albertel 6122:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      6123:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6124:     &startSettingsScreen($r,'parmset',$crstype);
1.208     www      6125:     $r->print(<<ENDOVER);
1.549     raeburn  6126: <form method="post" action="/adm/parmset?action=newoverview" name="parmform" onsubmit="return validateParms();">
1.208     www      6127: ENDOVER
1.211     www      6128:     my @ids=();
                   6129:     my %typep=();
                   6130:     my %keyp=();
                   6131:     my %allparms=();
                   6132:     my %allparts=();
                   6133:     my %allmaps=();
                   6134:     my %mapp=();
                   6135:     my %symbp=();
                   6136:     my %maptitles=();
                   6137:     my %uris=();
                   6138:     my %keyorder=&standardkeyorder();
                   6139:     my %defkeytype=();
                   6140: 
                   6141:     my %alllevs=();
                   6142:     $alllevs{'Resource Level'}='full';
1.215     www      6143:     $alllevs{'Map/Folder Level'}='map';
1.211     www      6144:     $alllevs{'Course Level'}='general';
                   6145: 
                   6146:     my $csec=$env{'form.csec'};
1.269     raeburn  6147:     my $cgroup=$env{'form.cgroup'};
1.211     www      6148: 
                   6149:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
                   6150:     my $pschp=$env{'form.pschp'};
1.506     www      6151: 
1.211     www      6152:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      6153:     if (!@psprt) { $psprt[0]='all'; }
1.211     www      6154: 
1.446     bisitz   6155:     my @selected_sections =
1.473     amueller 6156:     &Apache::loncommon::get_env_multiple('form.Section');
1.211     www      6157:     @selected_sections = ('all') if (! @selected_sections);
1.374     albertel 6158:     foreach my $sec (@selected_sections) {
                   6159:         if ($sec eq 'all') {
1.211     www      6160:             @selected_sections = ('all');
                   6161:         }
                   6162:     }
1.552     raeburn  6163:     if ($env{'request.course.sec'} ne '') {
                   6164:         @selected_sections = ($env{'request.course.sec'});
                   6165:     }
1.269     raeburn  6166:     my @selected_groups =
                   6167:         &Apache::loncommon::get_env_multiple('form.Group');
1.211     www      6168: 
                   6169:     my $pssymb='';
                   6170:     my $parmlev='';
1.446     bisitz   6171: 
1.211     www      6172:     unless ($env{'form.parmlev'}) {
                   6173:         $parmlev = 'map';
                   6174:     } else {
                   6175:         $parmlev = $env{'form.parmlev'};
                   6176:     }
                   6177: 
1.446     bisitz   6178:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 6179:                 \%mapp, \%symbp,\%maptitles,\%uris,
1.603     raeburn  6180:                 \%keyorder,\%defkeytype,$pssymb);
1.211     www      6181: 
1.374     albertel 6182:     if (grep {$_ eq 'all'} (@psprt)) {
1.481     amueller 6183:         @psprt = keys(%allparts);
1.374     albertel 6184:     }
1.211     www      6185: # Menu to select levels, etc
                   6186: 
1.456     bisitz   6187:     $r->print('<div class="LC_Box">');
1.445     neumanie 6188:     #$r->print('<h2 class="LC_hcell">Step 1</h2>');
1.452     bisitz   6189:     $r->print('<div>');
1.523     raeburn  6190:     $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.211     www      6191:     &levelmenu($r,\%alllevs,$parmlev);
1.610     raeburn  6192:     $r->print(&Apache::lonhtmlcommon::row_closure());
                   6193:     &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.447     bisitz   6194:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 6195:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   6196:     $r->print('</div></div>');
1.446     bisitz   6197: 
1.456     bisitz   6198:     $r->print('<div class="LC_Box">');
1.452     bisitz   6199:     $r->print('<div>');
1.581     raeburn  6200:     &displaymenu($r,\%allparms,\@pscat,\%keyorder);
1.453     schualex 6201:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.446     bisitz   6202:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
1.553     raeburn  6203:     my $sectionselector = &sectionmenu(\@selected_sections);
                   6204:     my $groupselector = &groupmenu(\@selected_groups);
1.481     amueller 6205:     $r->print('<table>'.
1.553     raeburn  6206:               '<tr><th>'.&mt('Parts').'</th>');
                   6207:     if ($sectionselector) {
                   6208:         $r->print('<th>'.&mt('Section(s)').'</th>');
                   6209:     }
                   6210:     if ($groupselector) {
                   6211:         $r->print('<th>'.&mt('Group(s)').'</th>');
                   6212:     }
                   6213:     $r->print('</tr><tr><td>');
1.211     www      6214:     &partmenu($r,\%allparts,\@psprt);
1.553     raeburn  6215:     $r->print('</td>');
                   6216:     if ($sectionselector) { 
                   6217:         $r->print('<td>'.$sectionselector.'</td>');
                   6218:     }
                   6219:     if ($groupselector) {
                   6220:         $r->print('<td>'.$groupselector.'</td>');
                   6221:     }
                   6222:     $r->print('</tr></table>');
1.447     bisitz   6223:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 6224:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   6225:     $r->print('</div></div>');
                   6226: 
1.456     bisitz   6227:     $r->print('<div class="LC_Box">');
1.452     bisitz   6228:     $r->print('<div>');
1.214     www      6229:     my $sortorder=$env{'form.sortorder'};
                   6230:     unless ($sortorder) { $sortorder='realmstudent'; }
1.612     raeburn  6231:     &sortmenu($r,$sortorder,'newoverview');
1.445     neumanie 6232:     $r->print('</div></div>');
1.446     bisitz   6233: 
1.214     www      6234:     $r->print('<p><input type="submit" name="dis" value="'.&mt('Display').'" /></p>');
1.446     bisitz   6235: 
1.211     www      6236: # Build the list data hash from the specified parms
                   6237: 
                   6238:     my $listdata;
                   6239:     %{$listdata}=();
                   6240: 
                   6241:     foreach my $cat (@pscat) {
1.269     raeburn  6242:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_sections,\%defkeytype,\%allmaps,\@ids,\%symbp);
                   6243:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_groups,\%defkeytype,\%allmaps,\@ids,\%symbp);
1.211     www      6244:     }
                   6245: 
1.212     www      6246:     if (($env{'form.store'}) || ($env{'form.dis'})) {
1.211     www      6247: 
1.481     amueller 6248:         if ($env{'form.store'}) { &storedata($r,$crs,$dom); }
1.211     www      6249: 
                   6250: # Read modified data
                   6251: 
1.481     amueller 6252:         my $resourcedata=&readdata($crs,$dom);
1.211     www      6253: 
                   6254: # List data
                   6255: 
1.608     raeburn  6256:         my $hash_for_realm;
                   6257:         if (($parmlev eq 'map') && (keys(%allmaps))) {
                   6258:             %{$hash_for_realm} = reverse(%allmaps);
                   6259:         } elsif (($parmlev eq 'full') && (keys(%symbp))) {
                   6260:             for (my $i=0; $i<@ids; $i++) {
                   6261:                 $hash_for_realm->{$symbp{$ids[$i]}} = $i;
                   6262:             }
                   6263:         }
                   6264:         &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly,$parmlev,$hash_for_realm,$pschp);
1.568     raeburn  6265:     }
                   6266:     $r->print(&tableend());
                   6267:     unless ($readonly) {
                   6268:         $r->print( ((($env{'form.store'}) || ($env{'form.dis'}))?'<p><input type="submit" name="store" value="'.&mt('Save').'" /></p>':'') );
1.211     www      6269:     }
1.568     raeburn  6270:     $r->print('</form>');
1.507     www      6271:     &endSettingsScreen($r);
                   6272:     $r->print(&Apache::loncommon::end_page());
1.208     www      6273: }
                   6274: 
1.563     damieng  6275: # Fills $listdata with parameter information.
                   6276: # Keys use the format course id.[section id].part.name and course id.[section id].part.name.type.
                   6277: # The non-type value is always 1.
                   6278: #
                   6279: # @param {string} $cat - parameter name
1.566     damieng  6280: # @param {string} $pschp - selected map pc, or 'all'
1.563     damieng  6281: # @param {string} $parmlev - selected level value (full|map|general), or ''
                   6282: # @param {hash reference} $listdata - the parameter data that will be modified
                   6283: # @param {array reference} $psprt - selected parts
                   6284: # @param {array reference} $selections - selected sections
                   6285: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.566     damieng  6286: # @param {hash reference} $allmaps - hash map pc -> map src
                   6287: # @param {array reference} $ids - resource and map ids
                   6288: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.269     raeburn  6289: sub secgroup_lister {
                   6290:     my ($cat,$pschp,$parmlev,$listdata,$psprt,$selections,$defkeytype,$allmaps,$ids,$symbp) = @_;
                   6291:     foreach my $item (@{$selections}) {
                   6292:         foreach my $part (@{$psprt}) {
                   6293:             my $rootparmkey=$env{'request.course.id'};
                   6294:             if (($item ne 'all') && ($item ne 'none') && ($item)) {
                   6295:                 $rootparmkey.='.['.$item.']';
                   6296:             }
                   6297:             if ($parmlev eq 'general') {
                   6298: # course-level parameter
                   6299:                 my $newparmkey=$rootparmkey.'.'.$part.'.'.$cat;
                   6300:                 $$listdata{$newparmkey}=1;
                   6301:                 $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6302:             } elsif ($parmlev eq 'map') {
                   6303: # map-level parameter
1.548     raeburn  6304:                 foreach my $mapid (keys(%{$allmaps})) {
1.269     raeburn  6305:                     if (($pschp ne 'all') && ($pschp ne $mapid)) { next; }
                   6306:                     my $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(all).'.$part.'.'.$cat;
                   6307:                     $$listdata{$newparmkey}=1;
                   6308:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6309:                 }
                   6310:             } else {
                   6311: # resource-level parameter
                   6312:                 foreach my $rid (@{$ids}) {
                   6313:                     my ($map,$resid,$url)=&Apache::lonnet::decode_symb($$symbp{$rid});
                   6314:                     if (($pschp ne 'all') && ($$allmaps{$pschp} ne $map)) { next; }
                   6315:                     my $newparmkey=$rootparmkey.'.'.$$symbp{$rid}.'.'.$part.'.'.$cat;
                   6316:                     $$listdata{$newparmkey}=1;
                   6317:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6318:                 }
                   6319:             }
                   6320:         }
                   6321:     }
                   6322: }
                   6323: 
1.563     damieng  6324: # UI to edit parameter settings starting with a list of all existing parameters.
                   6325: # (called by setoverview action)
                   6326: #
                   6327: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      6328: sub overview {
1.568     raeburn  6329:     my ($r,$parm_permission) = @_;
1.208     www      6330:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6331:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6332:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  6333:     my $readonly = 1;
                   6334:     if ($parm_permission->{'edit'}) {
                   6335:         undef($readonly);
                   6336:     }
1.549     raeburn  6337:     my $js = '<script type="text/javascript">'."\n".
                   6338:              '// <![CDATA['."\n".
                   6339:              &toggleparmtextbox_js()."\n".
                   6340:              &validateparms_js()."\n".
                   6341:              &ipacc_boxes_js()."\n".
1.558     raeburn  6342:              &done_proctor_js()."\n".
1.588     raeburn  6343:              &deeplink_js()."\n".
1.549     raeburn  6344:              '// ]]>'."\n".
                   6345:              '</script>'."\n";
1.414     droeschl 6346:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 6347:     text=>"Overview Mode"});
1.549     raeburn  6348:     my %loaditems = (
                   6349:                       'onload'   => "showHideLenient();",
                   6350:                     );
                   6351: 
                   6352:     my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js,{'add_entries' => \%loaditems,});
1.298     albertel 6353:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      6354:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6355:     &startSettingsScreen($r,'parmset',$crstype);
1.549     raeburn  6356:     $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform" onsubmit="return validateParms();">');
1.507     www      6357: 
1.208     www      6358: # Store modified
                   6359: 
1.568     raeburn  6360:     unless ($readonly) {
                   6361:         &storedata($r,$crs,$dom);
                   6362:     }
1.208     www      6363: 
                   6364: # Read modified data
                   6365: 
1.552     raeburn  6366:     my ($resourcedata,$classlist)=&readdata($crs,$dom);
1.208     www      6367: 
1.214     www      6368: 
                   6369:     my $sortorder=$env{'form.sortorder'};
                   6370:     unless ($sortorder) { $sortorder='realmstudent'; }
1.608     raeburn  6371:     &sortmenu($r,$sortorder,'overview');
1.214     www      6372: 
1.568     raeburn  6373:     my $submitbutton = '<input type="submit" value="'.&mt('Save').'" />';
                   6374: 
                   6375:     if ($readonly) {
                   6376:         $r->print('<p>'.$submitbutton.'</p>');
                   6377:     }
                   6378: 
1.208     www      6379: # List data
                   6380: 
1.568     raeburn  6381:     my $foundkeys=&listdata($r,$resourcedata,$resourcedata,$sortorder,'overview',$classlist,$readonly);
                   6382:     $r->print(&tableend().'<p>');
                   6383:     if ($foundkeys) {
                   6384:         unless ($readonly) {
                   6385:             $r->print('<p>'.$submitbutton.'</p>');
                   6386:         }
                   6387:     } else {
                   6388:         $r->print('<p class="LC_info">'.&mt('There are no parameters.').'</p>');
                   6389:     }
                   6390:     $r->print('</form>'.&Apache::loncommon::end_page());
1.120     www      6391: }
1.121     www      6392: 
1.560     damieng  6393: # Unused sub.
1.563     damieng  6394: #
                   6395: # @param {Apache2::RequestRec} $r - the Apache request
1.333     albertel 6396: sub clean_parameters {
                   6397:     my ($r) = @_;
                   6398:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6399:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                   6400: 
1.414     droeschl 6401:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=cleanparameters',
1.473     amueller 6402:         text=>"Clean Parameters"});
1.333     albertel 6403:     my $start_page=&Apache::loncommon::start_page('Clean Parameters');
                   6404:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Clean');
                   6405:     $r->print(<<ENDOVER);
                   6406: $start_page
                   6407: $breadcrumbs
                   6408: <form method="post" action="/adm/parmset?action=cleanparameters" name="parmform">
                   6409: ENDOVER
                   6410: # Store modified
                   6411: 
                   6412:     &storedata($r,$crs,$dom);
                   6413: 
                   6414: # Read modified data
                   6415: 
                   6416:     my $resourcedata=&readdata($crs,$dom);
                   6417: 
                   6418: # List data
                   6419: 
                   6420:     $r->print('<h3>'.
1.473     amueller 6421:           &mt('These parameters refer to resources that do not exist.').
                   6422:           '</h3>'.
                   6423:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.'<br />'.
                   6424:           '<br />');
1.333     albertel 6425:     $r->print(&Apache::loncommon::start_data_table().
1.473     amueller 6426:           '<tr>'.
                   6427:           '<th>'.&mt('Delete').'</th>'.
                   6428:           '<th>'.&mt('Parameter').'</th>'.
                   6429:           '</tr>');
1.333     albertel 6430:     foreach my $thiskey (sort(keys(%{$resourcedata}))) {
1.560     damieng  6431:         next if (!exists($resourcedata->{$thiskey.'.type'})
                   6432:             && $thiskey=~/\.type$/);
                   6433:         my %data = &parse_key($thiskey);
                   6434:         if (1) { #exists($data{'realm_exists'})
                   6435:             #&& !$data{'realm_exists'}) {
                   6436:             $r->print(&Apache::loncommon::start_data_table_row().
                   6437:                 '<tr>'.
                   6438:                 '<td><input type="checkbox" name="del_'.$thiskey.'" /></td>'              );
                   6439: 
                   6440:             $r->print('<td>');
                   6441:             my $display_value = $resourcedata->{$thiskey};
                   6442:             if (&isdateparm($resourcedata->{$thiskey.'.type'})) {
                   6443:             $display_value =
                   6444:                 &Apache::lonlocal::locallocaltime($display_value);
                   6445:             }
1.470     raeburn  6446:             my $parmitem = &standard_parameter_names($data{'parameter_name'});
                   6447:             $parmitem = &mt($parmitem);
1.560     damieng  6448:             $r->print(&mt('Parameter: "[_1]" with value: "[_2]"',
                   6449:                 $parmitem,$resourcedata->{$thiskey}));
                   6450:             $r->print('<br />');
                   6451:             if ($data{'scope_type'} eq 'all') {
                   6452:                 $r->print(&mt('All users'));
                   6453:             } elsif ($data{'scope_type'} eq 'user') {
                   6454:                 $r->print(&mt('User: [_1]',join(':',@{$data{'scope'}})));
1.581     raeburn  6455:             } elsif ($data{'scope_type'} eq 'secgroup') {
                   6456:                 $r->print(&mt('Group/Section: [_1]',$data{'scope'}));
1.560     damieng  6457:             }
                   6458:             $r->print('<br />');
                   6459:             if ($data{'realm_type'} eq 'all') {
                   6460:                 $r->print(&mt('All Resources'));
                   6461:             } elsif ($data{'realm_type'} eq 'folder') {
                   6462:                 $r->print(&mt('Folder: [_1]'),$data{'realm'});
                   6463:             } elsif ($data{'realm_type'} eq 'symb') {
                   6464:             my ($map,$resid,$url) =
                   6465:                 &Apache::lonnet::decode_symb($data{'realm'});
                   6466:             $r->print(&mt('Resource: [_1]with ID: [_2]in folder [_3]',
                   6467:                         $url.' <br />&nbsp;&nbsp;&nbsp;',
                   6468:                         $resid.' <br />&nbsp;&nbsp;&nbsp;',$map));
                   6469:             }
                   6470:             $r->print(' <br />&nbsp;&nbsp;&nbsp;'.&mt('Part: [_1]',$data{'parameter_part'}));
                   6471:             $r->print('</td></tr>');
                   6472: 
1.473     amueller 6473:         }
1.333     albertel 6474:     }
                   6475:     $r->print(&Apache::loncommon::end_data_table().'<p>'.
1.473     amueller 6476:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.
1.507     www      6477:           '</p></form>');
                   6478:     &endSettingsScreen($r);
                   6479:     $r->print(&Apache::loncommon::end_page());
1.333     albertel 6480: }
                   6481: 
1.563     damieng  6482: # UI to shift all dates (called by dateshift1 action).
                   6483: # Used by overview mode.
                   6484: #
                   6485: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      6486: sub date_shift_one {
                   6487:     my ($r) = @_;
                   6488:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6489:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6490:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.594     raeburn  6491:     my $sec = $env{'request.course.sec'};
1.414     droeschl 6492:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 6493:         text=>"Shifting Dates"});
1.594     raeburn  6494:     my $submit_text = &mt('Shift all dates accordingly');
                   6495:     if ($sec ne '') {
1.595     raeburn  6496:         my @groups;
                   6497:         if ($env{'request.course.groups'} ne '') {
                   6498:             @groups = split(/:/,$env{'request.course.groups'});
                   6499:         }
                   6500:         if (@groups) {
                   6501:             $submit_text = &mt("Shift dates set just for your section/group(s), accordingly");
                   6502:         } else {
                   6503:             $submit_text = &mt("Shift dates set just for your section, accordingly");
                   6504:         }
1.594     raeburn  6505:     }
1.390     www      6506:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   6507:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      6508:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6509:     &startSettingsScreen($r,'parmset',$crstype);
1.538     bisitz   6510:     $r->print('<form name="shiftform" method="post" action="">'.
1.390     www      6511:               '<table><tr><td>'.&mt('Currently set date:').'</td><td>'.
                   6512:               &Apache::lonlocal::locallocaltime($env{'form.timebase'}).'</td></tr>'.
                   6513:               '<tr><td>'.&mt('Shifted date:').'</td><td>'.
1.541     bisitz   6514:                     &Apache::lonhtmlcommon::date_setter('shiftform',
1.390     www      6515:                                                         'timeshifted',
                   6516:                                                         $env{'form.timebase'},,
                   6517:                                                         '').
                   6518:               '</td></tr></table>'.
                   6519:               '<input type="hidden" name="action" value="dateshift2" />'.
                   6520:               '<input type="hidden" name="timebase" value="'.$env{'form.timebase'}.'" />'.
1.594     raeburn  6521:               '<input type="submit" value="'.$submit_text.'" /></form>');
1.507     www      6522:     &endSettingsScreen($r);
1.390     www      6523:     $r->print(&Apache::loncommon::end_page());
                   6524: }
                   6525: 
1.563     damieng  6526: # UI to shift all dates (second form).
                   6527: #
                   6528: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      6529: sub date_shift_two {
                   6530:     my ($r) = @_;
                   6531:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6532:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594     raeburn  6533:     my $sec = $env{'request.course.sec'};
1.531     raeburn  6534:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 6535:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 6536:         text=>"Shifting Dates"});
1.390     www      6537:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   6538:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      6539:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6540:     &startSettingsScreen($r,'parmset',$crstype);
1.390     www      6541:     my $timeshifted=&Apache::lonhtmlcommon::get_date_from_form('timeshifted');
1.594     raeburn  6542:     $r->print('<h2>'.&mt('Shift Dates').'</h2>');
                   6543:     if ($sec ne '') {
1.595     raeburn  6544:         my @groups;
                   6545:         if ($env{'request.course.groups'} ne '') {
                   6546:             @groups = split(/:/,$env{'request.course.groups'});
                   6547:         }
                   6548:         if (@groups) {
                   6549:             $r->print('<p>'.
                   6550:                       &mt("Shift dates set just for your section/group(s), such that [_1] becomes [_2]",
                   6551:                           &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6552:                           &Apache::lonlocal::locallocaltime($timeshifted)).
                   6553:                       '</p>');
                   6554:         } else {
                   6555:             $r->print('<p>'.
                   6556:                       &mt("Shift dates set just for your section, such that [_1] becomes [_2]",
                   6557:                           &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6558:                           &Apache::lonlocal::locallocaltime($timeshifted)).
                   6559:                       '</p>');
                   6560:         }
1.594     raeburn  6561:     } else {
                   6562:         $r->print('<p>'.&mt('Shifting all dates such that [_1] becomes [_2]',
                   6563:                             &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6564:                             &Apache::lonlocal::locallocaltime($timeshifted)).
                   6565:                   '</p>');
                   6566:     }
1.390     www      6567:     my $delta=$timeshifted-$env{'form.timebase'};
1.594     raeburn  6568:     my $numchanges = 0;
                   6569:     my $result = &dateshift($delta,\$numchanges);
                   6570:     if ($result eq 'ok') {
                   6571:         $r->print(
                   6572:             &Apache::lonhtmlcommon::confirm_success(&mt('Completed shifting of [quant,_1,date setting]',
                   6573:                                                     $numchanges)));
                   6574:     } elsif ($result eq 'con_delayed') {
                   6575:         $r->print(
                   6576:             &Apache::lonhtmlcommon::confirm_success(&mt('Queued shifting of [quant,_1,date setting]',
                   6577:                                                         $numchanges)));
                   6578:     } else {
                   6579:         $r->print(
                   6580:             &Apache::lonhtmlcommon::confirm_success(&mt('An error occurred attempting to shift dates'),1));
                   6581:     }
1.543     bisitz   6582:     $r->print(
                   6583:         '<br /><br />'.
                   6584:         &Apache::lonhtmlcommon::actionbox(
                   6585:             ['<a href="/adm/parmset">'.&mt('Content and Problem Settings').'</a>']));
1.507     www      6586:     &endSettingsScreen($r);
1.390     www      6587:     $r->print(&Apache::loncommon::end_page());
                   6588: }
                   6589: 
1.563     damieng  6590: # Returns the different components of a resourcedata key.
                   6591: # Keys: scope_type, scope, realm_type, realm, realm_title,
                   6592: #       realm_exists, parameter_part, parameter_name.
                   6593: # Was used by clean_parameters (which is unused).
                   6594: #
                   6595: # @param {string} $key - the parameter key
                   6596: # @returns {hash}
1.333     albertel 6597: sub parse_key {
                   6598:     my ($key) = @_;
                   6599:     my %data;
                   6600:     my ($middle,$part,$name)=
1.572     damieng  6601:     ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.333     albertel 6602:     $data{'scope_type'} = 'all';
                   6603:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  6604:         $data{'scope'} = $1;
                   6605:         if ($data{'scope'}=~/^useropt\:($match_username)\:($match_domain)/) {
                   6606:             $data{'scope_type'} = 'user';
                   6607:             $data{'scope'} = [$1,$2];
                   6608:         } else {
1.581     raeburn  6609:             $data{'scope_type'} = 'secgroup';
1.560     damieng  6610:         }
                   6611:         $middle=~s/^\[(.*)\]//;
1.333     albertel 6612:     }
                   6613:     $middle=~s/\.+$//;
                   6614:     $middle=~s/^\.+//;
                   6615:     $data{'realm_type'}='all';
                   6616:     if ($middle=~/^(.+)\_\_\_\(all\)$/) {
1.560     damieng  6617:         $data{'realm'} = $1;
                   6618:         $data{'realm_type'} = 'folder';
                   6619:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   6620:         ($data{'realm_exists'}) = &Apache::lonnet::is_on_map($data{'realm'});
1.333     albertel 6621:     } elsif ($middle) {
1.560     damieng  6622:         $data{'realm'} = $middle;
                   6623:         $data{'realm_type'} = 'symb';
                   6624:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   6625:         my ($map,$resid,$url) = &Apache::lonnet::decode_symb($data{'realm'});
                   6626:         $data{'realm_exists'} = &Apache::lonnet::symbverify($data{'realm'},$url);
1.333     albertel 6627:     }
1.446     bisitz   6628: 
1.333     albertel 6629:     $data{'parameter_part'} = $part;
                   6630:     $data{'parameter_name'} = $name;
                   6631: 
                   6632:     return %data;
                   6633: }
                   6634: 
1.239     raeburn  6635: 
1.563     damieng  6636: # Calls loncommon::start_page with the "Settings" title.
1.416     jms      6637: sub header {
1.507     www      6638:     return &Apache::loncommon::start_page('Settings');
1.416     jms      6639: }
1.193     albertel 6640: 
                   6641: 
                   6642: 
1.560     damieng  6643: ##################################################
                   6644: # MAIN MENU
                   6645: ##################################################
                   6646: 
1.563     damieng  6647: # Content and problem settings main menu.
                   6648: #
                   6649: # @param {Apache2::RequestRec} $r - the Apache request
                   6650: # @param {boolean} $parm_permission - true if the user has permission to edit the current course or section
1.193     albertel 6651: sub print_main_menu {
                   6652:     my ($r,$parm_permission)=@_;
                   6653:     #
1.414     droeschl 6654:     $r->print(&header());
1.507     www      6655:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content and Problem Settings'));
1.531     raeburn  6656:     my $crstype = &Apache::loncommon::course_type();
                   6657:     my $lc_crstype = lc($crstype);
                   6658: 
                   6659:     &startSettingsScreen($r,'parmset',$crstype);
1.193     albertel 6660:     $r->print(<<ENDMAINFORMHEAD);
                   6661: <form method="post" enctype="multipart/form-data"
                   6662:       action="/adm/parmset" name="studentform">
                   6663: ENDMAINFORMHEAD
                   6664: #
1.195     albertel 6665:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   6666:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1.268     albertel 6667:     my $vgr  = &Apache::lonnet::allowed('vgr',$env{'request.course.id'});
1.366     albertel 6668:     my $mgr  = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
1.520     raeburn  6669:     my $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'});
1.568     raeburn  6670:     my $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'});
                   6671:     my $vpa = &Apache::lonnet::allowed('vpa',$env{'request.course.id'});
1.520     raeburn  6672:     if ((!$dcm) && ($env{'request.course.sec'} ne '')) {
                   6673:         $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'}.
                   6674:                                         '/'.$env{'request.course.sec'});
                   6675:     }
1.568     raeburn  6676:     if ((!$vcb) && ($env{'request.course.sec'} ne '')) {
                   6677:         $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'}.
                   6678:                                         '/'.$env{'request.course.sec'});
                   6679:     }
                   6680:     my (%linktext,%linktitle,%url);
                   6681:     if ($parm_permission->{'edit'}) {
                   6682:         %linktext = (
                   6683:                      newoverview     => 'Edit Resource Parameters - Overview Mode',
                   6684:                      settable        => 'Edit Resource Parameters - Table Mode',
                   6685:                      setoverview     => 'Modify Resource Parameters - Overview Mode',
                   6686:                     );
                   6687:         %linktitle = (
                   6688:                      newoverview     => 'Set/Modify resource parameters in overview mode.',
                   6689:                      settable        => 'Set/Modify resource parameters in table mode.',
                   6690:                      setoverview     => 'Set/Modify existing resource parameters in overview mode.',
                   6691:                      );
                   6692:     } else {
                   6693:         %linktext = (
                   6694:                      newoverview     => 'View Resource Parameters - Overview Mode',
                   6695:                      settable        => 'View Resource Parameters - Table Mode',
                   6696:                      setoverview     => 'View Resource Parameters - Overview Mode',
                   6697:                    );
                   6698:         %linktitle = (
                   6699:                      newoverview     => 'Display resource parameters in overview mode.',
                   6700:                      settable        => 'Display resource parameters in table mode.',
                   6701:                      setoverview     => 'Display existing resource parameters in overview mode.',
                   6702:                      );
                   6703:     }
                   6704:     if ($mgr) {
                   6705:         $linktext{'resettimes'} = 'Reset Student Access Times';
                   6706:         $linktitle{'resettimes'} = "Reset access times for folders/maps, resources or the $lc_crstype.";
                   6707:         $url{'resettimes'} = '/adm/helper/resettimes.helper';
                   6708:     } elsif ($vgr) {
                   6709:         $linktext{'resettimes'} = 'Display Student Access Times',
                   6710:         $linktitle{'resettimes'} = "Display access times for folders/maps, resources or the $lc_crstype.",
                   6711:         $url{'resettimes'} = '/adm/accesstimes';
                   6712:     }
1.193     albertel 6713:     my @menu =
1.507     www      6714:         ( { categorytitle=>"Content Settings for this $crstype",
1.473     amueller 6715:         items => [
                   6716:           { linktext => 'Portfolio Metadata',
                   6717:             url => '/adm/parmset?action=setrestrictmeta',
1.568     raeburn  6718:             permission => $parm_permission->{'setrestrictmeta'},
1.477     raeburn  6719:             linktitle => "Restrict metadata for this $lc_crstype." ,
1.473     amueller 6720:             icon =>'contact-new.png'   ,
                   6721:             },
1.568     raeburn  6722:           { linktext => $linktext{'resettimes'},
                   6723:             url => $url{'resettimes'},
                   6724:             permission => ($vgr || $mgr),
                   6725:             linktitle => $linktitle{'resettimes'},
                   6726:             icon => 'start-here.png',
1.473     amueller 6727:             },
1.520     raeburn  6728:           { linktext => 'Blocking Communication/Resource Access',
                   6729:             url => '/adm/setblock',
1.568     raeburn  6730:             permission => ($vcb || $dcm),
1.520     raeburn  6731:             linktitle => 'Configure blocking of communication/collaboration and access to resources during an exam',
                   6732:             icon => 'comblock.png',
                   6733:             },
1.473     amueller 6734:           { linktext => 'Set Parameter Setting Default Actions',
                   6735:             url => '/adm/parmset?action=setdefaults',
1.568     raeburn  6736:             permission => $parm_permission->{'setdefaults'},
1.473     amueller 6737:             linktitle =>'Set default actions for parameters.'  ,
                   6738:             icon => 'folder-new.png'  ,
                   6739:             }]},
                   6740:       { categorytitle => 'New and Existing Parameter Settings for Resources',
                   6741:         items => [
                   6742:           { linktext => 'Edit Resource Parameters - Helper Mode',
                   6743:             url => '/adm/helper/parameter.helper',
1.568     raeburn  6744:             permission => $parm_permission->{'helper'},
1.473     amueller 6745:             linktitle =>'Set/Modify resource parameters in helper mode.'  ,
                   6746:             icon => 'dialog-information.png'  ,
                   6747:             #help => 'Parameter_Helper',
                   6748:             },
1.568     raeburn  6749:           { linktext => $linktext{'newoverview'},
1.473     amueller 6750:             url => '/adm/parmset?action=newoverview',
1.568     raeburn  6751:             permission => $parm_permission->{'newoverview'},
                   6752:             linktitle => $linktitle{'newoverview'},
                   6753:             icon => 'edit-find.png',
1.473     amueller 6754:             #help => 'Parameter_Overview',
                   6755:             },
1.568     raeburn  6756:           { linktext => $linktext{'settable'},
1.473     amueller 6757:             url => '/adm/parmset?action=settable',
1.568     raeburn  6758:             permission => $parm_permission->{'settable'},
                   6759:             linktitle => $linktitle{'settable'},
                   6760:             icon => 'edit-copy.png',
1.473     amueller 6761:             #help => 'Table_Mode',
                   6762:             }]},
1.417     droeschl 6763:            { categorytitle => 'Existing Parameter Settings for Resources',
1.473     amueller 6764:          items => [
1.570     raeburn  6765:           { linktext => $linktext{'setoverview'},
1.473     amueller 6766:             url => '/adm/parmset?action=setoverview',
1.568     raeburn  6767:             permission => $parm_permission->{'setoverview'},
                   6768:             linktitle => $linktitle{'setoverview'},
                   6769:             icon => 'preferences-desktop-wallpaper.png',
1.473     amueller 6770:             #help => 'Parameter_Overview',
                   6771:             },
                   6772:           { linktext => 'Change Log',
                   6773:             url => '/adm/parmset?action=parameterchangelog',
1.568     raeburn  6774:             permission => $parm_permission->{'parameterchangelog'},
1.477     raeburn  6775:             linktitle =>"View parameter and $lc_crstype blog posting/user notification change log."  ,
1.487     wenzelju 6776:             icon => 'document-properties.png',
1.473     amueller 6777:             }]}
1.193     albertel 6778:           );
1.414     droeschl 6779:     $r->print(&Apache::lonhtmlcommon::generate_menu(@menu));
1.539     raeburn  6780:     $r->print('</form>');
1.507     www      6781:     &endSettingsScreen($r);
1.539     raeburn  6782:     $r->print(&Apache::loncommon::end_page());
1.193     albertel 6783:     return;
                   6784: }
1.414     droeschl 6785: 
1.416     jms      6786: 
                   6787: 
1.560     damieng  6788: ##################################################
                   6789: # PORTFOLIO METADATA
                   6790: ##################################################
                   6791: 
1.563     damieng  6792: # Prints HTML to edit an item of portfolio metadata. The HTML contains several td elements (no tr).
                   6793: # It looks like field titles are not localized.
                   6794: #
                   6795: # @param {Apache2::RequestRec} $r - the Apache request
                   6796: # @param {string} $field_name - metadata field name
                   6797: # @param {string} $field_text - metadata field title, in English unless manually added
                   6798: # @param {boolean} $added_flag - true if the field was manually added
1.252     banghart 6799: sub output_row {
1.347     banghart 6800:     my ($r, $field_name, $field_text, $added_flag) = @_;
1.252     banghart 6801:     my $output;
1.263     banghart 6802:     my $options=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'};
                   6803:     my $values=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.values'};
1.337     banghart 6804:     if (!defined($options)) {
1.254     banghart 6805:         $options = 'active,stuadd';
1.261     banghart 6806:         $values = '';
1.252     banghart 6807:     }
1.337     banghart 6808:     if (!($options =~ /deleted/)) {
                   6809:         my @options= ( ['active', 'Show to student'],
1.418     schafran 6810:                     ['stuadd', 'Provide text area for students to type metadata'],
1.351     banghart 6811:                     ['choices','Provide choices for students to select from']);
1.473     amueller 6812: #           ['onlyone','Student may select only one choice']);
1.337     banghart 6813:         if ($added_flag) {
                   6814:             push @options,['deleted', 'Delete Metadata Field'];
                   6815:         }
1.351     banghart 6816:        $output = &Apache::loncommon::start_data_table_row();
1.451     bisitz   6817:         $output .= '<td><strong>'.$field_text.':</strong></td>';
1.351     banghart 6818:         $output .= &Apache::loncommon::end_data_table_row();
1.337     banghart 6819:         foreach my $opt (@options) {
1.560     damieng  6820:             my $checked = ($options =~ m/$opt->[0]/) ? ' checked="checked" ' : '' ;
                   6821:             $output .= &Apache::loncommon::continue_data_table_row();
                   6822:             $output .= '<td>'.('&nbsp;' x 5).'<label>
                   6823:                     <input type="checkbox" name="'.
                   6824:                     $field_name.'_'.$opt->[0].'" value="yes"'.$checked.' />'.
                   6825:                     &mt($opt->[1]).'</label></td>';
                   6826:             $output .= &Apache::loncommon::end_data_table_row();
                   6827:         }
1.351     banghart 6828:         $output .= &Apache::loncommon::continue_data_table_row();
1.451     bisitz   6829:         $output .= '<td>'.('&nbsp;' x 10).'<input name="'.$field_name.'_values" type="text" value="'.$values.'" size="80" /></td>';
1.351     banghart 6830:         $output .= &Apache::loncommon::end_data_table_row();
                   6831:         my $multiple_checked;
                   6832:         my $single_checked;
                   6833:         if ($options =~ m/onlyone/) {
1.422     bisitz   6834:             $multiple_checked = '';
1.423     bisitz   6835:             $single_checked = ' checked="checked"';
1.351     banghart 6836:         } else {
1.423     bisitz   6837:             $multiple_checked = ' checked="checked"';
1.422     bisitz   6838:             $single_checked = '';
1.351     banghart 6839:         }
1.560     damieng  6840:         $output .= &Apache::loncommon::continue_data_table_row();
                   6841:         $output .= '<td>'.('&nbsp;' x 10).'
                   6842:                     <input type="radio" name="'.$field_name.'_onlyone" value="multiple"'.$multiple_checked .' />
                   6843:                     '.&mt('Student may select multiple choices from list').'</td>';
                   6844:         $output .= &Apache::loncommon::end_data_table_row();
                   6845:         $output .= &Apache::loncommon::continue_data_table_row();
                   6846:         $output .= '<td>'.('&nbsp;' x 10).'
                   6847:                     <input type="radio" name="'.$field_name.'_onlyone"  value="single"'.$single_checked.' />
                   6848:                     '.&mt('Student may select only one choice from list').'</td>';
                   6849:         $output .= &Apache::loncommon::end_data_table_row();
1.252     banghart 6850:     }
                   6851:     return ($output);
                   6852: }
1.416     jms      6853: 
                   6854: 
1.560     damieng  6855: # UI to order portfolio metadata fields.
1.563     damieng  6856: # Currently useless because addmetafield does not work.
                   6857: #
                   6858: # @param {Apache2::RequestRec} $r - the Apache request
1.340     banghart 6859: sub order_meta_fields {
                   6860:     my ($r)=@_;
                   6861:     my $idx = 1;
                   6862:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6863:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6864:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};;
1.341     banghart 6865:     $r->print(&Apache::loncommon::start_page('Order Metadata Fields'));
1.560     damieng  6866:     &Apache::lonhtmlcommon::add_breadcrumb(
                   6867:         {href=>'/adm/parmset?action=addmetadata',
1.473     amueller 6868:         text=>"Add Metadata Field"});
1.560     damieng  6869:     &Apache::lonhtmlcommon::add_breadcrumb(
                   6870:         {href=>"/adm/parmset?action=setrestrictmeta",
                   6871:         text=>"Restrict Metadata"},
                   6872:         {text=>"Order Metadata"});
1.345     banghart 6873:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Order Metadata'));
1.531     raeburn  6874:     &startSettingsScreen($r,'parmset',$crstype);
1.340     banghart 6875:     if ($env{'form.storeorder'}) {
                   6876:         my $newpos = $env{'form.newpos'} - 1;
                   6877:         my $currentpos = $env{'form.currentpos'} - 1;
                   6878:         my @neworder = ();
1.548     raeburn  6879:         my @oldorder = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 6880:         my $i;
1.341     banghart 6881:         if ($newpos > $currentpos) {
1.340     banghart 6882:         # moving stuff up
                   6883:             for ($i=0;$i<$currentpos;$i++) {
1.560     damieng  6884:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 6885:             }
                   6886:             for ($i=$currentpos;$i<$newpos;$i++) {
1.560     damieng  6887:                 $neworder[$i]=$oldorder[$i+1];
1.340     banghart 6888:             }
                   6889:             $neworder[$newpos]=$oldorder[$currentpos];
                   6890:             for ($i=$newpos+1;$i<=$#oldorder;$i++) {
1.560     damieng  6891:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 6892:             }
                   6893:         } else {
                   6894:         # moving stuff down
1.473     amueller 6895:             for ($i=0;$i<$newpos;$i++) {
                   6896:                 $neworder[$i]=$oldorder[$i];
                   6897:             }
                   6898:             $neworder[$newpos]=$oldorder[$currentpos];
                   6899:             for ($i=$newpos+1;$i<$currentpos+1;$i++) {
                   6900:                 $neworder[$i]=$oldorder[$i-1];
                   6901:             }
                   6902:             for ($i=$currentpos+1;$i<=$#oldorder;$i++) {
                   6903:                 $neworder[$i]=$oldorder[$i];
                   6904:             }
1.340     banghart 6905:         }
1.560     damieng  6906:         my $ordered_fields = join ",", @neworder;
1.343     banghart 6907:         my $put_result = &Apache::lonnet::put('environment',
1.560     damieng  6908:                         {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   6909:         &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.metadata.addedorder' => $ordered_fields});
1.340     banghart 6910:     }
1.357     raeburn  6911:     my $fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.341     banghart 6912:     my $ordered_fields;
1.548     raeburn  6913:     my @fields_in_order = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 6914:     if (!@fields_in_order) {
                   6915:         # no order found, pick sorted order then create metadata.addedorder key.
1.548     raeburn  6916:         foreach my $key (sort(keys(%$fields))) {
1.340     banghart 6917:             push @fields_in_order, $key;
1.341     banghart 6918:             $ordered_fields = join ",", @fields_in_order;
1.340     banghart 6919:         }
1.341     banghart 6920:         my $put_result = &Apache::lonnet::put('environment',
1.446     bisitz   6921:                             {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   6922:     }
1.340     banghart 6923:     $r->print('<table>');
                   6924:     my $num_fields = scalar(@fields_in_order);
                   6925:     foreach my $key (@fields_in_order) {
                   6926:         $r->print('<tr><td>');
                   6927:         $r->print('<form method="post" action="">');
1.537     bisitz   6928:         $r->print('<select name="newpos" onchange="this.form.submit()">');
1.340     banghart 6929:         for (my $i = 1;$i le $num_fields;$i ++) {
                   6930:             if ($i eq $idx) {
                   6931:                 $r->print('<option value="'.$i.'"  SELECTED>('.$i.')</option>');
                   6932:             } else {
                   6933:                 $r->print('<option value="'.$i.'">'.$i.'</option>');
                   6934:             }
                   6935:         }
                   6936:         $r->print('</select></td><td>');
                   6937:         $r->print('<input type="hidden" name="currentpos" value="'.$idx.'" />');
                   6938:         $r->print('<input type="hidden" name="storeorder" value="true" />');
                   6939:         $r->print('</form>');
                   6940:         $r->print($$fields{$key}.'</td></tr>');
                   6941:         $idx ++;
                   6942:     }
                   6943:     $r->print('</table>');
1.507     www      6944:     &endSettingsScreen($r);
1.340     banghart 6945:     return 'ok';
                   6946: }
1.416     jms      6947: 
                   6948: 
1.563     damieng  6949: # Returns HTML with a Continue button redirecting to the initial portfolio metadata screen.
                   6950: # @returns {string}
1.359     banghart 6951: sub continue {
                   6952:     my $output;
                   6953:     $output .= '<form action="" method="post">';
                   6954:     $output .= '<input type="hidden" name="action" value="setrestrictmeta" />';
1.586     raeburn  6955:     $output .= '<input type="submit" value="'.&mt('Continue').'" />';
1.359     banghart 6956:     return ($output);
                   6957: }
1.416     jms      6958: 
                   6959: 
1.563     damieng  6960: # UI to add a metadata field.
                   6961: # Currenly does not work because of an HTML error (the field is not visible).
                   6962: #
                   6963: # @param {Apache2::RequestRec} $r - the Apache request
1.334     banghart 6964: sub addmetafield {
                   6965:     my ($r)=@_;
1.414     droeschl 6966:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=addmetadata',
1.473     amueller 6967:         text=>"Add Metadata Field"});
1.334     banghart 6968:     $r->print(&Apache::loncommon::start_page('Add Metadata Field'));
                   6969:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Add Metadata Field'));
1.335     banghart 6970:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6971:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6972:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   6973:     &startSettingsScreen($r,'parmset',$crstype);
1.339     banghart 6974:     if (exists($env{'form.undelete'})) {
1.358     banghart 6975:         my @meta_fields = &Apache::loncommon::get_env_multiple('form.undeletefield');
1.339     banghart 6976:         foreach my $meta_field(@meta_fields) {
                   6977:             my $options = $env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.options'};
                   6978:             $options =~ s/deleted//;
                   6979:             $options =~ s/,,/,/;
                   6980:             my $put_result = &Apache::lonnet::put('environment',
                   6981:                                         {'metadata.'.$meta_field.'.options'=>$options},$dom,$crs);
1.446     bisitz   6982: 
1.586     raeburn  6983:             $r->print(&mt('Undeleted Metadata Field [_1] with result [_2]',
                   6984:                           '<strong>'.$env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.added'}.
                   6985:                           '</strong>',$put_result).
                   6986:                       '<br />');
1.339     banghart 6987:         }
1.359     banghart 6988:         $r->print(&continue());
1.339     banghart 6989:     } elsif (exists($env{'form.fieldname'})) {
1.335     banghart 6990:         my $meta_field = $env{'form.fieldname'};
                   6991:         my $display_field = $env{'form.fieldname'};
                   6992:         $meta_field =~ s/\W/_/g;
1.338     banghart 6993:         $meta_field =~ tr/A-Z/a-z/;
1.335     banghart 6994:         my $put_result = &Apache::lonnet::put('environment',
                   6995:                             {'metadata.'.$meta_field.'.values'=>"",
                   6996:                              'metadata.'.$meta_field.'.added'=>"$display_field",
                   6997:                              'metadata.'.$meta_field.'.options'=>""},$dom,$crs);
1.586     raeburn  6998:         $r->print(&mt('Added new Metadata Field [_1] with result [_2]',
                   6999:                       '<strong>'.$env{'form.fieldname'}.'</strong>',$put_result).
                   7000:                   '<br />');
1.359     banghart 7001:         $r->print(&continue());
1.335     banghart 7002:     } else {
1.357     raeburn  7003:         my $fields = &get_deleted_meta_fieldnames($env{'request.course.id'});
1.339     banghart 7004:         if ($fields) {
1.586     raeburn  7005:             $r->print(&mt('You may undelete previously deleted fields.').
                   7006:                       '<br />'.
                   7007:                       &mt('Check those you wish to undelete and click Undelete.').
                   7008:                       '<br />');
1.339     banghart 7009:             $r->print('<form method="post" action="">');
                   7010:             foreach my $key(keys(%$fields)) {
1.581     raeburn  7011:                 $r->print('<label><input type="checkbox" name="undeletefield" value="'.$key.'" />'.$$fields{$key}.'</label><br /');
1.339     banghart 7012:             }
1.586     raeburn  7013:             $r->print('<input type="submit" name="undelete" value="'.&mt('Undelete').'" />');
1.339     banghart 7014:             $r->print('</form>');
                   7015:         }
1.586     raeburn  7016:         $r->print('<hr />'.
                   7017:                   &mt('[_1]Or[_2] you may enter a new metadata field name.',
                   7018:                       '<strong>','</strong>').
1.581     raeburn  7019:                   '<form method="post" action="/adm/parmset?action=addmetadata">');
1.335     banghart 7020:         $r->print('<input type="text" name="fieldname" /><br />');
1.586     raeburn  7021:         $r->print('<input type="submit" value="'.&mt('Add Metadata Field').'" />');
1.581     raeburn  7022:         $r->print('</form>');
1.334     banghart 7023:     }
1.507     www      7024:     &endSettingsScreen($r);
1.334     banghart 7025: }
1.416     jms      7026: 
                   7027: 
                   7028: 
1.560     damieng  7029: # Display or save portfolio metadata.
1.563     damieng  7030: #
                   7031: # @param {Apache2::RequestRec} $r - the Apache request
1.259     banghart 7032: sub setrestrictmeta {
1.240     banghart 7033:     my ($r)=@_;
1.242     banghart 7034:     my $next_meta;
1.244     banghart 7035:     my $output;
1.245     banghart 7036:     my $item_num;
1.246     banghart 7037:     my $put_result;
1.414     droeschl 7038:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setrestrictmeta',
1.473     amueller 7039:         text=>"Restrict Metadata"});
1.280     albertel 7040:     $r->print(&Apache::loncommon::start_page('Restrict Metadata'));
1.298     albertel 7041:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Restrict Metadata'));
1.240     banghart 7042:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7043:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  7044:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   7045:     &startSettingsScreen($r,'parmset',$crstype);
1.259     banghart 7046:     my $key_base = $env{'course.'.$env{'request.course.id'}.'.'};
1.252     banghart 7047:     my $save_field = '';
1.586     raeburn  7048:     my %lt = &Apache::lonlocal::texthash(
                   7049:                                            addm => 'Add Metadata Field',
                   7050:                                            ordm => 'Order Metadata Fields',
                   7051:                                            save => 'Save',
                   7052:                                         );
1.259     banghart 7053:     if ($env{'form.restrictmeta'}) {
1.254     banghart 7054:         foreach my $field (sort(keys(%env))) {
1.252     banghart 7055:             if ($field=~m/^form.(.+)_(.+)$/) {
1.254     banghart 7056:                 my $options;
1.252     banghart 7057:                 my $meta_field = $1;
                   7058:                 my $meta_key = $2;
1.253     banghart 7059:                 if ($save_field ne $meta_field) {
1.252     banghart 7060:                     $save_field = $meta_field;
1.473     amueller 7061:                     if ($env{'form.'.$meta_field.'_stuadd'}) {
                   7062:                         $options.='stuadd,';
                   7063:                     }
                   7064:                     if ($env{'form.'.$meta_field.'_choices'}) {
                   7065:                         $options.='choices,';
                   7066:                     }
                   7067:                     if ($env{'form.'.$meta_field.'_onlyone'} eq 'single') {
                   7068:                         $options.='onlyone,';
                   7069:                     }
                   7070:                     if ($env{'form.'.$meta_field.'_active'}) {
                   7071:                         $options.='active,';
                   7072:                     }
                   7073:                     if ($env{'form.'.$meta_field.'_deleted'}) {
                   7074:                         $options.='deleted,';
                   7075:                     }
1.259     banghart 7076:                     my $name = $save_field;
1.560     damieng  7077:                     $put_result = &Apache::lonnet::put('environment',
                   7078:                         {'metadata.'.$meta_field.'.options'=>$options,
                   7079:                         'metadata.'.$meta_field.'.values'=>$env{'form.'.$meta_field.'_values'},
                   7080:                         },$dom,$crs);
1.252     banghart 7081:                 }
                   7082:             }
                   7083:         }
                   7084:     }
1.296     albertel 7085:     &Apache::lonnet::coursedescription($env{'request.course.id'},
1.473     amueller 7086:                        {'freshen_cache' => 1});
1.335     banghart 7087:     # Get the default metadata fields
1.258     albertel 7088:     my %metadata_fields = &Apache::lonmeta::fieldnames('portfolio');
1.335     banghart 7089:     # Now get possible added metadata fields
1.357     raeburn  7090:     my $added_metadata_fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.347     banghart 7091:     $output .= &Apache::loncommon::start_data_table();
1.258     albertel 7092:     foreach my $field (sort(keys(%metadata_fields))) {
1.265     banghart 7093:         if ($field ne 'courserestricted') {
1.586     raeburn  7094:             $output.= &output_row($r,$field,$metadata_fields{$field});
1.560     damieng  7095:         }
1.255     banghart 7096:     }
1.351     banghart 7097:     my $buttons = (<<ENDButtons);
1.586     raeburn  7098:         <input type="submit" name="restrictmeta" value="$lt{'save'}" />
1.351     banghart 7099:         </form><br />
                   7100:         <form method="post" action="/adm/parmset?action=addmetadata" name="form1">
1.586     raeburn  7101:         <input type="submit" name="restrictmeta" value="$lt{'addm'}" />
1.351     banghart 7102:         </form>
                   7103:         <br />
                   7104:         <form method="post" action="/adm/parmset?action=ordermetadata" name="form2">
1.586     raeburn  7105:         <input type="submit" name="restrictmeta" value="$lt{'ordm'}" />
1.351     banghart 7106: ENDButtons
1.337     banghart 7107:     my $added_flag = 1;
1.335     banghart 7108:     foreach my $field (sort(keys(%$added_metadata_fields))) {
1.586     raeburn  7109:         $output.= &output_row($r,$field,$$added_metadata_fields{$field},$added_flag);
1.335     banghart 7110:     }
1.347     banghart 7111:     $output .= &Apache::loncommon::end_data_table();
1.446     bisitz   7112:     $r->print(<<ENDenv);
1.259     banghart 7113:         <form method="post" action="/adm/parmset?action=setrestrictmeta" name="form">
1.244     banghart 7114:         $output
1.351     banghart 7115:         $buttons
1.340     banghart 7116:         </form>
1.244     banghart 7117: ENDenv
1.507     www      7118:     &endSettingsScreen($r);
1.280     albertel 7119:     $r->print(&Apache::loncommon::end_page());
1.240     banghart 7120:     return 'ok';
                   7121: }
1.416     jms      7122: 
                   7123: 
1.563     damieng  7124: # Returns metadata fields that have been manually added.
                   7125: #
                   7126: # @param {string} $cid - course id
                   7127: # @returns {hash reference} - hash field name -> field title (not localized)
1.335     banghart 7128: sub get_added_meta_fieldnames {
1.357     raeburn  7129:     my ($cid) = @_;
1.335     banghart 7130:     my %fields;
                   7131:     foreach my $key(%env) {
1.357     raeburn  7132:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.335     banghart 7133:             my $field_name = $1;
                   7134:             my ($display_field_name) = $env{$key};
                   7135:             $fields{$field_name} = $display_field_name;
                   7136:         }
                   7137:     }
                   7138:     return \%fields;
                   7139: }
1.416     jms      7140: 
                   7141: 
1.563     damieng  7142: # Returns metadata fields that have been manually added and deleted.
                   7143: #
                   7144: # @param {string} $cid - course id
                   7145: # @returns {hash reference} - hash field name -> field title (not localized)
1.339     banghart 7146: sub get_deleted_meta_fieldnames {
1.357     raeburn  7147:     my ($cid) = @_;
1.339     banghart 7148:     my %fields;
                   7149:     foreach my $key(%env) {
1.357     raeburn  7150:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.339     banghart 7151:             my $field_name = $1;
                   7152:             if ($env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'} =~ m/deleted/) {
                   7153:                 my ($display_field_name) = $env{$key};
                   7154:                 $fields{$field_name} = $display_field_name;
                   7155:             }
                   7156:         }
                   7157:     }
                   7158:     return \%fields;
                   7159: }
1.560     damieng  7160: 
                   7161: 
                   7162: ##################################################
                   7163: # PARAMETER SETTINGS DEFAULT ACTIONS
                   7164: ##################################################
                   7165: 
                   7166: # UI to change parameter setting default actions
1.563     damieng  7167: #
                   7168: # @param {Apache2::RequestRec} $r - the Apache request
1.220     www      7169: sub defaultsetter {
1.280     albertel 7170:     my ($r) = @_;
                   7171: 
1.414     droeschl 7172:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setdefaults',
1.473     amueller 7173:         text=>"Set Defaults"});
1.531     raeburn  7174:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7175:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   7176:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.446     bisitz   7177:     my $start_page =
1.531     raeburn  7178:         &Apache::loncommon::start_page('Parameter Setting Default Actions');
1.298     albertel 7179:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Defaults');
1.507     www      7180:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  7181:     &startSettingsScreen($r,'parmset',$crstype);
1.507     www      7182:     $r->print('<form method="post" action="/adm/parmset?action=setdefaults" name="defaultform">');
1.280     albertel 7183: 
1.221     www      7184:     my @ids=();
                   7185:     my %typep=();
                   7186:     my %keyp=();
                   7187:     my %allparms=();
                   7188:     my %allparts=();
                   7189:     my %allmaps=();
                   7190:     my %mapp=();
                   7191:     my %symbp=();
                   7192:     my %maptitles=();
                   7193:     my %uris=();
                   7194:     my %keyorder=&standardkeyorder();
                   7195:     my %defkeytype=();
                   7196: 
1.446     bisitz   7197:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 7198:                 \%mapp, \%symbp,\%maptitles,\%uris,
                   7199:                 \%keyorder,\%defkeytype);
1.224     www      7200:     if ($env{'form.storerules'}) {
1.560     damieng  7201:         my %newrules=();
                   7202:         my @delrules=();
                   7203:         my %triggers=();
                   7204:         foreach my $key (keys(%env)) {
1.225     albertel 7205:             if ($key=~/^form\.(\w+)\_action$/) {
1.560     damieng  7206:                 my $tempkey=$1;
                   7207:                 my $action=$env{$key};
1.226     www      7208:                 if ($action) {
1.560     damieng  7209:                     $newrules{$tempkey.'_action'}=$action;
                   7210:                     if ($action ne 'default') {
                   7211:                         my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
                   7212:                         $triggers{$whichparm}.=$tempkey.':';
                   7213:                     }
                   7214:                     $newrules{$tempkey.'_type'}=$defkeytype{$tempkey};
                   7215:                     if (&isdateparm($defkeytype{$tempkey})) {
                   7216:                         $newrules{$tempkey.'_days'}=$env{'form.'.$tempkey.'_days'};
                   7217:                         $newrules{$tempkey.'_hours'}=$env{'form.'.$tempkey.'_hours'};
                   7218:                         $newrules{$tempkey.'_min'}=$env{'form.'.$tempkey.'_min'};
                   7219:                         $newrules{$tempkey.'_sec'}=$env{'form.'.$tempkey.'_sec'};
                   7220:                     } else {
                   7221:                         $newrules{$tempkey.'_value'}=$env{'form.'.$tempkey.'_value'};
                   7222:                         $newrules{$tempkey.'_triggervalue'}=$env{'form.'.$tempkey.'_triggervalue'};
                   7223:                     }
                   7224:                 } else {
                   7225:                     push(@delrules,$tempkey.'_action');
                   7226:                     push(@delrules,$tempkey.'_type');
                   7227:                     push(@delrules,$tempkey.'_hours');
                   7228:                     push(@delrules,$tempkey.'_min');
                   7229:                     push(@delrules,$tempkey.'_sec');
                   7230:                     push(@delrules,$tempkey.'_value');
                   7231:                 }
1.473     amueller 7232:             }
                   7233:         }
1.560     damieng  7234:         foreach my $key (keys(%allparms)) {
                   7235:             $newrules{$key.'_triggers'}=$triggers{$key};
1.473     amueller 7236:         }
1.560     damieng  7237:         &Apache::lonnet::put('parmdefactions',\%newrules,$cdom,$cnum);
                   7238:         &Apache::lonnet::del('parmdefactions',\@delrules,$cdom,$cnum);
                   7239:         &resetrulescache();
1.224     www      7240:     }
1.227     www      7241:     my %lt=&Apache::lonlocal::texthash('days' => 'Days',
1.473     amueller 7242:                        'hours' => 'Hours',
                   7243:                        'min' => 'Minutes',
                   7244:                        'sec' => 'Seconds',
                   7245:                        'yes' => 'Yes',
                   7246:                        'no' => 'No');
1.222     www      7247:     my @standardoptions=('','default');
                   7248:     my @standarddisplay=('',&mt('Default value when manually setting'));
                   7249:     my @dateoptions=('','default');
                   7250:     my @datedisplay=('',&mt('Default value when manually setting'));
                   7251:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  7252:         unless ($tempkey) { next; }
                   7253:         push @standardoptions,'when_setting_'.$tempkey;
                   7254:         push @standarddisplay,&mt('Automatically set when setting ').$tempkey;
                   7255:         if (&isdateparm($defkeytype{$tempkey})) {
                   7256:             push @dateoptions,'later_than_'.$tempkey;
                   7257:             push @datedisplay,&mt('Automatically set later than ').$tempkey;
                   7258:             push @dateoptions,'earlier_than_'.$tempkey;
                   7259:             push @datedisplay,&mt('Automatically set earlier than ').$tempkey;
                   7260:         }
1.222     www      7261:     }
1.563     damieng  7262:     $r->print(&mt('Manual setting rules apply to all interfaces.').'<br />'.
                   7263:         &mt('Automatic setting rules apply to table mode interfaces only.'));
1.318     albertel 7264:     $r->print("\n".&Apache::loncommon::start_data_table().
1.473     amueller 7265:           &Apache::loncommon::start_data_table_header_row().
                   7266:           "<th>".&mt('Rule for parameter').'</th><th>'.
                   7267:           &mt('Action').'</th><th>'.&mt('Value').'</th>'.
                   7268:           &Apache::loncommon::end_data_table_header_row());
1.221     www      7269:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  7270:         unless ($tempkey) { next; }
                   7271:         $r->print("\n".&Apache::loncommon::start_data_table_row().
                   7272:             "<td>".$allparms{$tempkey}."\n<br />(".$tempkey.')</td><td>');
                   7273:         my $action=&rulescache($tempkey.'_action');
                   7274:         $r->print('<select name="'.$tempkey.'_action">');
                   7275:         if (&isdateparm($defkeytype{$tempkey})) {
                   7276:             for (my $i=0;$i<=$#dateoptions;$i++) {
                   7277:             if ($dateoptions[$i]=~/\_$tempkey$/) { next; }
                   7278:             $r->print("\n<option value='$dateoptions[$i]'".
                   7279:                 ($dateoptions[$i] eq $action?' selected="selected"':'').
                   7280:                 ">$datedisplay[$i]</option>");
                   7281:             }
                   7282:         } else {
                   7283:             for (my $i=0;$i<=$#standardoptions;$i++) {
                   7284:             if ($standardoptions[$i]=~/\_$tempkey$/) { next; }
                   7285:             $r->print("\n<option value='$standardoptions[$i]'".
                   7286:                 ($standardoptions[$i] eq $action?' selected="selected"':'').
                   7287:                 ">$standarddisplay[$i]</option>");
                   7288:             }
1.473     amueller 7289:         }
1.560     damieng  7290:         $r->print('</select>');
                   7291:         unless (&isdateparm($defkeytype{$tempkey})) {
                   7292:             $r->print("\n<br />".&mt('Triggering value(s) of other parameter (optional, comma-separated):').
                   7293:                 '<input type="text" size="20" name="'.$tempkey.'_triggervalue" value="'.&rulescache($tempkey.'_triggervalue').'" />');
1.473     amueller 7294:         }
1.560     damieng  7295:         $r->print("\n</td><td>\n");
1.222     www      7296: 
1.221     www      7297:         if (&isdateparm($defkeytype{$tempkey})) {
1.560     damieng  7298:             my $days=&rulescache($tempkey.'_days');
                   7299:             my $hours=&rulescache($tempkey.'_hours');
                   7300:             my $min=&rulescache($tempkey.'_min');
                   7301:             my $sec=&rulescache($tempkey.'_sec');
                   7302:             $r->print(<<ENDINPUTDATE);
                   7303:     <input name="$tempkey\_days" type="text" size="4" value="$days" />$lt{'days'}<br />
                   7304:     <input name="$tempkey\_hours" type="text" size="4" value="$hours" />$lt{'hours'}<br />
                   7305:     <input name="$tempkey\_min" type="text" size="4" value="$min" />$lt{'min'}<br />
                   7306:     <input name="$tempkey\_sec" type="text" size="4" value="$sec" />$lt{'sec'}
1.564     raeburn  7307: ENDINPUTDATE
1.560     damieng  7308:         } elsif ($defkeytype{$tempkey} eq 'string_yesno') {
                   7309:                 my $yeschecked='';
                   7310:                 my $nochecked='';
                   7311:                 if (&rulescache($tempkey.'_value') eq 'yes') { $yeschecked=' checked="checked"'; }
                   7312:                 if (&rulescache($tempkey.'_value') eq 'no') { $nochecked=' checked="checked"'; }
                   7313: 
                   7314:             $r->print(<<ENDYESNO);
                   7315:     <label><input type="radio" name="$tempkey\_value" value="yes"$yeschecked /> $lt{'yes'}</label><br />
                   7316:     <label><input type="radio" name="$tempkey\_value" value="no"$nochecked /> $lt{'no'}</label>
1.564     raeburn  7317: ENDYESNO
1.221     www      7318:         } else {
1.560     damieng  7319:             $r->print('<input type="text" size="20" name="'.$tempkey.'_value" value="'.&rulescache($tempkey.'_value').'" />');
                   7320:         }
1.318     albertel 7321:         $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.221     www      7322:     }
1.318     albertel 7323:     $r->print(&Apache::loncommon::end_data_table().
1.473     amueller 7324:           "\n".'<input type="submit" name="storerules" value="'.
1.507     www      7325:           &mt('Save').'" /></form>'."\n");
                   7326:     &endSettingsScreen($r);
                   7327:     $r->print(&Apache::loncommon::end_page());
1.220     www      7328:     return;
                   7329: }
1.193     albertel 7330: 
1.560     damieng  7331: ##################################################
                   7332: # PARAMETER CHANGES LOG
                   7333: ##################################################
                   7334: 
1.563     damieng  7335: # Returns some info for a parameter log entry.
                   7336: # Returned entries:
                   7337: # $realm - HTML title for the parameter level and resource
                   7338: # $section - parameter section
                   7339: # $name - parameter name
                   7340: # $part - parameter part
                   7341: # $what - $part.'.'.$name
                   7342: # $middle - resource symb ?
                   7343: # $uname - user name (same as given)
                   7344: # $udom - user domain (same as given)
                   7345: # $issection - section or group name
                   7346: # $realmdescription - title for the parameter level and resource (without using HTML)
                   7347: #
                   7348: # @param {string} $key - parameter log key
                   7349: # @param {string} $uname - user name
                   7350: # @param {string} $udom - user domain
                   7351: # @param {boolean} $typeflag - .type log entry
                   7352: # @returns {Array}
1.290     www      7353: sub components {
1.581     raeburn  7354:     my ($key,$uname,$udom,$typeflag)=@_;
1.330     albertel 7355: 
                   7356:     if ($typeflag) {
1.560     damieng  7357:         $key=~s/\.type$//;
1.290     www      7358:     }
1.330     albertel 7359: 
                   7360:     my ($middle,$part,$name)=
1.572     damieng  7361:         ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.291     www      7362:     my $issection;
1.330     albertel 7363: 
1.290     www      7364:     my $section=&mt('All Students');
                   7365:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  7366:         $issection=$1;
                   7367:         $section=&mt('Group/Section').': '.$issection;
                   7368:         $middle=~s/^\[(.*)\]//;
1.290     www      7369:     }
                   7370:     $middle=~s/\.+$//;
                   7371:     $middle=~s/^\.+//;
1.291     www      7372:     if ($uname) {
1.560     damieng  7373:         $section=&mt('User').": ".&Apache::loncommon::plainname($uname,$udom);
                   7374:         $issection='';
1.291     www      7375:     }
1.316     albertel 7376:     my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.446     bisitz   7377:     my $realmdescription=&mt('all resources');
1.556     raeburn  7378:     if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   7379:         my $mapurl = $1;
                   7380:         my $maplevel = $2;
                   7381:         my $leveltitle = &mt('Folder/Map');
                   7382:         if ($maplevel eq 'rec') {
                   7383:             $leveltitle = &mt('Recursive');
                   7384:         }
1.560     damieng  7385:         $realm='<span class="LC_parm_scope_folder">'.$leveltitle.
                   7386:             ': '.&Apache::lonnet::gettitle($mapurl).' <span class="LC_parm_folder"><br />('.
                   7387:             $mapurl.')</span></span>';
                   7388:         $realmdescription=&mt('folder').' '.&Apache::lonnet::gettitle($mapurl);
                   7389:     } elsif ($middle) {
                   7390:         my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
                   7391:         $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   7392:             ': '.&Apache::lonnet::gettitle($middle).' <br /><span class="LC_parm_symb">('.$url.
                   7393:             ' in '.$map.' id: '.$id.')</span></span>';
                   7394:         $realmdescription=&mt('resource').' '.&Apache::lonnet::gettitle($middle);
1.290     www      7395:     }
1.291     www      7396:     my $what=$part.'.'.$name;
1.330     albertel 7397:     return ($realm,$section,$name,$part,
1.473     amueller 7398:         $what,$middle,$uname,$udom,$issection,$realmdescription);
1.290     www      7399: }
1.293     www      7400: 
1.563     damieng  7401: my %standard_parms; # hash parameter name -> parameter title (not localized)
                   7402: my %standard_parms_types; # hash parameter name -> parameter type
1.416     jms      7403: 
1.563     damieng  7404: # Reads parameter info from packages.tab into %standard_parms.
1.328     albertel 7405: sub load_parameter_names {
1.583     raeburn  7406:     open(my $config,"<","$Apache::lonnet::perlvar{'lonTabDir'}/packages.tab");
1.328     albertel 7407:     while (my $configline=<$config>) {
1.560     damieng  7408:         if ($configline !~ /\S/ || $configline=~/^\#/) { next; }
                   7409:         chomp($configline);
                   7410:         my ($short,$plain)=split(/:/,$configline);
                   7411:         my (undef,$name,$type)=split(/\&/,$short,3);
                   7412:         if ($type eq 'display') {
                   7413:             $standard_parms{$name} = $plain;
1.469     raeburn  7414:         } elsif ($type eq 'type') {
1.560     damieng  7415:                 $standard_parms_types{$name} = $plain;
1.469     raeburn  7416:         }
1.328     albertel 7417:     }
                   7418:     close($config);
                   7419:     $standard_parms{'int_pos'}      = 'Positive Integer';
                   7420:     $standard_parms{'int_zero_pos'} = 'Positive Integer or Zero';
1.575     raeburn  7421:     $standard_parms{'scoreformat'}  = 'Format for display of score';
1.328     albertel 7422: }
                   7423: 
1.563     damieng  7424: # Returns a parameter title for standard parameters, the name for others.
                   7425: #
                   7426: # @param {string} $name - parameter name
                   7427: # @returns {string}
1.292     www      7428: sub standard_parameter_names {
                   7429:     my ($name)=@_;
1.328     albertel 7430:     if (!%standard_parms) {
1.560     damieng  7431:         &load_parameter_names();
1.328     albertel 7432:     }
1.292     www      7433:     if ($standard_parms{$name}) {
1.560     damieng  7434:         return $standard_parms{$name};
1.446     bisitz   7435:     } else {
1.560     damieng  7436:         return $name;
1.292     www      7437:     }
                   7438: }
1.290     www      7439: 
1.563     damieng  7440: # Returns a parameter type for standard parameters, undef for others.
                   7441: #
                   7442: # @param {string} $name - parameter name
                   7443: # @returns {string}
1.469     raeburn  7444: sub standard_parameter_types {
                   7445:     my ($name)=@_;
                   7446:     if (!%standard_parms_types) {
                   7447:         &load_parameter_names();
                   7448:     }
                   7449:     if ($standard_parms_types{$name}) {
                   7450:         return $standard_parms_types{$name};
                   7451:     }
                   7452:     return;
                   7453: }
1.309     www      7454: 
1.563     damieng  7455: # Returns a parameter level title (not localized) from the parameter level name.
                   7456: #
                   7457: # @param {string} $name - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   7458: # @returns {string}
1.557     raeburn  7459: sub standard_parameter_levels {
                   7460:     my ($name)=@_;
                   7461:     my %levels = (
                   7462:                     'resourcelevel'   => 'a single resource',
                   7463:                     'maplevel'        => 'the enclosing map/folder', 
                   7464:                     'maplevelrecurse' => 'the enclosing map/folder (recursive into sub-folders)',
                   7465:                     'courselevel'     => 'the general (course) level',
                   7466:                  );
                   7467:     if ($levels{$name}) {
                   7468:         return $levels{$name};
                   7469:     }
                   7470:     return;
                   7471: }
                   7472: 
1.560     damieng  7473: # Display log for parameter changes, blog postings, user notification changes.
1.563     damieng  7474: #
                   7475: # @param {Apache2::RequestRec} $r - the Apache request
1.285     albertel 7476: sub parm_change_log {
1.568     raeburn  7477:     my ($r,$parm_permission)=@_;
1.531     raeburn  7478:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7479:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.569     raeburn  7480:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 7481:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1.473     amueller 7482:     text=>"Parameter Change Log"});
1.522     raeburn  7483:     my $js = '<script type="text/javascript">'."\n".
                   7484:              '// <![CDATA['."\n".
                   7485:              &Apache::loncommon::display_filter_js('parmslog')."\n".
                   7486:              '// ]]>'."\n".
                   7487:              '</script>'."\n";
                   7488:     $r->print(&Apache::loncommon::start_page('Parameter Change Log',$js));
1.327     albertel 7489:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Parameter Change Log'));
1.531     raeburn  7490:     &startSettingsScreen($r,'parmset',$crstype);
                   7491:     my %parmlog=&Apache::lonnet::dump('nohist_parameterlog',$cdom,$cnum);
1.311     albertel 7492: 
1.301     www      7493:     if ((keys(%parmlog))[0]=~/^error\:/) { undef(%parmlog); }
1.311     albertel 7494: 
1.522     raeburn  7495:     $r->print('<div class="LC_left_float">'.
                   7496:               '<fieldset><legend>'.&mt('Display of Changes').'</legend>'.
                   7497:               '<form action="/adm/parmset?action=parameterchangelog"
1.327     albertel 7498:                      method="post" name="parameterlog">');
1.446     bisitz   7499: 
1.311     albertel 7500:     my %saveable_parameters = ('show' => 'scalar',);
                   7501:     &Apache::loncommon::store_course_settings('parameter_log',
                   7502:                                               \%saveable_parameters);
                   7503:     &Apache::loncommon::restore_course_settings('parameter_log',
                   7504:                                                 \%saveable_parameters);
1.522     raeburn  7505:     $r->print(&Apache::loncommon::display_filter('parmslog').'&nbsp;'."\n".
                   7506:               '<input type="submit" value="'.&mt('Display').'" />'.
                   7507:               '</form></fieldset></div><br clear="all" />');
1.301     www      7508: 
1.568     raeburn  7509:     my $readonly = 1;
                   7510:     if ($parm_permission->{'edit'}) {
                   7511:         undef($readonly);
                   7512:     }
1.531     raeburn  7513:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.301     www      7514:     $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
1.473     amueller 7515:           '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Extent').'</th><th>'.&mt('Users').'</th><th>'.
1.568     raeburn  7516:           &mt('Parameter').'</th><th>'.&mt('Part').'</th><th>'.&mt('New Value').'</th>');
                   7517:     unless ($readonly) {
                   7518:         $r->print('<th>'.&mt('Announce').'</th>');
                   7519:     }
                   7520:     $r->print(&Apache::loncommon::end_data_table_header_row());
1.309     www      7521:     my $shown=0;
1.349     www      7522:     my $folder='';
                   7523:     if ($env{'form.displayfilter'} eq 'currentfolder') {
1.560     damieng  7524:         my $last='';
                   7525:         if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
                   7526:                 &GDBM_READER(),0640)) {
                   7527:             $last=$hash{'last_known'};
                   7528:             untie(%hash);
                   7529:         }
                   7530:         if ($last) { ($folder) = &Apache::lonnet::decode_symb($last); }
                   7531:     }
1.595     raeburn  7532:     my $numgroups = 0;
                   7533:     my @groups;
                   7534:     if ($env{'request.course.groups'} ne '') {
                   7535:         @groups = split(/:/,$env{'request.course.groups'});
                   7536:         $numgroups = scalar(@groups);
                   7537:     }
1.560     damieng  7538:     foreach my $id (sort {
                   7539:                 if ($parmlog{$b}{'exe_time'} ne $parmlog{$a}{'exe_time'}) {
                   7540:                     return $parmlog{$b}{'exe_time'} <=>$parmlog{$a}{'exe_time'}
                   7541:                 }
                   7542:                 my $aid = (split('00000',$a))[-1];
                   7543:                 my $bid = (split('00000',$b))[-1];
                   7544:                 return $bid<=>$aid;
1.473     amueller 7545:             } (keys(%parmlog))) {
1.294     www      7546:         my @changes=keys(%{$parmlog{$id}{'logentry'}});
1.560     damieng  7547:         my $count = 0;
                   7548:         my $time =
                   7549:             &Apache::lonlocal::locallocaltime($parmlog{$id}{'exe_time'});
                   7550:         my $plainname =
                   7551:             &Apache::loncommon::plainname($parmlog{$id}{'exe_uname'},
                   7552:                         $parmlog{$id}{'exe_udom'});
                   7553:         my $about_me_link =
                   7554:             &Apache::loncommon::aboutmewrapper($plainname,
                   7555:                             $parmlog{$id}{'exe_uname'},
                   7556:                             $parmlog{$id}{'exe_udom'});
                   7557:         my $send_msg_link='';
1.568     raeburn  7558:         if ((!$readonly) && 
                   7559:             (($parmlog{$id}{'exe_uname'} ne $env{'user.name'})
1.560     damieng  7560:             || ($parmlog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
                   7561:             $send_msg_link ='<br />'.
                   7562:             &Apache::loncommon::messagewrapper(&mt('Send message'),
                   7563:                             $parmlog{$id}{'exe_uname'},
                   7564:                             $parmlog{$id}{'exe_udom'});
                   7565:         }
                   7566:         my $row_start=&Apache::loncommon::start_data_table_row();
                   7567:         my $makenewrow=0;
                   7568:         my %istype=();
                   7569:         my $output;
                   7570:         foreach my $changed (reverse(sort(@changes))) {
                   7571:                 my $value=$parmlog{$id}{'logentry'}{$changed};
                   7572:             my $typeflag = ($changed =~/\.type$/ &&
                   7573:                     !exists($parmlog{$id}{'logentry'}{$changed.'.type'}));
1.330     albertel 7574:             my ($realm,$section,$parmname,$part,$what,$middle,$uname,$udom,$issection,$realmdescription)=
1.581     raeburn  7575:                 &components($changed,$parmlog{$id}{'uname'},$parmlog{$id}{'udom'},$typeflag);
1.560     damieng  7576:             if ($env{'request.course.sec'} ne '') {
1.595     raeburn  7577:                 next if (($issection ne '') && (!(($issection eq $env{'request.course.sec'}) ||
                   7578:                                                   ($numgroups && (grep(/^\Q$issection\E$/,@groups))))));
1.560     damieng  7579:                 if ($uname ne '') {
                   7580:                     my $stusection = &Apache::lonnet::getsection($uname,$udom,$env{'request.course.id'});
                   7581:                     next if (($stusection ne '-1') && ($stusection ne $env{'request.course.sec'})); 
                   7582:                 }
                   7583:             }
                   7584:             if ($env{'form.displayfilter'} eq 'currentfolder') {
                   7585:                 if ($folder) {
                   7586:                     if ($middle!~/^\Q$folder\E/) { next; }
                   7587:                 }
                   7588:             }
                   7589:             if ($typeflag) {
                   7590:                 $istype{$parmname}=$value;
                   7591:                 if (!$env{'form.includetypes'}) { next; }
                   7592:             }
                   7593:             $count++;
                   7594:             if ($makenewrow) {
                   7595:                 $output .= $row_start;
                   7596:             } else {
                   7597:                 $makenewrow=1;
                   7598:             }
1.470     raeburn  7599:             my $parmitem = &standard_parameter_names($parmname);
1.560     damieng  7600:             $output .='<td>'.$realm.'</td><td>'.$section.'</td><td>'.
                   7601:                 &mt($parmitem).'</td><td>'.
                   7602:                 ($part?&mt('Part: [_1]',$part):&mt('All Parts')).'</td><td>';
                   7603:             my $stillactive=0;
                   7604:             if ($parmlog{$id}{'delflag'}) {
                   7605:                 $output .= &mt('Deleted');
                   7606:             } else {
                   7607:                 if ($typeflag) {
1.470     raeburn  7608:                     my $parmitem = &standard_parameter_names($value); 
                   7609:                     $parmitem = &mt($parmitem);
1.560     damieng  7610:                     $output .= &mt('Type: [_1]',$parmitem);
                   7611:                 } else {
1.584     raeburn  7612:                     my $toolsymb;
                   7613:                     if ($middle =~ /ext\.tool$/) {
                   7614:                         $toolsymb = $middle;
                   7615:                     }
1.560     damieng  7616:                     my ($level,@all)=&parmval_by_symb($what,$middle,
1.584     raeburn  7617:                         &Apache::lonnet::metadata($middle,$what,$toolsymb),
1.560     damieng  7618:                         $uname,$udom,$issection,$issection,$courseopt);
1.469     raeburn  7619:                     my $showvalue = $value;
                   7620:                     if ($istype{$parmname} eq '') {
                   7621:                         my $type = &standard_parameter_types($parmname);
                   7622:                         if ($type ne '') {
                   7623:                             if (&isdateparm($type)) {
                   7624:                                 $showvalue =
                   7625:                                     &Apache::lonlocal::locallocaltime($value);
                   7626:                             }
                   7627:                         }
                   7628:                     } else {
1.560     damieng  7629:                         if (&isdateparm($istype{$parmname})) {
                   7630:                             $showvalue = &Apache::lonlocal::locallocaltime($value);
                   7631:                         }
1.469     raeburn  7632:                     }
                   7633:                     $output .= $showvalue;
1.560     damieng  7634:                     if ($value ne $all[$level]) {
                   7635:                         $output .= '<br /><span class="LC_warning">'.&mt('Not active anymore').'</span>';
                   7636:                     } else {
                   7637:                         $stillactive=1;
                   7638:                     }
                   7639:                 }
1.473     amueller 7640:             }
1.568     raeburn  7641:             $output .= '</td>';
                   7642: 
                   7643:             unless ($readonly) { 
                   7644:                 $output .= '<td>';
                   7645:                 if ($stillactive) {
                   7646:                     my $parmitem = &standard_parameter_names($parmname);
                   7647:                     $parmitem = &mt($parmitem);
                   7648:                     my $title=&mt('Changed [_1]',$parmitem);
                   7649:                     my $description=&mt('Changed [_1] for [_2] to [_3]',
                   7650:                         $parmitem,$realmdescription,
                   7651:                         (&isdateparm($istype{$parmname})?&Apache::lonlocal::locallocaltime($value):$value));
                   7652:                     if (($uname) && ($udom)) {
                   7653:                         $output .=
                   7654:                         &Apache::loncommon::messagewrapper('Notify User',
                   7655:                                                            $uname,$udom,$title,
                   7656:                                                            $description);
                   7657:                     } else {
                   7658:                         $output .=
                   7659:                             &Apache::lonrss::course_blog_link($id,$title,
                   7660:                                                               $description);
                   7661:                     }
1.560     damieng  7662:                 }
1.568     raeburn  7663:                 $output .= '</td>';
1.560     damieng  7664:             }
1.568     raeburn  7665:             $output .= &Apache::loncommon::end_data_table_row();
1.473     amueller 7666:         }
1.560     damieng  7667:         if ($env{'form.displayfilter'} eq 'containing') {
                   7668:             my $wholeentry=$about_me_link.':'.
                   7669:             $parmlog{$id}{'exe_uname'}.':'.$parmlog{$id}{'exe_udom'}.':'.
                   7670:             $output;
                   7671:             if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
1.473     amueller 7672:         }
1.349     www      7673:         if ($count) {
1.560     damieng  7674:             $r->print($row_start.'<td rowspan="'.$count.'">'.$time.'</td>
                   7675:                         <td rowspan="'.$count.'">'.$about_me_link.
                   7676:             '<br /><tt>'.$parmlog{$id}{'exe_uname'}.
                   7677:                         ':'.$parmlog{$id}{'exe_udom'}.'</tt>'.
                   7678:             $send_msg_link.'</td>'.$output);
                   7679:             $shown++;
                   7680:         }
                   7681:         if (!($env{'form.show'} eq &mt('all')
                   7682:             || $shown<=$env{'form.show'})) { last; }
1.286     www      7683:     }
1.301     www      7684:     $r->print(&Apache::loncommon::end_data_table());
1.507     www      7685:     &endSettingsScreen($r);
1.284     www      7686:     $r->print(&Apache::loncommon::end_page());
                   7687: }
                   7688: 
1.560     damieng  7689: ##################################################
                   7690: # MISC !
                   7691: ##################################################
                   7692: 
1.563     damieng  7693: # Stores slot information.
1.560     damieng  7694: # Used by table UI
1.563     damieng  7695: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   7696: #
                   7697: # @param {string} $slot_name - slot name
                   7698: # @param {string} $cdom - course domain
                   7699: # @param {string} $cnum - course number
                   7700: # @param {string} $symb - resource symb
                   7701: # @param {string} $uname - user name
                   7702: # @param {string} $udom - user domain
                   7703: # @returns {string} - 'ok' or error name
1.437     raeburn  7704: sub update_slots {
                   7705:     my ($slot_name,$cdom,$cnum,$symb,$uname,$udom) = @_;
                   7706:     my %slot=&Apache::lonnet::get_slot($slot_name);
                   7707:     if (!keys(%slot)) {
                   7708:         return 'error: slot does not exist';
                   7709:     }
                   7710:     my $max=$slot{'maxspace'};
                   7711:     if (!defined($max)) { $max=99999; }
                   7712: 
                   7713:     my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
                   7714:                                        "^$slot_name\0");
                   7715:     my ($tmp)=%consumed;
                   7716:     if ($tmp=~/^error: 2 / ) {
                   7717:         return 'error: unable to determine current slot status';
                   7718:     }
                   7719:     my $last=0;
                   7720:     foreach my $key (keys(%consumed)) {
                   7721:         my $num=(split('\0',$key))[1];
                   7722:         if ($num > $last) { $last=$num; }
                   7723:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   7724:             return 'ok';
                   7725:         }
                   7726:     }
                   7727: 
                   7728:     if (scalar(keys(%consumed)) >= $max) {
                   7729:         return 'error: no space left in slot';
                   7730:     }
                   7731:     my $wanted=$last+1;
                   7732: 
                   7733:     my %reservation=('name'      => $uname.':'.$udom,
                   7734:                      'timestamp' => time,
                   7735:                      'symb'      => $symb);
                   7736: 
                   7737:     my $success=&Apache::lonnet::newput('slot_reservations',
                   7738:                                         {"$slot_name\0$wanted" =>
                   7739:                                              \%reservation},
                   7740:                                         $cdom, $cnum);
1.438     raeburn  7741:     if ($success eq 'ok') {
                   7742:         my %storehash = (
                   7743:                           symb    => $symb,
                   7744:                           slot    => $slot_name,
                   7745:                           action  => 'reserve',
                   7746:                           context => 'parameter',
                   7747:                         );
1.526     raeburn  7748:         &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  7749:                                    '',$uname,$udom,$cnum,$cdom);
1.438     raeburn  7750: 
1.526     raeburn  7751:         &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  7752:                                    '',$uname,$udom,$uname,$udom);
1.438     raeburn  7753:     }
1.437     raeburn  7754:     return $success;
                   7755: }
                   7756: 
1.563     damieng  7757: # Deletes a slot reservation.
1.560     damieng  7758: # Used by table UI
1.563     damieng  7759: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   7760: #
                   7761: # @param {string} $slot_name - slot name
                   7762: # @param {string} $cdom - course domain
                   7763: # @param {string} $cnum - course number
                   7764: # @param {string} $uname - user name
                   7765: # @param {string} $udom - user domain
                   7766: # @param {string} $symb - resource symb
                   7767: # @returns {string} - 'ok' or error name
1.437     raeburn  7768: sub delete_slots {
                   7769:     my ($slot_name,$cdom,$cnum,$uname,$udom,$symb) = @_;
                   7770:     my $delresult;
                   7771:     my %consumed = &Apache::lonnet::dump('slot_reservations',$cdom,
                   7772:                                          $cnum, "^$slot_name\0");
                   7773:     if (&Apache::lonnet::error(%consumed)) {
                   7774:         return 'error: unable to determine current slot status';
                   7775:     }
                   7776:     my ($tmp)=%consumed;
                   7777:     if ($tmp=~/^error: 2 /) {
                   7778:         return 'error: unable to determine current slot status';
                   7779:     }
                   7780:     foreach my $key (keys(%consumed)) {
                   7781:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   7782:             my $num=(split('\0',$key))[1];
                   7783:             my $entry = $slot_name.'\0'.$num;
                   7784:             $delresult = &Apache::lonnet::del('slot_reservations',[$entry],
                   7785:                                               $cdom,$cnum);
                   7786:             if ($delresult eq 'ok') {
                   7787:                 my %storehash = (
                   7788:                                   symb    => $symb,
                   7789:                                   slot    => $slot_name,
                   7790:                                   action  => 'release',
                   7791:                                   context => 'parameter',
                   7792:                                 );
1.526     raeburn  7793:                 &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  7794:                                            1,$uname,$udom,$cnum,$cdom);
1.526     raeburn  7795:                 &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  7796:                                            1,$uname,$udom,$uname,$udom);
1.437     raeburn  7797:             }
                   7798:         }
                   7799:     }
                   7800:     return $delresult;
                   7801: }
                   7802: 
1.563     damieng  7803: # Returns true if there is a current course.
1.560     damieng  7804: # Used by handler
1.563     damieng  7805: #
                   7806: # @returns {boolean}
1.355     albertel 7807: sub check_for_course_info {
                   7808:     my $navmap = Apache::lonnavmaps::navmap->new();
                   7809:     return 1 if ($navmap);
                   7810:     return 0;
                   7811: }
                   7812: 
1.563     damieng  7813: # Returns the current course host and host LON-CAPA version.
                   7814: #
                   7815: # @returns {Array} - (course hostname, major version number, minor version number)
1.514     raeburn  7816: sub parameter_release_vars { 
1.504     raeburn  7817:    my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7818:    my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   7819:    my $chostname = &Apache::lonnet::hostname($chome);
                   7820:    my ($cmajor,$cminor) = 
                   7821:        split(/\./,&Apache::lonnet::get_server_loncaparev($cdom,$chome));
                   7822:    return ($chostname,$cmajor,$cminor);
                   7823: }
                   7824: 
1.563     damieng  7825: # Checks if the course host version can handle a parameter required version,
                   7826: # and if it does, stores the release needed for the course.
                   7827: #
                   7828: # @param {string} $name - parameter name
                   7829: # @param {string} $value - parameter value
                   7830: # @param {string} $valmatch - name of the test used for checking the value
                   7831: # @param {string} $namematch - name of the test used for checking the name
                   7832: # @param {string} $needsrelease - version needed by the parameter, major.minor
                   7833: # @param {integer} $cmajor - course major version number
                   7834: # @param {integer} $cminor - course minor version number
                   7835: # @returns {boolean} - true if a newer version is needed
1.514     raeburn  7836: sub parameter_releasecheck {
1.557     raeburn  7837:     my ($name,$value,$valmatch,$namematch,$needsrelease,$cmajor,$cminor) = @_;
1.504     raeburn  7838:     my $needsnewer;
                   7839:     my ($needsmajor,$needsminor) = split(/\./,$needsrelease);
                   7840:     if (($cmajor < $needsmajor) || 
                   7841:         ($cmajor == $needsmajor && $cminor < $needsminor)) {
                   7842:         $needsnewer = 1;
1.557     raeburn  7843:     } elsif ($name) {
                   7844:         if ($valmatch) {
                   7845:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.'::'.$valmatch.':'});
                   7846:         } elsif ($value) { 
                   7847:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.':'.$value.'::'});
                   7848:         }
                   7849:     } elsif ($namematch) {
                   7850:         &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter::::'.$namematch});
1.504     raeburn  7851:     }
                   7852:     return $needsnewer;
                   7853: }
                   7854: 
1.568     raeburn  7855: sub get_permission {
                   7856:     my %permission;
                   7857:     my $allowed = 0;
                   7858:     return (\%permission,$allowed) unless ($env{'request.course.id'});
                   7859:     if ((&Apache::lonnet::allowed('opa',$env{'request.course.id'})) ||
                   7860:         (&Apache::lonnet::allowed('opa',$env{'request.course.id'}.'/'.
                   7861:                   $env{'request.course.sec'}))) {
                   7862:         %permission= (
                   7863:                        'edit'               => 1,
                   7864:                        'set'                => 1,
                   7865:                        'setoverview'        => 1,
                   7866:                        'addmetadata'        => 1,
                   7867:                        'ordermetadata'      => 1,
                   7868:                        'setrestrictmeta'    => 1,
                   7869:                        'newoverview'        => 1,
                   7870:                        'setdefaults'        => 1,
                   7871:                        'settable'           => 1,
                   7872:                        'parameterchangelog' => 1,
                   7873:                        'cleanparameters'    => 1,
                   7874:                        'dateshift1'         => 1,
                   7875:                        'dateshift2'         => 1,
                   7876:                        'helper'             => 1,
                   7877:          );
                   7878:     } elsif ((&Apache::lonnet::allowed('vpa',$env{'request.course.id'})) ||
                   7879:              (&Apache::lonnet::allowed('vpa',$env{'request.course.id'}.'/'.
                   7880:                   $env{'request.course.sec'}))) {
                   7881:         %permission = (
                   7882:                        'set'                => 1,
                   7883:                        'settable'           => 1,
                   7884:                        'newoverview'        => 1,
                   7885:                        'setoverview'        => 1,
                   7886:                        'parameterchangelog' => 1,
                   7887:                       );
                   7888:     }
                   7889:     foreach my $perm (values(%permission)) {
                   7890:         if ($perm) { $allowed=1; last; }
                   7891:     }
                   7892:     return (\%permission,$allowed);
                   7893: }
                   7894: 
1.560     damieng  7895: ##################################################
                   7896: # HANDLER
                   7897: ##################################################
                   7898: 
                   7899: # Main handler for lonparmset.
                   7900: # Sub called based on request parameters action and command:
                   7901: # no command or action: print_main_menu
                   7902: # command 'set': assessparms (direct access to table mode for a resource)
                   7903: #                (this can also be accessed simply with the symb parameter)
                   7904: # action 'setoverview': overview (display all existing parameter settings)
                   7905: # action 'addmetadata': addmetafield (called to add a portfolio metadata field)
                   7906: # action 'ordermetadata': order_meta_fields (called to order portfolio metadata fields)
                   7907: # action 'setrestrictmeta': setrestrictmeta (display or save portfolio metadata)
                   7908: # action 'newoverview': newoverview (overview mode)
                   7909: # action 'setdefaults': defaultsetter (UI to change parameter setting default actions)
                   7910: # action 'settable': assessparms (table mode)
                   7911: # action 'parameterchangelog': parm_change_log (display log for parameter changes,
                   7912: #                              blog postings, user notification changes)
                   7913: # action 'cleanparameters': clean_parameters (unused)
                   7914: # action 'dateshift1': date_shift_one (overview mode, shift all dates)
                   7915: # action 'dateshift2': date_shift_two (overview mode, shift all dates)
1.30      www      7916: sub handler {
1.43      albertel 7917:     my $r=shift;
1.30      www      7918: 
1.376     albertel 7919:     &reset_caches();
                   7920: 
1.414     droeschl 7921:     &Apache::loncommon::content_type($r,'text/html');
                   7922:     $r->send_http_header;
                   7923:     return OK if $r->header_only;
                   7924: 
1.193     albertel 7925:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.473     amueller 7926:                         ['action','state',
1.205     www      7927:                                              'pres_marker',
                   7928:                                              'pres_value',
1.206     www      7929:                                              'pres_type',
1.506     www      7930:                                              'filter','part',
1.390     www      7931:                                              'udom','uname','symb','serial','timebase']);
1.131     www      7932: 
1.83      bowersj2 7933: 
1.193     albertel 7934:     &Apache::lonhtmlcommon::clear_breadcrumbs();
1.194     albertel 7935:     &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
1.507     www      7936:                         text=>"Content and Problem Settings",
1.473     amueller 7937:                         faq=>10,
                   7938:                         bug=>'Instructor Interface',
1.442     droeschl 7939:                                             help =>
                   7940:                                             'Parameter_Manager,Course_Environment,Parameter_Helper,Parameter_Overview,Table_Mode'});
1.203     www      7941: 
1.30      www      7942: # ----------------------------------------------------- Needs to be in a course
1.568     raeburn  7943:     my ($parm_permission,$allowed) = &get_permission();
1.355     albertel 7944:     my $exists = &check_for_course_info();
                   7945: 
1.568     raeburn  7946:     if ($env{'request.course.id'} && $allowed && $exists) {
1.193     albertel 7947:         #
                   7948:         # Main switch on form.action and form.state, as appropriate
                   7949:         #
                   7950:         # Check first if coming from someone else headed directly for
                   7951:         #  the table mode
1.568     raeburn  7952:         if (($parm_permission->{'set'}) && 
                   7953:             ((($env{'form.command'} eq 'set') && ($env{'form.url'})
                   7954:                 && (!$env{'form.dis'})) || ($env{'form.symb'}))) {
                   7955:             &assessparms($r,$parm_permission);
1.193     albertel 7956:         } elsif (! exists($env{'form.action'})) {
                   7957:             &print_main_menu($r,$parm_permission);
1.568     raeburn  7958:         } elsif (!$parm_permission->{$env{'form.action'}}) {
                   7959:             &print_main_menu($r,$parm_permission);
1.414     droeschl 7960:         } elsif ($env{'form.action'} eq 'setoverview') {
1.568     raeburn  7961:             &overview($r,$parm_permission);
1.560     damieng  7962:         } elsif ($env{'form.action'} eq 'addmetadata') {
                   7963:             &addmetafield($r);
                   7964:         } elsif ($env{'form.action'} eq 'ordermetadata') {
                   7965:             &order_meta_fields($r);
1.414     droeschl 7966:         } elsif ($env{'form.action'} eq 'setrestrictmeta') {
1.560     damieng  7967:             &setrestrictmeta($r);
1.414     droeschl 7968:         } elsif ($env{'form.action'} eq 'newoverview') {
1.568     raeburn  7969:             &newoverview($r,$parm_permission);
1.414     droeschl 7970:         } elsif ($env{'form.action'} eq 'setdefaults') {
1.560     damieng  7971:             &defaultsetter($r);
                   7972:         } elsif ($env{'form.action'} eq 'settable') {
1.568     raeburn  7973:             &assessparms($r,$parm_permission);
1.414     droeschl 7974:         } elsif ($env{'form.action'} eq 'parameterchangelog') {
1.568     raeburn  7975:             &parm_change_log($r,$parm_permission);
1.414     droeschl 7976:         } elsif ($env{'form.action'} eq 'cleanparameters') {
1.560     damieng  7977:             &clean_parameters($r);
1.414     droeschl 7978:         } elsif ($env{'form.action'} eq 'dateshift1') {
1.390     www      7979:             &date_shift_one($r);
1.414     droeschl 7980:         } elsif ($env{'form.action'} eq 'dateshift2') {
1.390     www      7981:             &date_shift_two($r);
1.446     bisitz   7982:         }
1.43      albertel 7983:     } else {
1.1       www      7984: # ----------------------------- Not in a course, or not allowed to modify parms
1.560     damieng  7985:         if ($exists) {
                   7986:             $env{'user.error.msg'}=
                   7987:             "/adm/parmset:opa:0:0:Cannot modify assessment parameters";
                   7988:         } else {
                   7989:             $env{'user.error.msg'}=
                   7990:             "/adm/parmset::0:1:Course environment gone, reinitialize the course";
                   7991:         }
                   7992:         return HTTP_NOT_ACCEPTABLE;
1.43      albertel 7993:     }
1.376     albertel 7994:     &reset_caches();
                   7995: 
1.43      albertel 7996:     return OK;
1.1       www      7997: }
                   7998: 
                   7999: 1;
                   8000: __END__
                   8001: 
                   8002: 

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