# The LearningOnline Network
# Feedback
#
# $Id: lonfeedback.pm,v 1.145 2004/12/09 21:58:29 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
###
package Apache::lonfeedback;
use strict;
use Apache::Constants qw(:common);
use Apache::lonmsg();
use Apache::loncommon();
use Apache::lontexconvert();
use Apache::lonlocal; # must not have ()
use Apache::lonhtmlcommon();
use Apache::lonnavmaps;
use Apache::lonenc();
use HTML::LCParser();
use Apache::lonspeller();
use Cwd;
sub discussion_open {
my ($status,$symb)=@_;
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);
if (defined($close) && $close ne '' && $close < time) {
return 0;
}
return 1;
}
sub discussion_visible {
my ($status)=@_;
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; }
}
}
return 1;
}
sub list_discussion {
my ($mode,$status,$ressymb)=@_;
my $outputtarget=$ENV{'form.grade_target'};
if (defined($ENV{'form.export'})) {
if($ENV{'form.export'}) {
$outputtarget = 'export';
}
}
if (not &discussion_visible($status)) { return ''; }
my @bgcols = ("#cccccc","#eeeeee");
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'};
}
$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)$/));
my %usernamesort = ();
my %namesort =();
my %subjectsort = ();
# Get discussion display settings for this discussion
my $lastkey = $ressymb.'_lastread';
my $showkey = $ressymb.'_showonlyunread';
my $markkey = $ressymb.'_showonlyunmark',
my $visitkey = $ressymb.'_visit';
my $ondispkey = $ressymb.'_markondisp';
my $userpickkey = $ressymb.'_userpick';
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 %discinfo = ();
my $showonlyunread = 0;
my $showunmark = 0;
my $markondisp = 0;
my $prevread = 0;
my $previous = 0;
my $visit = 0;
my $newpostsflag = 0;
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'};
if ($previous > 0) {
$prevread = $previous;
} elsif (defined($dischash{$lastkey})) {
unless ($dischash{$lastkey} eq '') {
$prevread = $dischash{$lastkey};
}
}
# 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/:/,$_;
if ($role =~ /^cr/) {
$role = 'cr';
}
my ($end,$start) = split/:/,$roleshash{$_};
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;
}
}
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 $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;
}
}
# Get discussion display default settings for user
if ($ENV{'environment.discdisplay'} eq 'unread') {
$showonlyunread = 1;
}
if ($ENV{'environment.discmarkread'} eq 'ondisp') {
$markondisp = 1;
}
# Override user's default if user specified display setting for this discussion
if (defined($dischash{$ondispkey})) {
unless ($dischash{$ondispkey} eq '') {
$markondisp = $dischash{$ondispkey};
}
}
if ($markondisp) {
$discinfo{$lastkey} = time;
}
if (defined($dischash{$showkey})) {
unless ($dischash{$showkey} eq '') {
$showonlyunread = $dischash{$showkey};
}
}
if (defined($dischash{$markkey})) {
unless ($dischash{$markkey} eq '') {
$showunmark = $dischash{$markkey};
}
}
if (defined($dischash{$visitkey})) {
unless ($dischash{$visitkey} eq '') {
$visit = $dischash{$visitkey};
}
}
$visit ++;
my $seeid=&Apache::lonnet::allowed('rin',$crs);
my @discussionitems=();
my %shown = ();
my @posteridentity=();
my $current=0;
my $visible=0;
my @depth=();
my @replies = ();
my %alldiscussion=();
my %imsitems=();
my %imsfiles=();
my %notshown = ();
my %newitem = ();
my $maxdepth=0;
my $target='';
unless ($ENV{'browser.interface'} eq 'textual' ||
$ENV{'environment.remote'} eq 'off' ) {
$target='target="LONcom"';
}
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);
my $discussion='';
my $manifestfile;
my $manifestok=0;
my $tempexport;
my $imsresources;
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',
'allposts' => 'All posts',
'unread' => 'New posts only',
'unmark' => 'Unread only',
'ondisp' => 'Once displayed',
'onmark' => 'Once marked not NEW',
'toggoff' => 'Off',
'toggon' => 'On',
'disa' => 'Posts to be displayed',
'npce' => 'Posts cease to be marked "NEW"',
'epcb' => 'Each post can be toggled read/unread',
'chgt' => 'Change',
'disp' => 'Display',
'nolo' => 'Not new',
'togg' => 'Toggle read/unread',
);
my $currdisp = $lt{'allposts'};
my $currmark = $lt{'onmark'};
my $currtogg = $lt{'toggoff'};
my $dispchange = $lt{'unread'};
my $markchange = $lt{'ondisp'};
my $toggchange = $lt{'toggon'};
my $chglink = '/adm/feedback?modifydisp='.$ressymb;
my $displinkA = 'onlyunread';
my $displinkB = 'onlyunmark';
my $marklink = 'markondisp';
my $togglink = 'toggon';
if ($markondisp) {
$currmark = $lt{'ondisp'};
$markchange = $lt{'onmark'};
$marklink = 'markonread';
}
if ($showonlyunread) {
$currdisp = $lt{'unread'};
$dispchange = $lt{'allposts'};
$displinkA = 'allposts';
}
if ($showunmark) {
$currdisp = $lt{'unmark'};
$dispchange = $lt{'unmark'};
$displinkA='allposts';
$displinkB='onlyunread';
$showonlyunread = 0;
}
if ($dischash{$toggkey}) {
$currtogg = $lt{'toggon'};
$toggchange = $lt{'toggoff'};
$togglink = 'toggoff';
}
$chglink .= '&changes='.$displinkA.'_'.$displinkB.'_'.$marklink.'_'.$togglink;
if ($newpostsflag) {
$chglink .= '&previous='.$prevread;
}
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'.
'\noindent\textbf{'.$lt{'disa'}.'}: \textit{'.$currdisp.'}\vskip 0 mm'.
'\noindent\textbf{'.$lt{'npce'}.'}: \textit{'.$currmark.'}';
} elsif ($outputtarget eq 'export') {
# Create temporary directory if this is an export
my $now = time;
$tempexport = $Apache::lonnet::perlvar{'lonDaemons'}.'/tmp/ims_exports';
if (!-e $tempexport) {
mkdir($tempexport,0700);
}
$tempexport .= '/'.$now;
if (!-e $tempexport) {
mkdir($tempexport,0700);
}
$tempexport .= '/'.$ENV{'user.domain'}.'_'.$ENV{'user.name'};
if (!-e $tempexport) {
mkdir($tempexport,0700);
}
# open manifest file
my $manifest = '/imsmanifest.xml';
my $manifestfilename = $tempexport.$manifest;
if ($manifestfile = Apache::File->new('>'.$manifestfilename)) {
$manifestok=1;
print $manifestfile qq|
Discussion for $ressymb\n|;
} else {
$discussion .= 'An error occurred opening the manifest file. ';
}
} else {
my $colspan=$maxdepth+1;
$discussion.= qq|
|;
$discussion.='