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

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

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