--- loncom/interface/lonhelper.pm 2011/10/17 12:41:30 1.183 +++ loncom/interface/lonhelper.pm 2015/08/28 22:44:59 1.197 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # .helper XML handler to implement the LON-CAPA helper # -# $Id: lonhelper.pm,v 1.183 2011/10/17 12:41:30 raeburn Exp $ +# $Id: lonhelper.pm,v 1.197 2015/08/28 22:44:59 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -64,9 +64,11 @@ messages, resource selections, or date q The helper tag is required to have one attribute, "title", which is the name of the helper itself, such as "Parameter helper". The helper tag may optionally -have a "requiredpriv" attribute, specifying the priviledge a user must have +have a "requiredpriv" attribute, specifying the privilege a user must have to use the helper, or get denied access. See loncom/auth/rolesplain.tab for -useful privs. Default is full access, which is often wrong! +useful privs. You may add the modifier &S at the end of the three letter priv +if you want to grant access to users for whom the corresponding privilege is +section-specific. The default is full access, which is often wrong! =head2 State tags @@ -261,7 +263,7 @@ sub real_handler { my $uri = shift; if (!defined($uri)) { $uri = $r->uri(); } $env{'request.uri'} = $uri; - my $filename = '/home/httpd/html' . $uri; + my $filename = $r->dir_config('lonDocRoot').$uri; my $fh = Apache::File->new($filename); my $file; read $fh, $file, 100000000; @@ -283,7 +285,8 @@ sub real_handler { my $allowed = $helper->allowedCheck(); if (!$allowed) { - $env{'user.error.msg'} = $env{'request.uri'}.':'.$helper->{REQUIRED_PRIV}. + my ($priv,$modifier) = split(/\&/,$helper->{REQUIRED_PRIV}); + $env{'user.error.msg'} = $env{'request.uri'}.':'.$priv. ":0:0:Permission denied to access this helper."; return HTTP_NOT_ACCEPTABLE; } @@ -508,8 +511,13 @@ sub allowedCheck { if (!defined($self->{REQUIRED_PRIV})) { return 1; } - - return Apache::lonnet::allowed($self->{REQUIRED_PRIV}, $env{'request.course.id'}); + my ($priv,$modifier) = split(/\&/,$self->{REQUIRED_PRIV}); + my $allowed = &Apache::lonnet::allowed($priv,$env{'request.course.id'}); + if ((!$allowed) && ($modifier eq 'S') && ($env{'request.course.sec'} ne '')) { + $allowed = &Apache::lonnet::allowed($priv,$env{'request.course.id'}.'/'. + $env{'request.course.sec'}); + } + return $allowed; } sub changeState { @@ -651,7 +659,7 @@ sub display { $result .= $buttons; - #foreach my $key (keys %{$self->{VARS}}) { + #foreach my $key (keys(%{$self->{VARS}})) { # $result .= "|$key| -> " . $self->{VARS}->{$key} . "
"; #} @@ -1913,7 +1921,13 @@ CHECK if ($anytime) { $result.=' checked="checked" ' } - $result.="name='${var}anytime'/>".&mt('Any time').'' + my $anytimetext = &mt('Any time'); + if (($var eq 'startreserve') || ($var eq 'endreserve')) { + $anytimetext = &mt('Any time before slot starts'); + } elsif (($var eq 'startunique') || ($var eq 'endunique')) { + $anytimetext = &mt('No restriction on uniqueness'); + } + $result.="name='${var}anytime'/>".$anytimetext.'' } return $result; @@ -2390,7 +2404,7 @@ BUTTONS $result .= "$text"; } } - $result .= "Select"; + $result .= ''.&Apache::lonlocal::mt('Select').''; $result .= ""; # Close off the extra row and start a new one. $headings_done = 1; } @@ -2487,9 +2501,9 @@ BUTTONS &HTML::Entities::encode(&$valueFunc($resource),"<>&\"'"); if ($addparts && (scalar(@{$resource->parts}) > 1)) { $col .= ""; } @@ -2534,7 +2548,8 @@ RADIO 'closeAllPages' => $self->{'closeallpages'}, 'suppressEmptySequences' => $self->{'suppressEmptySequences'}, 'include_top_level_map' => $self->{'include_top_level_map'}, - 'iterator_map' => $mapUrl } + 'iterator_map' => $mapUrl, + 'map_no_edit_link' => 1, } ); $result .= $buttons; @@ -2606,6 +2621,12 @@ selection. Defaults to false. If true, only active students and course personnel will be shown. Defaults to false. +=item * B: + +If true, and user's role is in a specific section, only course personnel +will be shown if they also have a section-specific role in the same section. +Defaults to false. + =item * B: If true, the selection of no users is allowed. Defaults to false. @@ -2641,6 +2662,7 @@ sub start_student { $helper->declareVar($paramHash->{'variable'}); $paramHash->{'multichoice'} = $token->[2]{'multichoice'}; $paramHash->{'coursepersonnel'} = $token->[2]{'coursepersonnel'}; + $paramHash->{'sectiononly'} = $token->[2]{'sectiononly'}; $paramHash->{'activeonly'} = $token->[2]{'activeonly'}; if (defined($token->[2]{'nextstate'})) { $paramHash->{NEXTSTATE} = $token->[2]{'nextstate'}; @@ -2682,14 +2704,17 @@ sub render { delete($defaultUsers{''}); } + my $personnel_section; + if ($self->{'sectiononly'}) { + $personnel_section = $env{'request.course.sec'}; + } my ($course_personnel, $current_members, $expired_members, $future_members) = - &Apache::lonselstudent::get_people_in_class($env{'request.course.sec'}); - - + &Apache::lonselstudent::get_people_in_class($env{'request.course.sec'}, + $personnel_section); # Load up the non-students, if necessary @@ -2697,26 +2722,44 @@ sub render { unshift @$current_members, (@$course_personnel); } + my %titles = &Apache::lonlocal::texthash( + 'active' => 'Select Currently Enrolled Students and Active Course Personnel', + 'future' => 'Select Future Enrolled Students', + 'expired' => 'Select Previously Enrolled Students', + ); + + if ($env{'request.course.sec'}) { + if ($self->{'sectiononly'}) { + $titles{'active'} = &mt('Select Currently Enrolled Students and Active Course Personnel in Section: [_1]', + $env{'request.course.sec'}); + } else { + $titles{'active'} = &mt('Select Currently Enrolled Students in Section: [_1], and Active Course Personnel', + $env{'request.course.sec'}); + } + $titles{'future'} = &mt('Select Future Enrolled Students in Section: [_1]', + $env{'request.course.sec'}); + $titles{'expired'} = &mt('Select Previously Enrolled Students in Section: [_1]', + $env{'request.course.sec'}); + } - # Current personel + # Current personnel - $result .= '

'.&mt('Select Currently Enrolled Students and Active Course Personnel').'

'; + $result .= '

'.$titles{'active'}.'

'; $result .= &Apache::lonselstudent::render_student_list( $current_members, "helpform", - "current", + "current", \%defaultUsers, $self->{'multichoice'}, $self->{'variable'}, 1); - # If activeonly is not set then we can also give the expired students: # if (!$self->{'activeonly'} && ((scalar(@$future_members)) > 0)) { # And future. - $result .= '

'.&mt('Select Future Enrolled Students and Future Course Personnel').'

'; + $result .= '

'.$titles{'future'}.'

'; $result .= &Apache::lonselstudent::render_student_list( $future_members, "helpform", @@ -2729,7 +2772,7 @@ sub render { if (!$self->{'activeonly'} && ((scalar(@$expired_members)) > 0)) { # Past - $result .= '

'.&mt('Select Previously Enrolled Students and Inactive Course Personnel').'

'; + $result .= '

'.$titles{'expired'}.'

'; $result .= &Apache::lonselstudent::render_student_list($expired_members, "helpform", "past", @@ -2975,19 +3018,15 @@ BUTTONS # If the subdirectory is in local CSTR space my $metadir; - if ($subdir =~ m|/home/([^/]+)/public_html/(.*)|) { - my ($user,$domain)= - &Apache::loncacc::constructaccess($subdir, - $Apache::lonnet::perlvar{'lonDefDomain'}); - $metadir='/res/'.$domain.'/'.$user.'/'.$2; - ($listref,$listerror) = - &Apache::lonnet::dirlist($subdir,$domain,$user,undef,undef,'/'); - } elsif ($subdir =~ m|^~([^/]+)/(.*)$|) { - $subdir='/home/'.$1.'/public_html/'.$2; + my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'}; + if ($subdir =~ m{^(?:\Q$londocroot\E)*/priv/[^/]+/[^/]+/(.*)$}) { + my $innerpath=$1; + unless ($subdir=~m{^\Q$londocroot\E}) { + $subdir=$londocroot.$subdir; + } my ($user,$domain)= - &Apache::loncacc::constructaccess($subdir, - $Apache::lonnet::perlvar{'lonDefDomain'}); - $metadir='/res/'.$domain.'/'.$user.'/'.$2; + &Apache::lonnet::constructaccess($subdir); + $metadir='/res/'.$domain.'/'.$user.'/'.$innerpath; ($listref,$listerror) = &Apache::lonnet::dirlist($subdir,$domain,$user,undef,undef,'/'); } else { @@ -3094,7 +3133,7 @@ sub fileState { } my $docroot = $Apache::lonnet::perlvar{'lonDocRoot'}; my $subdirpart = $constructionSpaceDir; - $subdirpart =~ s/^\/home\/$uname\/public_html//; + $subdirpart =~ s{^\Q$docroot/priv/$udom/$uname\E}{}; my $resdir = $docroot . '/res/' . $udom . '/' . $uname . $subdirpart; @@ -3144,7 +3183,7 @@ It takes the standard attributes "variab "allowempty" and "nextstate", meaning what they do for most other elements. -also takes a boolean 'onlysections' whcih will restrict this to only +also takes a boolean 'onlysections' which will restrict this to only have sections and not include groups =cut @@ -3182,22 +3221,27 @@ sub start_section { # Populate the CHOICES element my %choices; + my $usersec = $Apache::lonnet::env{'request.course.sec'}; - my $section = Apache::loncoursedata::CL_SECTION(); - my $classlist = Apache::loncoursedata::get_classlist(); - foreach my $user (keys(%$classlist)) { - my $section_name = $classlist->{$user}[$section]; - if (!$section_name) { - $choices{"No section assigned"} = ""; - } else { - $choices{$section_name} = $section_name; + if ($usersec ne '') { + $choices{$usersec} = $usersec; + } else { + my $section = Apache::loncoursedata::CL_SECTION(); + my $classlist = Apache::loncoursedata::get_classlist(); + foreach my $user (keys(%$classlist)) { + my $section_name = $classlist->{$user}[$section]; + if (!$section_name) { + $choices{"No section assigned"} = ""; + } else { + $choices{$section_name} = $section_name; + } + } + + if (exists($choices{"No section assigned"})) { + push(@{$paramHash->{CHOICES}}, + ['No section assigned','No section assigned']); + delete($choices{"No section assigned"}); } - } - - if (exists($choices{"No section assigned"})) { - push(@{$paramHash->{CHOICES}}, - ['No section assigned','No section assigned']); - delete($choices{"No section assigned"}); } for my $section_name (sort {lc($a) cmp lc($b) } (keys(%choices))) { push @{$paramHash->{CHOICES}}, [$section_name, $section_name]; @@ -3233,6 +3277,10 @@ It takes the standard attributes "variab "allowempty" and "nextstate", meaning what they do for most other elements. +also takes a boolean grouponly, which if true, will restrict choice to +groups in which user is a member, unless user has the mdg priv in the course, +in which case all groups will be possible choices. Defaults to false. + =cut no strict; @@ -3262,6 +3310,7 @@ sub start_group { $helper->declareVar($paramHash->{'variable'}); $paramHash->{'multichoice'} = $token->[2]{'multichoice'}; $paramHash->{'allowempty'} = $token->[2]{'allowempty'}; + $paramHash->{'grouponly'} = $token->[2]{'grouponly'}; if (defined($token->[2]{'nextstate'})) { $paramHash->{NEXTSTATE} = $token->[2]{'nextstate'}; } @@ -3269,7 +3318,12 @@ sub start_group { # Populate the CHOICES element my %choices; - my %curr_groups = &Apache::longroup::coursegroups(); + my %curr_groups; + if ((!$paramHash->{'grouponly'}) || (&Apache::lonnet::allowed('mdg',$Apache::lonnet::env{'request.course.id'}))) { + %curr_groups = &Apache::longroup::coursegroups(); + } elsif ($Apache::lonnet::env{'request.course.groups'} ne '') { + map { $curr_groups{$_} = 1; } split(/,/,$Apache::lonnet::env{'request.course.groups'}); + } foreach my $group_name (sort {lc($a) cmp lc($b)} (keys(%curr_groups))) { push(@{$paramHash->{CHOICES}}, [$group_name, $group_name]); } @@ -3631,7 +3685,7 @@ sub render { my @results; # Collect all the results - for my $stateName (keys %{$helper->{STATES}}) { + for my $stateName (keys(%{$helper->{STATES}})) { my $state = $helper->{STATES}->{$stateName}; for my $element (@{$state->{ELEMENTS}}) {