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

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

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