--- loncom/interface/lonfeedback.pm 2005/02/17 08:29:42 1.153
+++ loncom/interface/lonfeedback.pm 2012/03/15 15:02:59 1.342
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Feedback
#
-# $Id: lonfeedback.pm,v 1.153 2005/02/17 08:29:42 albertel Exp $
+# $Id: lonfeedback.pm,v 1.342 2012/03/15 15:02:59 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -35,21 +35,36 @@ use Apache::lonmsg();
use Apache::loncommon();
use Apache::lontexconvert();
use Apache::lonlocal; # must not have ()
+use Apache::lonnet;
use Apache::lonhtmlcommon();
use Apache::lonnavmaps;
use Apache::lonenc();
+use Apache::lonrss();
use HTML::LCParser();
+#use HTML::Tidy::libXML;
use Apache::lonspeller();
+use Apache::longroup;
use Cwd;
+use LONCAPA;
sub discussion_open {
my ($status,$symb)=@_;
+# Advanced roles can always discuss
+ if ($env{'request.role.adv'}) { return 1; }
+# Get discussion closing date
+ my $close=&Apache::lonnet::EXT('resource.0.discussend',$symb);
+# If it is defined and in the future, the instructor wants this discussion to be open
+ if (defined($close) && $close ne '' && $close > time) {
+ return 1;
+ }
+# It was not explicitly open, check if the problem is available.
+# If the problem is not available, close the discussion
if (defined($status) &&
!($status eq 'CAN_ANSWER' || $status eq 'CANNOT_ANSWER'
|| $status eq 'OPEN')) {
return 0;
}
- my $close=&Apache::lonnet::EXT('resource.0.discussend',$symb);
+# The problem is available, but check if the instructor explictly closed discussion
if (defined($close) && $close ne '' && $close < time) {
return 0;
}
@@ -61,17 +76,40 @@ sub discussion_visible {
if (not &discussion_open($status)) {
my $hidden=&Apache::lonnet::EXT('resource.0.discusshide');
if (lc($hidden) eq 'yes' or $hidden eq '' or !defined($hidden)) {
- if (!$ENV{'request.role.adv'}) { return 0; }
+ if (!$env{'request.role.adv'}) { return 0; }
}
}
return 1;
}
+sub discussion_vote_available {
+ my ($status,$symb)=@_;
+ my $canvote=&Apache::lonnet::EXT('resource.0.discussvote',$symb);
+ if ((lc($canvote) eq 'yes') ||
+ ((lc($canvote) eq 'notended') && (&discussion_open($status,$symb)))) {
+ return 1;
+ }
+}
+
+sub get_realsymb {
+ my ($symb) = @_;
+ my $realsymb = $symb;
+ if ($symb=~/^bulletin___/) {
+ my $filename=(&Apache::lonnet::decode_symb($symb))[2];
+ $filename=~s{^adm/wrapper/}{};
+ $realsymb=&Apache::lonnet::symbread($filename);
+ }
+ return $realsymb;
+}
+
sub list_discussion {
- my ($mode,$status,$ressymb,$imsextras)=@_;
- my $outputtarget=$ENV{'form.grade_target'};
- if (defined($ENV{'form.export'})) {
- if($ENV{'form.export'}) {
+ my ($mode,$status,$ressymb,$imsextras,$group)=@_;
+ unless ($ressymb) { $ressymb=&Apache::lonnet::symbread(); }
+ unless ($ressymb) { return ''; }
+ $ressymb=&wrap_symb($ressymb);
+ my $outputtarget=$env{'form.grade_target'};
+ if (defined($env{'form.export'})) {
+ if($env{'form.export'}) {
$outputtarget = 'export';
}
}
@@ -80,23 +118,44 @@ sub list_discussion {
$outputtarget = 'export';
}
}
- if (not &discussion_visible($status)) { return ''; }
- my @bgcols = ("#cccccc","#eeeeee");
+ if (not &discussion_visible($status)) {
+ if ($mode ne 'board') {
+ &Apache::lonenc::check_encrypt(\$ressymb);
+ return '
'.&send_message_link($ressymb)."
";
+ }
+ }
+ if ($group ne '' && $mode eq 'board') {
+ if (&check_group_priv($group,'vgb') ne 'ok') {
+ return '';
+ }
+ }
+
+ my ($blocked,$blocktext) =
+ &Apache::loncommon::blocking_status('boards');
+ if ($blocked) {
+ $blocktext = '
'.$blocktext."";
+ &Apache::lonenc::check_encrypt(\$ressymb);
+ if ($mode ne 'board') {
+ $blocktext.=&send_message_link($ressymb).'
';
+ }else{
+ $blocktext.="";
+ }
+ return $blocktext;
+ }
+
+ my @bgcols = ("LC_disc_old_item","LC_disc_new_item");
my $discussiononly=0;
if ($mode eq 'board') { $discussiononly=1; }
- unless ($ENV{'request.course.id'}) { return ''; }
- my $crs='/'.$ENV{'request.course.id'};
- my $cid=$ENV{'request.course.id'};
- if ($ENV{'request.course.sec'}) {
- $crs.='_'.$ENV{'request.course.sec'};
+ unless ($env{'request.course.id'}) { return ''; }
+ my $crs='/'.$env{'request.course.id'};
+ my $cid=$env{'request.course.id'};
+ if ($env{'request.course.sec'}) {
+ $crs.='_'.$env{'request.course.sec'};
}
$crs=~s/\_/\//g;
- unless ($ressymb) { $ressymb=&Apache::lonnet::symbread(); }
- unless ($ressymb) { return ''; }
- $ressymb=&wrap_symb($ressymb);
my $encsymb=&Apache::lonenc::check_encrypt($ressymb);
my $viewgrades=(&Apache::lonnet::allowed('vgr',$crs)
- && ($ressymb=~/\.(problem|exam|quiz|assess|survey|form)$/));
+ && ($ressymb=~/$LONCAPA::assess_re/));
my %usernamesort = ();
my %namesort =();
@@ -112,7 +171,7 @@ sub list_discussion {
my $toggkey = $ressymb.'_readtoggle';
my $readkey = $ressymb.'_read';
$ressymb=$encsymb;
- my %dischash = &Apache::lonnet::get('nohist_'.$ENV{'request.course.id'}.'_discuss',[$lastkey,$showkey,$markkey,$visitkey,$ondispkey,$userpickkey,$toggkey,$readkey],$ENV{'user.domain'},$ENV{'user.name'});
+ my %dischash = &Apache::lonnet::get('nohist_'.$cid.'_discuss',[$lastkey,$showkey,$markkey,$visitkey,$ondispkey,$userpickkey,$toggkey,$readkey],$env{'user.domain'},$env{'user.name'});
my %discinfo = ();
my $showonlyunread = 0;
my $showunmark = 0;
@@ -121,26 +180,18 @@ sub list_discussion {
my $previous = 0;
my $visit = 0;
my $newpostsflag = 0;
- my @posters = split/\&/,$dischash{$userpickkey};
+ my @posters = split(/\&/,$dischash{$userpickkey});
# Retain identification of "NEW" posts identified in last display, if continuing 'previous' browsing of posts.
- &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['previous','sortposts','rolefilter','statusfilter','sectionpick','totposters']);
- my $sortposts = $ENV{'form.sortposts'};
- my $statusfilter = $ENV{'form.statusfilter'};
- my @sectionpick = ();
- if ($ENV{'form.sectionpick'} =~ /,/) {
- @sectionpick = split/,/,$ENV{'form.sectionpick'};
- } else {
- $sectionpick[0] = $ENV{'form.sectionpick'};
- }
- my @rolefilter = ();
- if ($ENV{'form.rolefilter'} =~ /,/) {
- @rolefilter = split/,/,$ENV{'form.rolefilter'};
- } else {
- $rolefilter[0] = $ENV{'form.rolefilter'};
- }
- my $totposters = $ENV{'form.totposters'};
- $previous = $ENV{'form.previous'};
+ &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['previous','sortposts','rolefilter','statusfilter','sectionpick','grouppick','totposters']);
+ my $sortposts = $env{'form.sortposts'};
+ my $statusfilter = $env{'form.statusfilter'};
+ my @sectionpick = split(/,/,$env{'form.sectionpick'});
+ my @grouppick = split(/,/,$env{'form.grouppick'});
+ my @rolefilter = split(/,/,$env{'form.rolefilter'});
+
+ my $totposters = $env{'form.totposters'};
+ $previous = $env{'form.previous'};
if ($previous > 0) {
$prevread = $previous;
} elsif (defined($dischash{$lastkey})) {
@@ -149,44 +200,50 @@ sub list_discussion {
}
}
+ my $cdom = $env{'course.'.$cid.'.domain'};
+ my $cnum = $env{'course.'.$cid.'.num'};
+ my $crstype = &Apache::loncommon::course_type();
+
# Get information about students and non-students in course for filtering display of posts
my %roleshash = ();
my %roleinfo = ();
- if ($ENV{'form.rolefilter'}) {
- %roleshash = &Apache::lonnet::dump('nohist_userroles',$ENV{'course.'.$ENV{'request.course.id'}.'.domain'},$ENV{'course.'.$ENV{'request.course.id'}.'.num'});
- foreach (keys %roleshash) {
- my ($role,$uname,$udom,$sec) = split/:/,$_;
+ my ($classgroups,$studentgroups);
+ if ($env{'form.rolefilter'}) {
+ %roleshash = &Apache::lonnet::dump('nohist_userroles',$cdom,$cnum);
+ foreach my $rolekey (keys(%roleshash)) {
+ my ($role,$uname,$udom,$sec) = split(/:/,$rolekey);
if ($role =~ /^cr/) {
$role = 'cr';
}
- my ($end,$start) = split/:/,$roleshash{$_};
+ my ($end,$start) = split(/:/,$roleshash{$rolekey});
my $now = time;
my $status = 'Active';
if (($now < $start) || ($end > 0 && $now > $end)) {
$status = 'Expired';
}
if ($uname && $udom) {
- push @{$roleinfo{$uname.':'.$udom}}, $role.':'.$sec.':'.$status;
+ push(@{$roleinfo{$uname.':'.$udom}}, $role.':'.$sec.':'.$status);
}
}
- my ($classlist) = &Apache::loncoursedata::get_classlist(
- $ENV{'request.course.id'},
- $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
- $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
+ my ($classlist,$keylist) =
+ &Apache::loncoursedata::get_classlist($cdom,$cnum);
my $sec_index = &Apache::loncoursedata::CL_SECTION();
my $status_index = &Apache::loncoursedata::CL_STATUS();
while (my ($student,$data) = each %$classlist) {
my ($section,$status) = ($data->[$sec_index],
$data->[$status_index]);
- push @{$roleinfo{$student}}, 'st:'.$section.':'.$status;
+ push(@{$roleinfo{$student}}, 'st:'.$section.':'.$status);
}
+ ($classgroups,$studentgroups) =
+ &Apache::loncoursedata::get_group_memberships($classlist,$keylist,
+ $cdom,$cnum);
}
# Get discussion display default settings for user
- if ($ENV{'environment.discdisplay'} eq 'unread') {
+ if ($env{'environment.discdisplay'} eq 'unread') {
$showonlyunread = 1;
}
- if ($ENV{'environment.discmarkread'} eq 'ondisp') {
+ if ($env{'environment.discmarkread'} eq 'ondisp') {
$markondisp = 1;
}
@@ -219,7 +276,20 @@ sub list_discussion {
}
$visit ++;
- my $seeid=&Apache::lonnet::allowed('rin',$crs);
+ my $seeid;
+ if (($group ne '') && ($mode eq 'board') &&
+ ($ressymb =~ m|^bulletin___\d+___adm/wrapper/adm/\Q$cdom\E/\Q$cnum\E/\d+/bulletinboard$|)) {
+ if (&check_group_priv($group,'dgp') eq 'ok') {
+ $seeid = 1;
+ }
+ } else {
+ $seeid=&Apache::lonnet::allowed('rin',$crs);
+ }
+
+# Is voting on discussions available
+ my $realsymb = &get_realsymb($ressymb);
+ my $canvote = &discussion_vote_available($status,$realsymb);
+
my @discussionitems=();
my %shown = ();
my @posteridentity=();
@@ -234,18 +304,14 @@ sub list_discussion {
my %notshown = ();
my %newitem = ();
my $maxdepth=0;
-
- my $target='';
- unless ($ENV{'browser.interface'} eq 'textual' ||
- $ENV{'environment.remote'} eq 'off' ) {
- $target='target="LONcom"';
- }
+ my %anonhash=();
+ my $anoncnt=0;
my $now = time;
$discinfo{$visitkey} = $visit;
- &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',\%discinfo,$ENV{'user.domain'},$ENV{'user.name'});
- &build_posting_display(\%usernamesort,\%subjectsort,\%namesort,\%notshown,\%newitem,\%dischash,\%shown,\%alldiscussion,\%imsitems,\%imsfiles,\%roleinfo,\@discussionitems,\@replies,\@depth,\@posters,\$maxdepth,\$visible,\$newpostsflag,\$current,$status,$viewgrades,$seeid,$prevread,$sortposts,$encsymb,$target,$readkey,$showunmark,$showonlyunread,$totposters,\@rolefilter,\@sectionpick,$statusfilter,$toggkey,$outputtarget);
+ &Apache::lonnet::put('nohist_'.$cid.'_discuss',\%discinfo,$env{'user.domain'},$env{'user.name'});
+ &build_posting_display(\%usernamesort,\%subjectsort,\%namesort,\%notshown,\%newitem,\%dischash,\%shown,\%alldiscussion,\%imsitems,\%imsfiles,\%roleinfo,\@discussionitems,\@replies,\@depth,\@posters,\$maxdepth,\$visible,\$newpostsflag,\$current,$status,$viewgrades,$seeid,$canvote,$prevread,$sortposts,$encsymb,$readkey,$showunmark,$showonlyunread,$totposters,\@rolefilter,\@sectionpick,\@grouppick,$classgroups,$statusfilter,$toggkey,$outputtarget,\%anonhash,$anoncnt,$group);
my $discussion='';
my $manifestfile;
@@ -255,10 +321,8 @@ sub list_discussion {
my $copyresult;
my $function = &Apache::loncommon::get_users_function();
- my $color = &Apache::loncommon::designparm($function.'.tabbg',
- $ENV{'user.domain'});
my %lt = &Apache::lonlocal::texthash(
- 'cuse' => 'Current discussion settings',
+ 'cuse' => 'My settings for this discussion',
'allposts' => 'All posts',
'unread' => 'New posts only',
'unmark' => 'Unread only',
@@ -273,6 +337,14 @@ sub list_discussion {
'disp' => 'Display',
'nolo' => 'Not new',
'togg' => 'Toggle read/unread',
+ 'aner' => 'An error occurred opening the manifest file.',
+ 'difo' => 'Discussion for',
+ 'aerr' => 'An error occurred opening the export file for posting',
+ 'aysu' => 'Are you sure you want to delete this post?',
+ 'dpwn' => 'Deleted posts will no longer be visible to you and other students',
+ 'bwco' => 'but will continue to be visible to your instructor',
+ 'depo' => 'Deleted posts will no longer be visible to you or anyone else.',
+ 'discussions' => 'DISCUSSIONS'
);
my $currdisp = $lt{'allposts'};
@@ -313,20 +385,20 @@ sub list_discussion {
$togglink = 'toggoff';
}
- $chglink .= '&changes='.$displinkA.'_'.$displinkB.'_'.$marklink.'_'.$togglink;
+ $chglink .= '&changes='.$displinkA.'_'.$displinkB.'_'.$marklink.'_'.$togglink;
if ($newpostsflag) {
- $chglink .= '&previous='.$prevread;
+ $chglink .= '&previous='.$prevread;
}
+ $chglink.=&group_args($group);
if ($visible) {
# Print the discusssion
if ($outputtarget eq 'tex') {
- $discussion.='\vskip 0 mm\noindent\makebox[2 cm][b]{\hrulefill}'.
- '\textbf{DISCUSSIONS}\makebox[2 cm][b]{\hrulefill}'.
- '\vskip 0 mm\noindent\textbf{'.$lt{'cuse'}.'}:\vskip 0 mm'.
+ $discussion.='{\tiny \vskip 0 mm\noindent\makebox[2 cm][b]{\hrulefill}'.
+ '\textbf{'.$lt{'discussions'}.'}\makebox[2 cm][b]{\hrulefill}\vskip 0 mm'.
'\noindent\textbf{'.$lt{'disa'}.'}: \textit{'.$currdisp.'}\vskip 0 mm'.
- '\noindent\textbf{'.$lt{'npce'}.'}: \textit{'.$currmark.'}';
+ '\noindent\textbf{'.$lt{'npce'}.'}: \textit{'.$currmark.'}}';
} elsif ($outputtarget eq 'export') {
# Create temporary directory if this is an export
my $now = time;
@@ -348,7 +420,7 @@ sub list_discussion {
if (!-e $tempexport) {
mkdir($tempexport,0700);
}
- $tempexport .= '/'.$ENV{'user.domain'}.'_'.$ENV{'user.name'};
+ $tempexport .= '/'.$env{'user.domain'}.'_'.$env{'user.name'};
}
if (!-e $tempexport) {
mkdir($tempexport,0700);
@@ -358,81 +430,54 @@ sub list_discussion {
my $manifestfilename = $tempexport.$manifest;
if ($manifestfile = Apache::File->new('>'.$manifestfilename)) {
$manifestok=1;
- print $manifestfile qq|
-
+ print $manifestfile qq|
- Discussion for $ressymb\n|;
+ $lt{'difo'} $ressymb\n|;
} else {
- $discussion .= 'An error occurred opening the manifest file.
';
+ $discussion .= $lt{'aner'}.'
';
}
} else {
my $colspan=$maxdepth+1;
- $discussion.= qq|
-
- |;
- $discussion.='