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

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

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