--- loncom/interface/lonfeedback.pm 2004/08/31 15:54:48 1.99.2.4 +++ loncom/interface/lonfeedback.pm 2004/09/21 20:44:16 1.127 @@ -1,7 +1,7 @@ # The LearningOnline Network # Feedback # -# $Id: lonfeedback.pm,v 1.99.2.4 2004/08/31 15:54:48 albertel Exp $ +# $Id: lonfeedback.pm,v 1.127 2004/09/21 20:44:16 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -36,15 +36,18 @@ use Apache::loncommon(); use Apache::lontexconvert(); use Apache::lonlocal; # must not have () use Apache::lonhtmlcommon(); +use HTML::LCParser(); +use Apache::lonspeller(); +use Cwd; sub discussion_open { - my ($status)=@_; + 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'); + my $close=&Apache::lonnet::EXT('resource.0.discussend',$symb); if (defined($close) && $close ne '' && $close < time) { return 0; } @@ -56,7 +59,7 @@ 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)) { - return 0; + if (!$ENV{'request.role.adv'}) { return 0; } } } return 1; @@ -64,14 +67,19 @@ sub discussion_visible { sub list_discussion { my ($mode,$status,$symb)=@_; - 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'}; } @@ -80,7 +88,9 @@ sub list_discussion { $symb=&Apache::lonnet::symbread(); } unless ($symb) { return ''; } - + my %usernamesort = (); + my %namesort =(); + my %subjectsort = (); # backward compatibility (bulletin boards used to be 'wrapped') my $ressymb=$symb; if ($mode eq 'board') { @@ -92,19 +102,31 @@ sub list_discussion { # 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 %dischash = &Apache::lonnet::get('nohist_'.$ENV{'request.course.id'}.'_discuss',[$lastkey,$showkey,$visitkey,$ondispkey],$ENV{'user.domain'},$ENV{'user.name'}); + my $userpickkey = $ressymb.'_userpick'; + my $toggkey = $ressymb.'_readtoggle'; + my $readkey = $ressymb.'_read'; + + 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']); + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['previous','sortposts','rolefilter','statusfilter','sectionpick','totposters']); + my $sortposts = $ENV{'form.sortposts'}; + my $rolefilter = $ENV{'form.rolefilter'}; + my $statusfilter = $ENV{'form.statusfilter'}; + my $sectionpick = $ENV{'form.sectionpick'}; + my $totposters = $ENV{'form.totposters'}; $previous = $ENV{'form.previous'}; if ($previous > 0) { $prevread = $previous; @@ -114,31 +136,68 @@ sub list_discussion { } } +# Get information about students and non-students in course for filtering display of posts + my %roleshash = (); + my %roleinfo = (); + if ($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 ($end,$start) = split/:/,$roleshash{$_}; + my $now = time; + my $status = 'Active'; + if (($now < $start) || ($end > 0 && $now > $end)) { + $status = 'Expired'; + } + 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 - my %userenv = &Apache::lonnet::get('environment',['discdisplay','discmarkread'],$ENV{'user.domain'},$ENV{'user.name'}); - my $discdisplay=$userenv{'discdisplay'}; - if ($discdisplay eq 'unread') { + if ($ENV{'environment.discdisplay'} eq 'unread') { $showonlyunread = 1; } - my $discmarkread=$userenv{'discmarkread'}; - if ($discmarkread eq 'ondisp') { + if ($ENV{'environment.discmarkread'} eq 'ondisp') { $markondisp = 1; } # Override user's default if user specified display setting for this discussion if (defined($dischash{$ondispkey})) { - $markondisp = $dischash{$ondispkey}; + unless ($dischash{$ondispkey} eq '') { + $markondisp = $dischash{$ondispkey}; + } } if ($markondisp) { $discinfo{$lastkey} = time; } if (defined($dischash{$showkey})) { - $showonlyunread = $dischash{$showkey}; + unless ($dischash{$showkey} eq '') { + $showonlyunread = $dischash{$showkey}; + } + } + + if (defined($dischash{$markkey})) { + unless ($dischash{$markkey} eq '') { + $showunmark = $dischash{$markkey}; + } } if (defined($dischash{$visitkey})) { - $visit = $dischash{$visitkey}; + unless ($dischash{$visitkey} eq '') { + $visit = $dischash{$visitkey}; + } } $visit ++; @@ -146,15 +205,16 @@ sub list_discussion { my $viewgrades=(&Apache::lonnet::allowed('vgr',$crs) && ($symb=~/\.(problem|exam|quiz|assess|survey|form)$/)); my @discussionitems=(); - my %contrib=&Apache::lonnet::restore($ressymb,$ENV{'request.course.id'}, - $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}, - $ENV{'course.'.$ENV{'request.course.id'}.'.num'}); + my %shown = (); + my @posteridentity=(); + + my $current=0; my $visible=0; my @depth=(); - my @original=(); - my @index=(); - my @replies=(); + my @replies = (); my %alldiscussion=(); + my %imsitems=(); + my %imsfiles=(); my %notshown = (); my %newitem = (); my $maxdepth=0; @@ -164,162 +224,19 @@ sub list_discussion { $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'}); - - if ($contrib{'version'}) { - my $oldest = $contrib{'1:timestamp'}; - if ($prevread eq '0') { - $prevread = $oldest-1; - } - for (my $id=1;$id<=$contrib{'version'};$id++) { - my $idx=$id; - my $posttime = $contrib{$idx.':timestamp'}; - if ($prevread <= $posttime) { - $newpostsflag = 1; - } - my $hidden=($contrib{'hidden'}=~/\.$idx\./); - my $deleted=($contrib{'deleted'}=~/\.$idx\./); - my $origindex='0.'; - if (($contrib{$idx.':replyto'}) && ($ENV{'environment.threadeddiscussion'})) { -# this is a follow-up message - $original[$idx]=$original[$contrib{$idx.':replyto'}]; - $depth[$idx]=$depth[$contrib{$idx.':replyto'}]+1; - $origindex=$index[$contrib{$idx.':replyto'}]; - if ($depth[$idx]>$maxdepth) { $maxdepth=$depth[$idx]; } - } else { -# this is an original message - $original[$idx]=0; - $depth[$idx]=0; - } - if ($replies[$depth[$idx]]) { - $replies[$depth[$idx]]++; - } else { - $replies[$depth[$idx]]=1; - } - unless ((($hidden) && (!$seeid)) || ($deleted)) { - $visible++; - my $message=$contrib{$idx.':message'}; - $message=~s/\n/\
/g; - $message=&Apache::lontexconvert::msgtexconverted($message); - my $subject=$contrib{$idx.':subject'}; - if (defined($subject)) { - $subject=~s/\n/\
/g; - $subject=&Apache::lontexconvert::msgtexconverted($subject); - } - if ($contrib{$idx.':attachmenturl'}) { - my ($fname) - =($contrib{$idx.':attachmenturl'}=~m|/([^/]+)$|); - &Apache::lonnet::allowuploaded('/adm/feedback', - $contrib{$idx.':attachmenturl'}); - $message.='

'.&mt('Attachment'). - ': '. - $fname.'

'; - } - if ($message) { - if ($hidden) { - $message=''.$message.''; - } - my $screenname=&Apache::loncommon::screenname( - $contrib{$idx.':sendername'}, - $contrib{$idx.':senderdomain'}); - my $plainname=&Apache::loncommon::nickname( - $contrib{$idx.':sendername'}, - $contrib{$idx.':senderdomain'}); - - my $sender=&mt('Anonymous'); - if ((!$contrib{$idx.':anonymous'}) || ($seeid)) { - $sender=&Apache::loncommon::aboutmewrapper( - $plainname, - $contrib{$idx.':sendername'}, - $contrib{$idx.':senderdomain'}).' ('. - $contrib{$idx.':sendername'}.' at '. - $contrib{$idx.':senderdomain'}.')'; - if ($contrib{$idx.':anonymous'}) { - $sender.=' ['.&mt('anonymous').'] '. - $screenname; - } - if ($seeid) { - if ($hidden) { - $sender.=' '.&mt('Make Visible').''; - } else { - $sender.=' '.&mt('Hide').''; - } - $sender.=' '.&mt('Delete').''; - } - } else { - if ($screenname) { - $sender=''.$screenname.''; - } - } - if (&discussion_open($status) && - &Apache::lonnet::allowed('pch', - $ENV{'request.course.id'}. - ($ENV{'request.course.sec'}?'/'.$ENV{'request.course.sec'}:''))) { - $sender.=' '.&mt('Reply').''; - } - my $vgrlink; - if ($viewgrades) { - $vgrlink=&Apache::loncommon::submlink('Submissions', - $contrib{$idx.':sendername'},$contrib{$idx.':senderdomain'},$symb); - } -#figure out at what position this needs to print - my $thisindex=$idx; - if ($ENV{'environment.threadeddiscussion'}) { - $thisindex=$origindex.substr('00'.$replies[$depth[$idx]],-2,2); - } - $alldiscussion{$thisindex}=$idx; - $index[$idx]=$thisindex; - my $spansize = 2; - if ($showonlyunread && $prevread > $posttime) { - $notshown{$idx} = 1; - } else { - if ($prevread > 0 && $prevread <= $posttime) { - $newitem{$idx} = 1; - $discussionitems[$idx] .= ' -

- '; - } else { - $newitem{$idx} = 0; - $discussionitems[$idx] .= ' -

NEW
- '; - } - $discussionitems[$idx] .= ''. - '
   '. - ''.$subject.'  '. - $sender.' '.$vgrlink.' ('. - localtime($posttime).')

'.$message.'

'; - } - } - } - } - } + &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,$ressymb,$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', @@ -328,22 +245,31 @@ sub list_discussion { 'cuse' => 'Current discussion settings', 'allposts' => 'All posts', 'unread' => 'New posts only', + 'unmark' => 'Unread only', 'ondisp' => 'Once displayed', - 'onmark' => 'Once marked read', + '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 $displink = 'onlyunread'; + my $displinkA = 'onlyunread'; + my $displinkB = 'onlyunmark'; my $marklink = 'markondisp'; + my $togglink = 'toggon'; if ($markondisp) { $currmark = $lt{'ondisp'}; @@ -354,10 +280,24 @@ sub list_discussion { if ($showonlyunread) { $currdisp = $lt{'unread'}; $dispchange = $lt{'allposts'}; - $displink = '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='.$displink.'_'.$marklink; + $chglink .= '&changes='.$displinkA.'_'.$displinkB.'_'.$marklink.'_'.$togglink; if ($newpostsflag) { $chglink .= '&previous='.$prevread; @@ -365,9 +305,61 @@ sub list_discussion { if ($visible) { # Print the discusssion - if ($outputtarget ne 'tex') { + 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.=''; + $discussion.= qq| + + |; + $discussion.='
'; $discussion .=''; - } else { - $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.'}'; - } - my $numhidden = keys %notshown; - if ($numhidden > 0) { - my $colspan = $maxdepth+1; - $discussion.="\n".''; } - $discussion .= '">'.&mt('Show all posts').' '.&mt('to display').' '. - $numhidden.' '.&mt('previously viewed posts'). - '
'; - } - foreach (sort { $a <=> $b } keys %alldiscussion) { - unless ($notshown{$alldiscussion{$_}} eq '1') { - if ($outputtarget ne 'tex') { + } + +# Choose sort mechanism + my @showposts = (); + if ($sortposts eq 'descdate') { + @showposts = (sort { $b <=> $a } keys %alldiscussion); + } elsif ($sortposts eq 'thread') { + @showposts = (sort { $a <=> $b } keys %alldiscussion); + } elsif ($sortposts eq 'subject') { + foreach (sort keys %subjectsort) { + push @showposts, @{$subjectsort{$_}}; + } + } elsif ($sortposts eq 'username') { + foreach my $domain (sort keys %usernamesort) { + foreach (sort keys %{$usernamesort{$domain}}) { + push @showposts, @{$usernamesort{$domain}{$_}}; + } + } + } elsif ($sortposts eq 'lastfirst') { + foreach my $last (sort keys %namesort) { + foreach (sort keys %{$namesort{$last}}) { + push @showposts, @{$namesort{$last}{$_}}; + } + } + } else { + $sortposts = 'ascdate'; + @showposts = (sort { $a <=> $b } keys %alldiscussion); + } + my $currdepth = 0; + my $firstidx = $alldiscussion{$showposts[0]}; + foreach (@showposts) { + unless (($sortposts eq 'thread') || ($sortposts eq 'ascdate' && $ENV{'environment.threadeddiscussion'}) || ($outputtarget eq 'export')) { + $alldiscussion{$_} = $_; + } + unless ( ($notshown{$alldiscussion{$_}} eq '1') || ($shown{$alldiscussion{$_}} == 0) ) { + if ($outputtarget ne 'tex' && $outputtarget ne 'export') { $discussion.="\n"; - } else { - $discussion.='\vskip 0 mm\noindent\makebox[2 cm][b]{\hrulefill}'; } my $thisdepth=$depth[$alldiscussion{$_}]; - if ($outputtarget ne 'tex') { + if ($outputtarget ne 'tex' && $outputtarget ne 'export') { for (1..$thisdepth) { $discussion.=''; } } my $colspan=$maxdepth-$thisdepth+1; - if ($outputtarget ne 'tex') { - $discussion.=''; - } else { + if ($outputtarget eq 'tex') { #cleanup block $discussionitems[$alldiscussion{$_}]=~s/]*)>/
'. ''; if ($visible>2) { @@ -381,11 +373,23 @@ sub list_discussion { if ($newpostsflag) { $discussion .= '&previous='.$prevread; } - $discussion .='">'.&mt('Chronological View').'  '; - } + $discussion .='">'.&mt('Chronological View').'   + '.&mt('Sorting/Filtering options').'  '; + } else { + $discussion .= ''; if ($newpostsflag) { if (!$markondisp) { - $discussion .=''; } @@ -393,44 +397,70 @@ sub list_discussion { $discussion .= ''; } $discussion .= '
'; + } + $discussion .=''.&mt('Export').'?  '.&mt('Mark new posts as read').'  '; + $discussion .=''.&mt('Mark NEW posts no longer new').'  '; } else { $discussion .= '  
'. + + my $numhidden = keys %notshown; + if ($numhidden > 0) { + my $colspan = $maxdepth+1; + $discussion.="\n".'
'. ''.&mt('Show all posts').' '.&mt('to display').' '. + $numhidden.' '; + if ($showunmark) { + $discussion .= &mt('posts previously marked read'); + } else { + $discussion .= &mt('previously viewed posts'); + } + $discussion .= '
   '. - $discussionitems[$alldiscussion{$_}]. - '
/; $discussionitems[$alldiscussion{$_}]=~s/]*)>]*)>/'; + } } } - if ($outputtarget ne 'tex') { + unless ($outputtarget eq 'tex' || $outputtarget eq 'export') { my $colspan=$maxdepth+1; - $discussion .= < +END + if ($dischash{$toggkey}) { + my $storebutton = &mt('Store read/unread changes'); + $discussion.=''; + } + $discussion .= (<
/; @@ -439,21 +469,52 @@ sub list_discussion { $threadinsert='
Reply: '.$thisdepth.''; } $discussionitems[$alldiscussion{$_}]=~s/<\/td>]*)>/$threadinsert<\/td>
/; - $discussionitems[$alldiscussion{$_}]=~s/]+)>(Hide|Delete|Reply|Submissions)<\/a>//g; + $discussionitems[$alldiscussion{$_}]=~s/]+)>(Edit|Hide|Delete|Reply|Submissions)<\/a>//g; $discussionitems[$alldiscussion{$_}]=~s/(|<\/b>|<\/a>|]+)>)//g; - - #FIXME xmlparse can't be safely called from inside xmlparse - # due to the global variables that are use, the safe - # space etc. I expect this has unforseen issues that - # need resolving. - - $discussion.=&Apache::lonxml::xmlparse('','tex',$discussionitems[$alldiscussion{$_}]); - } + + $discussionitems[$alldiscussion{$_}]='\vskip 0 mm\noindent\makebox[2 cm][b]{\hrulefill}'.$discussionitems[$alldiscussion{$_}]; + $discussion.=$discussionitems[$alldiscussion{$_}]; + } elsif ($outputtarget eq 'export') { + my $postfilename = $alldiscussion{$_}.'-'.$imsitems{$alldiscussion{$_}}{'timestamp'}.'.html'; + if ($manifestok) { + if (($depth[$alldiscussion{$_}] <= $currdepth) && ($alldiscussion{$_} != $firstidx)) { + print $manifestfile ' '."\n"; + } + $currdepth = $depth[$alldiscussion{$_}]; + print $manifestfile "\n". + ''. + ''.$imsitems{$alldiscussion{$_}}{'title'}.''; + $imsresources .= "\n". + ''. + ''."\n". + $imsfiles{$alldiscussion{$_}}{$imsitems{$alldiscussion{$_}}{'currversion'}}."\n". + ''; + } + my $postingfile; + my $postingfilename = $tempexport.'/'.$postfilename; + if ($postingfile = Apache::File->new('>'.$postingfilename)) { + print $postingfile 'Discussion Post'. + $imsitems{$alldiscussion{$_}}{'title'}.' '. + $imsitems{$alldiscussion{$_}}{'sender'}. + $imsitems{$alldiscussion{$_}}{'timestamp'}.'

'. + $imsitems{$alldiscussion{$_}}{'message'}.'
'. + $imsitems{$alldiscussion{$_}}{'attach'}.''."\n"; + close($postingfile); + } else { + $discussion .= 'An error occurred opening the export file for posting '.$alldiscussion{$_}.'
'; + } + $copyresult.=&replicate_attachments($imsitems{$alldiscussion{$_}}{'allattachments'},$tempexport); + } else { + $discussion.='
'. $discussionitems[$alldiscussion{$_}]. + '
@@ -464,51 +525,152 @@ sub list_discussion { + '; + '1. '.$lt{'disp'}.' - '.$currdisp.'  2. '.$lt{'nolo'}.' - '.$currmark.''; + if ($dischash{$toggkey}) { + $discussion .= '  3. '.$lt{'togg'}.' - '.$currtogg.''; + } } else { - $discussion .= - ''; + if ($dischash{$toggkey}) { + $discussion .= '1. '.$lt{'disp'}.' - '.$currdisp.' 2. '.$lt{'togg'}.' - '.$currtogg.''; + } else { + $discussion .= + $lt{'disp'}.' - '.$currdisp.''; + } } $discussion .= < + $lt{'chgt'}? +
$lt{'cuse'}:   END if ($newpostsflag) { $discussion .= - '1. '.$lt{'disp'}.' - '.$currdisp.'  2. '.$lt{'nolo'}.' - '.$currmark.''.$lt{'disp'}.' - '.$currdisp.'  - $lt{'chgt'}?
'. + ''."\n". + ''."\n". + '
-

+

END - } + } + if ($outputtarget eq 'export') { + if ($manifestok) { + while ($currdepth > 0) { + print $manifestfile " \n"; + $currdepth --; + } + print $manifestfile qq| +
+
+ + $imsresources + +
+ |; + close($manifestfile); + +#Create zip file in prtspool + + my $imszipfile = '/prtspool/'. + $ENV{'user.name'}.'_'.$ENV{'user.domain'}.'_'. + time.'_'.rand(1000000000).'.zip'; + # zip can cause an sh launch which can pass along all of %ENV + # which can be too large for /bin/sh to handle + my %oldENV=%ENV; + undef(%ENV); + my $cwd = &getcwd(); + my $imszip = '/home/httpd/'.$imszipfile; + chdir $tempexport; + open(OUTPUT, "zip -r $imszip * 2> /dev/null |"); + close(OUTPUT); + chdir $cwd; + %ENV=%oldENV; + undef(%oldENV); + $discussion .= 'Download the zip file from Discussion Posting Archive
'; + if ($copyresult) { + $discussion .= 'The following errors occurred during export -
'.$copyresult; + } + } else { + $discussion .= '
Unfortunately you will not be able to retrieve an archive of the discussion posts at this time, because there was a problem creating a manifest file.
'; + } + return $discussion; + } } if ($discussiononly) { - $discussion.=(< 0) { + $attachnum += @currnewattach; + } + } + if (&discussion_open($status)) { + $discussion.=(< -
-Note: in anonymous discussion, your name is visible only to -course faculty
-Title: 

- -

-Attachment (128 KB max size): -

- + +
+Note: in anonymous discussion, your name is visible only +to course faculty
+Title: 

+ ENDDISCUSS + if ($ENV{'form.origpage'}) { + $discussion.=''."\n"; + foreach (@currnewattach) { + $discussion.=''."\n"; + } + } + $discussion.="\n"; if ($outputtarget ne 'tex') { + $discussion.=&generate_attachments_button('',$attachnum,$ressymb,$now,\@currnewattach,\@currdelold,'',$mode); + if (@currnewattach > 0) { + $newattachmsg .= 'New attachments
'; + if (@currnewattach > 1) { + $newattachmsg .= '
    '; + foreach my $item (@currnewattach) { + $item =~ m#.*/([^/]+)$#; + $newattachmsg .= '
  1. '.$1.'
  2. '."\n"; + } + $newattachmsg .= '
'."\n"; + } else { + $currnewattach[0] =~ m#.*/([^/]+)$#; + $newattachmsg .= ''.$1.'
'."\n"; + } + } + $discussion.=$newattachmsg; $discussion.=&generate_preview_button(); } - } else { + } + } else { if (&discussion_open($status) && &Apache::lonnet::allowed('pch', $ENV{'request.course.id'}. @@ -519,41 +681,647 @@ ENDDISCUSS ''. &mt('Post Discussion').''; } - } + } } - return $discussion; + return $discussion; +} + +sub build_posting_display { + my ($usernamesort,$subjectsort,$namesort,$notshown,$newitem,$dischash,$shown,$alldiscussion,$imsitems,$imsfiles,$roleinfo,$discussionitems,$replies,$depth,$posters,$maxdepth,$visible,$newpostsflag,$current,$status,$viewgrades,$seeid,$prevread,$sortposts,$ressymb,$target,$readkey,$showunmark,$showonlyunread,$totposters,$rolefilter,$sectionpick,$statusfilter,$toggkey,$outputtarget) = @_; + + my @original=(); + my @index=(); + + my %contrib=&Apache::lonnet::restore($ressymb,$ENV{'request.course.id'}, + $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}, + $ENV{'course.'.$ENV{'request.course.id'}.'.num'}); + + if ($contrib{'version'}) { + my $oldest = $contrib{'1:timestamp'}; + if ($prevread eq '0') { + $prevread = $oldest-1; + } + for (my $id=1;$id<=$contrib{'version'};$id++) { + my $idx=$id; + my $posttime = $contrib{$idx.':timestamp'}; + if ($prevread <= $posttime) { + $$newpostsflag = 1; + } + my $hidden=($contrib{'hidden'}=~/\.$idx\./); + my $studenthidden=($contrib{'studenthidden'}=~/\.$idx\./); + my $deleted=($contrib{'deleted'}=~/\.$idx\./); + my $origindex='0.'; + my $numoldver=0; + if ($contrib{$idx.':replyto'}) { + if ( (($ENV{'environment.threadeddiscussion'}) && (($sortposts eq '') || ($sortposts eq 'ascdate'))) || ($sortposts eq 'thread') || ($outputtarget eq 'export')) { +# this is a follow-up message + $original[$idx]=$original[$contrib{$idx.':replyto'}]; + $$depth[$idx]=$$depth[$contrib{$idx.':replyto'}]+1; + $origindex=$index[$contrib{$idx.':replyto'}]; + if ($$depth[$idx]>$$maxdepth) { $$maxdepth=$$depth[$idx]; } + } else { + $original[$idx]=0; + $$depth[$idx]=0; + } + } else { +# this is an original message + $original[$idx]=0; + $$depth[$idx]=0; + } + if ($$replies[$$depth[$idx]]) { + $$replies[$$depth[$idx]]++; + } else { + $$replies[$$depth[$idx]]=1; + } + unless ((($hidden) && (!$seeid)) || ($deleted)) { + $$visible++; + if ($contrib{$idx.':history'}) { + if ($contrib{$idx.':history'} =~ /:/) { + my @oldversions = split/:/,$contrib{$idx.':history'}; + $numoldver = @oldversions; + } else { + $numoldver = 1; + } + } + $$current = $numoldver; + my %messages = (); + my %subjects = (); + my %attachtxt = (); + my %allattachments = (); + my ($screenname,$plainname); + my $sender = &mt('Anonymous'); + my ($message,$subject,$vgrlink,$ctlink); + &get_post_contents(\%contrib,$idx,$seeid,$outputtarget,\%messages,\%subjects,\%allattachments,\%attachtxt,$imsfiles,\$screenname,\$plainname,$numoldver); + + +# Set up for sorting by subject + unless ($outputtarget eq 'export') { + $message=$messages{$numoldver}; + $message.=$attachtxt{$numoldver}; + $subject=$subjects{$numoldver}; + if ($message) { + if ($hidden) { + $message=''.$message.''; + if ($studenthidden) { + $message .='

Deleted by poster (student).'; + } + } + + if ($subject eq '') { + if (defined($$subjectsort{'__No subject'})) { + push @{$$subjectsort{'__No subject'}}, $idx; + } else { + @{$$subjectsort{'__No subject'}} = ("$idx"); + } + } else { + if (defined($$subjectsort{$subject})) { + push @{$$subjectsort{$subject}}, $idx; + } else { + @{$$subjectsort{$subject}} = ("$idx"); + } + } + if ((!$contrib{$idx.':anonymous'}) || ($seeid)) { + $sender=&Apache::loncommon::aboutmewrapper( + $plainname, + $contrib{$idx.':sendername'}, + $contrib{$idx.':senderdomain'}).' ('. + $contrib{$idx.':sendername'}.' at '. + $contrib{$idx.':senderdomain'}.')'; + if ($contrib{$idx.':anonymous'}) { + $sender.=' ['.&mt('anonymous').'] '. + $screenname; + } + +# Set up for sorting by domain, then username + unless (defined($$usernamesort{$contrib{$idx.':senderdomain'}})) { + %{$$usernamesort{$contrib{$idx.':senderdomain'}}} = (); + } + if (defined($$usernamesort{$contrib{$idx.':senderdomain'}}{$contrib{$idx.':sendername'}})) { + push @{$$usernamesort{$contrib{$idx.':senderdomain'}}{$contrib{$idx.':sendername'}}}, $idx; + } else { + @{$$usernamesort{$contrib{$idx.':senderdomain'}}{$contrib{$idx.':sendername'}}} = ("$idx"); + } +# Set up for sorting by last name, then first name + my %names = &Apache::lonnet::get('environment', + ['firstname','lastname'],$contrib{$idx.':senderdomain'}, + ,$contrib{$idx.':sendername'}); + my $lastname = $names{'lastname'}; + my $firstname = $names{'firstname'}; + if ($lastname eq '') { + $lastname = '_'; + } + if ($firstname eq '') { + $firstname = '_'; + } + unless (defined($$namesort{$lastname})) { + %{$$namesort{$lastname}} = (); + } + if (defined($$namesort{$lastname}{$firstname})) { + push @{$$namesort{$lastname}{$firstname}}, $idx; + } else { + @{$$namesort{$lastname}{$firstname}} = ("$idx"); + } + if ($ENV{'course.'.$ENV{'request.course.id'}.'.allow_discussion_post_editing'} =~ m/yes/i) { + if (($ENV{'user.domain'} eq $contrib{$idx.':senderdomain'}) && ($ENV{'user.name'} eq $contrib{$idx.':sendername'})) { + $sender.=' '.&mt('Edit').''; + unless ($seeid) { + $sender.=" '; + } + } + } + if ($seeid) { + if ($hidden) { + unless ($studenthidden) { + $sender.=' '.&mt('Make Visible').''; + } + } else { + $sender.=' '.&mt('Hide').''; + } + $sender.=' '.&mt('Delete').''; + } + } else { + if ($screenname) { + $sender=''.$screenname.''; + } +# Set up for sorting by domain, then username for anonymous + unless (defined($$usernamesort{'__anon'})) { + %{$$usernamesort{'__anon'}} = (); + } + if (defined($$usernamesort{'__anon'}{'__anon'})) { + push @{$$usernamesort{'__anon'}{'__anon'}}, $idx; + } else { + @{$$usernamesort{'__anon'}{'__anon'}} = ("$idx"); + } +# Set up for sorting by last name, then first name for anonymous + unless (defined($$namesort{'__anon'})) { + %{$$namesort{'__anon'}} = (); + } + if (defined($$namesort{'__anon'}{'__anon'})) { + push @{$$namesort{'__anon'}{'__anon'}}, $idx; + } else { + @{$$namesort{'__anon'}{'__anon'}} = ("$idx"); + } + } + if (&discussion_open($status) && + &Apache::lonnet::allowed('pch', + $ENV{'request.course.id'}. + ($ENV{'request.course.sec'}?'/'.$ENV{'request.course.sec'}:''))) { + $sender.=' '.&mt('Reply').''; + } + if ($viewgrades) { + $vgrlink=&Apache::loncommon::submlink('Submissions', + $contrib{$idx.':sendername'},$contrib{$idx.':senderdomain'},$ressymb); + } + if ($$dischash{$readkey}=~/\.$idx\./) { + $ctlink = ''.&mt('Mark unread').'? '; + } else { + $ctlink = ''.&mt('Mark read').'? '; + } + } +#figure out at what position this needs to print + } + if ($outputtarget eq 'export' || $message) { + my $thisindex=$idx; + if ( (($ENV{'environment.threadeddiscussion'}) && (($sortposts eq '') || ($sortposts eq 'ascdate'))) || ($sortposts eq 'thread') || ($outputtarget eq 'export')) { + $thisindex=$origindex.substr('00'.$$replies[$$depth[$idx]],-2,2); + } + $$alldiscussion{$thisindex}=$idx; + $$shown{$idx} = 0; + $index[$idx]=$thisindex; + } + if ($outputtarget eq 'export') { + %{$$imsitems{$idx}} = (); + $$imsitems{$idx}{'isvisible'}='true'; + if ($hidden) { + $$imsitems{$idx}{'isvisible'}='false'; + } + $$imsitems{$idx}{'title'}=$subjects{$numoldver}; + $$imsitems{$idx}{'message'}=$messages{$numoldver}; + $$imsitems{$idx}{'attach'}=$attachtxt{$numoldver}; + $$imsitems{$idx}{'timestamp'}=$contrib{$idx.':timestamp'}; + $$imsitems{$idx}{'sender'}=$plainname.' ('. + $contrib{$idx.':sendername'}.' at '. + $contrib{$idx.':senderdomain'}.')'; + $$imsitems{$idx}{'isanonymous'}='false'; + if ($contrib{$idx.':anonymous'}) { + $$imsitems{$idx}{'isanonymous'}='true'; + } + $$imsitems{$idx}{'currversion'}=$numoldver; + %{$$imsitems{$idx}{'allattachments'}}=%allattachments; + unless ($messages{$numoldver} eq '' && $attachtxt{$numoldver} eq '') { + $$shown{$idx} = 1; + } + } else { + if ($message) { + my $spansize = 2; + if ($showonlyunread && $prevread > $posttime) { + $$notshown{$idx} = 1; + } elsif ($showunmark && $$dischash{$readkey}=~/\.$idx\./) { + $$notshown{$idx} = 1; + } else { +# apply filters + my $uname = $contrib{$idx.':sendername'}; + my $udom = $contrib{$idx.':senderdomain'}; + my $poster = $uname.':'.$udom; + my $rolematch = ''; + my $skiptest = 1; + if ($totposters > 0) { + if (grep/^$poster$/,@{$posters}) { + $$shown{$idx} = 1; + } + } else { + if ($rolefilter) { + if ($rolefilter eq 'all') { + $rolematch = '([^:]+)'; + } else { + $rolematch = $rolefilter; + $skiptest = 0; + } + } + if ($sectionpick) { + if ($sectionpick eq 'all') { + $rolematch .= ':([^:]*)'; + } else { + $rolematch .= ':'.$sectionpick; + $skiptest = 0; + } + } + if ($statusfilter) { + if ($statusfilter eq 'all') { + $rolematch .= ':([^:]+)'; + } else { + $rolematch .= ':'.$statusfilter; + $skiptest = 0; + } + } + if ($skiptest) { + $$shown{$idx} = 1; + } else { + foreach my $role (@{$$roleinfo{$poster}}) { + if ($role =~ m/^$rolematch$/) { + $$shown{$idx} = 1; + last; + } + } + } + } + } + unless ($$notshown{$idx} == 1) { + if ($prevread > 0 && $prevread <= $posttime) { + $$newitem{$idx} = 1; + $$discussionitems[$idx] .= ' +

+ '; + } else { + $$newitem{$idx} = 0; + $$discussionitems[$idx] .= ' +

NEW
+ '; + } + $$discussionitems[$idx] .= ''; + if ($$dischash{$toggkey}) { + $$discussionitems[$idx].=''; + } + $$discussionitems[$idx].= '
   '. + ''.$subject.'  '. + $sender.' '.$vgrlink.' ('. + &Apache::lonlocal::locallocaltime($posttime).')  '. + $ctlink.'

'. + $message.'

'; + if ($contrib{$idx.':history'}) { + my @postversions = (); + $$discussionitems[$idx] .= &mt('This post has been edited by the author.'); + if ($seeid) { + $$discussionitems[$idx] .= '  '.&mt('Display all versions').''; + } + $$discussionitems[$idx].='
'.&mt('Earlier version(s) were posted on: '); + if ($contrib{$idx.':history'} =~ m/:/) { + @postversions = split/:/,$contrib{$idx.':history'}; + } else { + @postversions = ("$contrib{$idx.':history'}"); + } + for (my $i=0; $i<@postversions; $i++) { + my $version = $i+1; + $$discussionitems[$idx] .= ''.$version.'. - '.&Apache::lonlocal::locallocaltime($postversions[$i]).' '; + } + } + } + } + } + } + } + } +} + +sub get_post_contents { + my ($contrib,$idx,$seeid,$type,$messages,$subjects,$allattachments,$attachtxt,$imsfiles,$screenname,$plainname,$numver) = @_; + my $discussion = ''; + my $start=$numver; + my $end=$numver + 1; + %{$$imsfiles{$idx}}=(); + if ($type eq 'allversions') { + unless($seeid) { + $discussion=&mt('You do not have privileges to view all versions of posts.').&mt('Please select a different role'); + return $discussion; + } + } +# $$screenname=&Apache::loncommon::screenname( +# $$contrib{$idx.':sendername'}, +# $$contrib{$idx.':senderdomain'}); +# $$plainname=&Apache::loncommon::nickname( +# $$contrib{$idx.':sendername'}, +# $$contrib{$idx.':senderdomain'}); + ($$screenname,$$plainname)=($$contrib{$idx.':screenname'}, + $$contrib{$idx.':plainname'}); + my $sender=&Apache::loncommon::aboutmewrapper( + $$plainname, + $$contrib{$idx.':sendername'}, + $$contrib{$idx.':senderdomain'}).' ('. + $$contrib{$idx.':sendername'}.' at '. + $$contrib{$idx.':senderdomain'}.')'; + my $attachmenturls = $$contrib{$idx.':attachmenturl'}; + my @postversions = (); + if ($type eq 'allversions' || $type eq 'export') { + $start = 0; + if ($$contrib{$idx.':history'}) { + if ($$contrib{$idx.':history'} =~ m/:/) { + @postversions = split/:/,$$contrib{$idx.':history'}; + } else { + @postversions = ("$$contrib{$idx.':history'}"); + } + } + &get_post_versions($messages,$$contrib{$idx.':message'},1); + &get_post_versions($subjects,$$contrib{$idx.':subject'},1); + push @postversions,$$contrib{$idx.':timestamp'}; + $end = @postversions; + } else { + &get_post_versions($messages,$$contrib{$idx.':message'},1,$numver); + &get_post_versions($subjects,$$contrib{$idx.':subject'},1,$numver); + } + + if ($$contrib{$idx.':anonymous'}) { + $sender.=' ['.&mt('anonymous').'] '.$$screenname; + } + if ($type eq 'allversions') { + $discussion=(''.$sender.'
'); + return $discussion; + } else { + return; + } +} + +sub replicate_attachments { + my ($attachrefs,$tempexport) = @_; + my $response; + foreach my $id (keys %{$attachrefs}) { + if ($$attachrefs{$id}{'filename'} =~ m-^/uploaded/([^/]+)/([^/]+)(/feedback)?(/?\d*)/([^/]+)$-) { + my $path = $tempexport; + my $tail = $1.'/'.$2.$4; + my @extras = split/\//,$tail; + my $destination = $tempexport.'/'.$1.'/'.$2.$4.'/'.$5; + if (!-e $destination) { + my $i= 0; + while ($i<@extras) { + $path .= '/'.$extras[$i]; + if (!-e $path) { + mkdir($path,0700); + } + $i ++; + } + my ($content,$rtncode); + my $uploadreply = &Apache::lonnet::getuploaded('GET',$$attachrefs{$id}{'filename'},$1,$2,$content,$rtncode); + if ($uploadreply eq 'ok') { + my $attachcopy; + if ($attachcopy = Apache::File->new('>'.$destination)) { + print $attachcopy $content; + close($attachcopy); + } else { + $response .= 'Error copying file attachment - '.$5.' to IMS package: '.$!.'
'."\n"; + } + } else { + &Apache::lonnet::logthis("Replication of attachment failed when building IMS export of discussion posts - domain: $1, course: $2, file: $$attachrefs{$id}{'filename'} -error: $rtncode"); + $response .= 'Error copying file attachment - '.$5.' to IMS package: '.$rtncode.'
'."\n"; + } + } + } + } + return $response; } sub mail_screen { my ($r,$feedurl,$options) = @_; + if (exists($ENV{'form.origpage'})) { + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['subject','comment','currnewattach','addnewattach','deloldattach','delnewattach','timestamp','idx','anondiscuss','discuss']); + } my $bodytag=&Apache::loncommon::bodytag('Resource Feedback and Discussion', - '','onLoad="window.focus();"'); + '','onLoad="window.focus();setposttype();"'); my $title=&Apache::lonnet::gettitle($feedurl); if (!$title) { $title = $feedurl; } my $quote=''; my $subject = ''; + my $comment = ''; my $prevtag = ''; - if ($ENV{'form.replydisc'}) { - my ($symb,$idx)=split(/\:\:\:/,$ENV{'form.replydisc'}); + my $parentmsg = ''; + my ($symb,$idx,$attachmenturls); + my $numoldver = 0; + my $attachmsg = ''; + my $newattachmsg = ''; + my @currnewattach = (); + my @currdelold = (); + my @keepold = (); + my %attachments = (); + my %currattach = (); + my $attachnum = 0; + my $anonchk = (</g; - $quote='
'.&Apache::lontexconvert::msgtexconverted($message).'
'; - if ($idx > 0) { - $subject = 'Re: '.$contrib{$idx.':subject'}; + if ($contrib{$idx.':history'}) { + if ($contrib{$idx.':history'} =~ /:/) { + my @oldversions = split/:/,$contrib{$idx.':history'}; + $numoldver = @oldversions; + } else { + $numoldver = 1; + } + } + if ($ENV{'form.replydisc'}) { + if ($contrib{$idx.':history'}) { + if ($contrib{$idx.':history'} =~ /:/) { + my @oldversions = split/:/,$contrib{$idx.':history'}; + $numoldver = @oldversions; + } else { + $numoldver = 1; + } + } + my $message; + if ($idx > 0) { + my %msgversions = (); + &get_post_versions(\%msgversions,$contrib{$idx.':message'},0,$numoldver); + $message = $msgversions{$numoldver}; + } + $message=~s/\n/\
/g; + $quote='
'.&Apache::lontexconvert::msgtexconverted($message).'
'; + if ($idx > 0) { + my %subversions = (); + &get_post_versions(\%subversions,$contrib{$idx.':subject'},1,$numoldver); + $subject = 'Re: '.$subversions{$numoldver}; + } + $subject = &HTML::Entities::encode($subject,'<>&"'); + } else { + $attachmenturls = $contrib{$idx.':attachmenturl'}; + if ($idx > 0) { + my %msgversions = (); + &get_post_versions(\%msgversions,$contrib{$idx.':message'},0,$numoldver); + $comment = $msgversions{$numoldver}; + my %subversions = (); + &get_post_versions(\%subversions,$contrib{$idx.':subject'},0,$numoldver); + $subject = $subversions{$numoldver}; + } + if (defined($contrib{$idx.':replyto'})) { + $parentmsg = $contrib{$idx.':replyto'}; + } + unless (exists($ENV{'form.origpage'})) { + my $anonflag = 0; + if ($contrib{$idx.':anonymous'}) { + $anonflag = 1; + } + $anonscript = (<'; } } + + if ($ENV{'form.origpage'}) { + $subject = &Apache::lonnet::unescape($ENV{'form.subject'}); + $comment = &Apache::lonnet::unescape($ENV{'form.comment'}); + &process_attachments(\@currnewattach,\@currdelold,\@keepold); + } my $latexHelp=&Apache::loncommon::helpLatexCheatsheet(); my $htmlheader=&Apache::lonhtmlcommon::htmlareaheaders(); my $send=&mt('Send'); - $r->print(<print(< The LearningOnline Network with CAPA @@ -603,6 +1371,8 @@ $htmlheader alert('Please check a feedback type.'); } } + $anonchk + $anonscript //--> @@ -612,7 +1382,18 @@ $bodytag enctype="multipart/form-data"> $prevtag +END + if ($ENV{'form.replydisc'}) { + $r->print(< +END + } elsif ($ENV{'form.editdisc'}) { + $r->print(< + +END + } + $r->print(< $quote @@ -621,24 +1402,82 @@ $quote $latexHelp Title:

-

+END + if ( ($ENV{'form.editdisc'}) || ($ENV{'form.replydisc'}) ) { + if ($ENV{'form.origpage'}) { + foreach (@currnewattach) { + $r->print(''."\n"); + } + foreach (@currdelold) { + $r->print(''."\n"); + } + } + if ($ENV{'form.editdisc'}) { + if ($attachmenturls) { + &extract_attachments($attachmenturls,$idx,$numoldver,\$attachmsg,\%attachments,\%currattach,\@currdelold); + $attachnum = scalar(keys %currattach); + foreach (keys %currattach) { + $r->print(''."\n"); + } + } + } + } else { + $r->print(<

+END + } + $r->print(<

-ENDDOCUMENT -$r->print(&generate_preview_button(). -&Apache::lonhtmlcommon::htmlareaselectactive('comment'). -''); +END + if ($ENV{'form.editdisc'} || $ENV{'form.replydisc'}) { + my $now = time; + my $ressymb = $symb; + my $postidx = ''; + if ($ENV{'form.editdisc'}) { + $postidx = $idx; + } + if (@currnewattach > 0) { + $attachnum += @currnewattach; + } + $r->print(&generate_attachments_button($postidx,$attachnum,$ressymb,$now,\@currnewattach,\@currdelold,$numoldver)); + if ($attachnum > 0) { + if (@currnewattach > 0) { + $newattachmsg .= 'New attachments
'; + if (@currnewattach > 1) { + $newattachmsg .= '
    '; + foreach my $item (@currnewattach) { + $item =~ m#.*/([^/]+)$#; + $newattachmsg .= '
  1. '.$1.'
  2. '."\n"; + } + $newattachmsg .= '
'."\n"; + } else { + $currnewattach[0] =~ m#.*/([^/]+)$#; + $newattachmsg .= ''.$1.'
'."\n"; + } + } + if ($attachmsg) { + $r->print("Retained attachments:$attachmsg
\n"); + } + if ($newattachmsg) { + $r->print("$newattachmsg
"); + } + } + } + $r->print(&generate_preview_button(). + &Apache::lonhtmlcommon::htmlareaselectactive('comment'). + ''); } sub print_display_options { - my ($r,$symb,$previous,$dispchg,$markchg,$feedurl) = @_; + my ($r,$symb,$previous,$dispchgA,$dispchgB,$markchg,$toggchg,$feedurl) = @_; # backward compatibility (bulletin boards used to be 'wrapped') if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) { $feedurl=~s|^/adm/wrapper||; @@ -658,54 +1497,116 @@ sub print_display_options { 'deff' => 'Default for all discussions', 'prca' => 'Preferences can be set for this discussion that determine ....', 'whpo' => 'Which posts are displayed when you display this bulletin board or resource, and', - 'unwh' => 'Under what circumstances posts are identfied as "New."', + 'unwh' => 'Under what circumstances posts are identified as "NEW", and', + 'wipa' => 'Whether individual posts can be marked as read/unread', 'allposts' => 'All posts', 'unread' => 'New posts only', + 'unmark' => 'Posts not marked read', 'ondisp' => 'Once displayed', - 'onmark' => 'Once marked as read', + 'onmark' => 'Once marked not NEW ', + 'toggon' => 'Shown', + 'toggoff' => 'Not shown', 'disa' => 'Posts displayed?', - 'npmr' => 'New posts cease to be identified as "New"?', + 'npmr' => 'New posts cease to be identified as "NEW"?', + 'dotm' => 'Option to mark each post as read/unread?', 'chgt' => 'Change to ', 'mkdf' => 'Set to ', - 'yhni' => 'You have not indicated that you wish to change either of the discussion settings', + 'yhni' => 'You have not indicated that you wish to change any of the discussion settings', 'ywbr' => 'You will be returned to the previous page if you click OK.' ); - my $dispchange = $lt{'unread'}; + my $dispchangeA = $lt{'unread'}; + my $dispchangeB = $lt{'unmark'}; my $markchange = $lt{'ondisp'}; + my $toggchange = $lt{'toggon'}; my $currdisp = $lt{'allposts'}; my $currmark = $lt{'onmark'}; my $discdisp = 'allposts'; my $discmark = 'onmark'; + my $currtogg = $lt{'toggoff'}; + my $disctogg = 'toggoff'; - if ($dispchg eq 'allposts') { - $dispchange = $lt{'allposts'}; + if ($dispchgA eq 'allposts') { + $dispchangeA = $lt{'allposts'}; $currdisp = $lt{'unread'}; $discdisp = 'unread'; } - + if ($markchg eq 'markonread') { $markchange = $lt{'onmark'}; $currmark = $lt{'ondisp'}; $discmark = 'ondisp'; } + + if ($dispchgB eq 'onlyunread') { + $dispchangeB = $lt{'unread'}; + $currdisp = $lt{'unmark'}; + $discdisp = 'unmark'; + } + if ($toggchg eq 'toggoff') { + $toggchange = $lt{'toggoff'}; + $currtogg = $lt{'toggon'}; + $disctogg = 'toggon'; + } $r->print(< $lt{'dido'} + +$bodytag +
+ + + + +
+ Subject: $subject

+END + if ($idx) { + if ($attachmenturls) { + my @currold = keys %currattach; + if (@currold > 0) { + $r->print("The following attachments were part of the most recent saved version of this posting.
Check the checkboxes for any you wish to remove
\n"); + foreach my $id (@currold) { + my $attachurl = &HTML::Entities::decode($attachments{$id}{'filename'}); + $attachurl =~ m#/([^/]+)$#; + $r->print(' '.$1.'
'."\n"); + } + $r->print("
"); + } + } + } + if (@{$currnewattach} > 0) { + $r->print("The following attachments have been uploaded for inclusion with this posting.
Check the checkboxes for any you wish to remove
\n"); + foreach (@{$currnewattach}) { + $_ =~ m#/([^/]+)$#; + $r->print(' '.$1.'
'."\n"); + } + $r->print("
"); + } + $r->print(< +
+ + + + + + + + +END + foreach (@{$currnewattach}) { + $r->print(''."\n"); + } + foreach (@{$currdelold}) { + $r->print(''."\n"); + } + $r->print(< + + + +END + return; +} + +sub process_attachments { + my ($currnewattach,$currdelold,$keepold) = @_; + if (exists($ENV{'form.currnewattach'})) { + if (ref($ENV{'form.currnewattach'}) eq 'ARRAY') { + @{$currnewattach} = @{$ENV{'form.currnewattach'}}; + } else { + $$currnewattach[0] = $ENV{'form.currnewattach'}; + } + } + if (exists($ENV{'form.deloldattach'})) { + if (ref($ENV{'form.deloldattach'}) eq 'ARRAY') { + @{$currdelold} = @{$ENV{'form.deloldattach'}}; + } else { + $$currdelold[0] = $ENV{'form.deloldattach'}; + } + } + if (exists($ENV{'form.delnewattach'})) { + my @currdelnew = (); + my @currnew = (); + if (ref($ENV{'form.delnewattach'}) eq 'ARRAY') { + @currdelnew = @{$ENV{'form.delnewattach'}}; + } else { + $currdelnew[0] = $ENV{'form.delnewattach'}; + } + foreach my $newone (@{$currnewattach}) { + my $delflag = 0; + foreach (@currdelnew) { + if ($newone eq $_) { + $delflag = 1; + last; + } + } + unless ($delflag) { + push @currnew, $newone; + } + } + @{$currnewattach} = @currnew; + } + if (exists($ENV{'form.keepold'})) { + if (ref($ENV{'form.keepold'}) eq 'ARRAY') { + @{$keepold} = @{$ENV{'form.keepold'}}; + } else { + $$keepold[0] = $ENV{'form.keepold'}; + } + } +} + +sub generate_attachments_button { + my ($idx,$attachnum,$ressymb,$now,$currnewattach,$deloldattach,$numoldver,$mode) = @_; + my $origpage = $ENV{'REQUEST_URI'}; + my $att=$attachnum.' '.&mt("attachments"); + my $response = (< +Click to add/remove attachments:  + + + + + + +ENDATTACH + if (defined($deloldattach)) { + if (@{$deloldattach} > 0) { + foreach (@{$deloldattach}) { + $response .= ''."\n"; + } + } + } + if (defined($currnewattach)) { + if (@{$currnewattach} > 0) { + foreach (@{$currnewattach}) { + $response .= ''."\n"; + } + } + } + $response .= ''; + return $response; +} + +sub extract_attachments { + my ($attachmenturls,$idx,$numoldver,$message,$attachments,$currattach,$currdelold) = @_; + %{$attachments}=(); + &get_post_attachments($attachments,$attachmenturls); + foreach my $id (sort keys %{$attachments}) { + if (exists($$attachments{$id}{$numoldver})) { + if (defined($currdelold)) { + if (@{$currdelold} > 0) { + unless (grep/^$id$/,@{$currdelold}) { + $$currattach{$id} = $$attachments{$id}{$numoldver}; + } + } else { + $$currattach{$id} = $$attachments{$id}{$numoldver}; + } + } else { + $$currattach{$id} = $$attachments{$id}{$numoldver}; + } + } + } + my @attached = (sort { $a <=> $b } keys %{$currattach}); + if (@attached == 1) { + my $id = $attached[0]; + my $attachurl; + if ($attachmenturls =~ m/^/) { + $attachurl = &HTML::Entities::decode($$attachments{$id}{'filename'}); + } else { + $attachurl = $$attachments{$id}{'filename'}; + } + $attachurl=~m|/([^/]+)$|; + $$message.='
'. + $1.'
'; + &Apache::lonnet::allowuploaded('/adm/feedback', + $attachurl); + } elsif (@attached > 1) { + $$message.='
    '; + foreach (@attached) { + my $id = $_; + my $attachurl = &HTML::Entities::decode($$attachments{$id}{'filename'}); + my ($fname) + =($attachurl=~m|/([^/]+)$|); + $$message .= '
  1. '. + $fname.'
  2. '; + &Apache::lonnet::allowuploaded('/adm/feedback', + $attachurl); + } + $$message .= '
'; + } +} + +sub construct_attachmenturl { + my ($currnewattach,$keepold,$symb,$idx)=@_; + my $oldattachmenturl; + my $newattachmenturl; + my $startnum = 0; + my $currver = 0; + if (($ENV{'form.editdisc'}) && ($idx)) { + my %contrib=&Apache::lonnet::restore($symb,$ENV{'request.course.id'}, + $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}, + $ENV{'course.'.$ENV{'request.course.id'}.'.num'}); + $oldattachmenturl = $contrib{$idx.':attachmenturl'}; + if ($contrib{$idx.':history'}) { + if ($contrib{$idx.':history'} =~ /:/) { + my @oldversions = split/:/,$contrib{$idx.':history'}; + $currver = 1 + scalar(@oldversions); + } else { + $currver = 2; + } + } else { + $currver = 1; + } + if ($oldattachmenturl) { + if ($oldattachmenturl =~ m/^/) { + my %attachments = (); + my $prevver = $currver-1; + &get_post_attachments(\%attachments,$oldattachmenturl); + my $numattach = scalar(keys %attachments); + $startnum += $numattach; + foreach my $num (sort {$a <=> $b} keys %attachments) { + $newattachmenturl .= ''.$attachments{$num}{'filename'}.''; + foreach $_ (sort {$a <=> $b} keys %{$attachments{$num}}) { + unless ($_ eq 'filename') { + $newattachmenturl .= ''.$attachments{$num}{$_}.''; + } + } + if (grep/^$num$/,@{$keepold}) { + $newattachmenturl .= ''.$attachments{$num}{$prevver}.''; + } + $newattachmenturl .= ''; + } + } else { + $newattachmenturl = ''.&HTML::Entities::encode($oldattachmenturl).'n'; + unless (grep/^0$/,@{$keepold}) { + $newattachmenturl .= 'n'; + } + $newattachmenturl .= ''; + $startnum ++; + } + } + } + for (my $i=0; $i<@{$currnewattach}; $i++) { + my $attachnum = $startnum + $i; + $newattachmenturl .= ''.&HTML::Entities::encode($$currnewattach[$i]).'n'; + } + return $newattachmenturl; +} + sub handler { my $r = shift; if ($r->header_only) { @@ -1133,8 +2728,154 @@ sub handler { # --------------------------- Get query string for limited number of parameters &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, - ['hide','unhide','deldisc','postdata','preview','replydisc','threadedon','threadedoff','onlyunread','allposts','previous','markread','markonread','markondisp','modifydisp','changes','navmaps','navurl']); - if ($ENV{'form.navmaps'}) { + ['hide','unhide','deldisc','postdata','preview','replydisc','editdisc','threadedon','threadedoff','onlyunread','allposts','onlyunmark','previous','markread','markonread','markondisp','toggoff','toggon','modifydisp','changes','navmaps','navurl','navtime','sortfilter','sortposts','applysort','rolefilter','statusfilter','sectionpick','posterlist','userpick','attach','origpage','currnewattach','deloldattach','keepold','allversions','export']); + if ($ENV{'form.discsymb'}) { + my $symb = $ENV{'form.discsymb'}; + my $readkey = $symb.'_read'; + my %readinghash = (); + my $chgcount = 0; + %readinghash = &Apache::lonnet::get('nohist_'.$ENV{'request.course.id'}.'_discuss',[$readkey],$ENV{'user.domain'},$ENV{'user.name'}); + foreach my $key (keys %ENV) { + if ($key =~ m/^form\.postunread_(\d+)/) { + if ($readinghash{$readkey} =~ /\.$1\./) { + $readinghash{$readkey} =~ s/\.$1\.//; + $chgcount ++; + } + } elsif ($key =~ m/^form\.postread_(\d+)/) { + unless ($readinghash{$readkey} =~ /\.$1\./) { + $readinghash{$readkey} .= '.'.$1.'.'; + $chgcount ++; + } + } + } + if ($chgcount > 0) { + &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',\%readinghash,$ENV{'user.domain'},$ENV{'user.name'}); + } + &Apache::loncommon::content_type($r,'text/html'); + $r->send_http_header; + my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb); + my $previous=$ENV{'form.previous'}; + my $feedurl = &Apache::lonnet::clutter($url); + &redirect_back($r,$feedurl,&mt('Marked postings read/unread').'
','0','0','',$previous,'','','',); + return OK; + } + if ($ENV{'form.allversions'}) { + &Apache::loncommon::content_type($r,'text/html'); + $r->send_http_header; + my $bodytag=&Apache::loncommon::bodytag('Discussion Post Versions', + '',''); + $r->print (< + +Post Versions + + +$bodytag +END + my $crs='/'.$ENV{'request.course.id'}; + if ($ENV{'request.course.sec'}) { + $crs.='_'.$ENV{'request.course.sec'}; + } + $crs=~s/\_/\//g; + my $seeid=&Apache::lonnet::allowed('rin',$crs); + my ($symb,$idx)=split(/\:\:\:/,$ENV{'form.allversions'}); + my $ressymb=$symb; + unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) { + $ressymb=~s|(bulletin___\d+___)|$1adm/wrapper|; + } + if ($idx > 0) { + my %messages = (); + my %subjects = (); + my %attachmsgs = (); + my %allattachments = (); + my %imsfiles = (); + my ($screenname,$plainname); + my %contrib=&Apache::lonnet::restore($ressymb,$ENV{'request.course.id'}, + $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}, + $ENV{'course.'.$ENV{'request.course.id'}.'.num'}); + my $discussion = &get_post_contents(\%contrib,$idx,$seeid,'allversions',\%messages,\%subjects,\%allattachments,\%attachmsgs,\%imsfiles,\$screenname,\$plainname); + $r->print($discussion); + } + return OK; + } + if ($ENV{'form.posterlist'}) { + &Apache::loncommon::content_type($r,'text/html'); + $r->send_http_header; + my $symb=$ENV{'form.posterlist'}; + my $sortposts = $ENV{'form.sortposts'}; + my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb); + my $previous=$ENV{'form.previous'}; + my $feedurl = &Apache::lonnet::clutter($url); + # backward compatibility (bulletin boards used to be 'wrapped') + if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) { + $feedurl=~s|^/adm/wrapper||; + } + &print_showposters($r,$symb,$previous,$feedurl,$sortposts); + return OK; + } + if ($ENV{'form.userpick'}) { + &Apache::loncommon::content_type($r,'text/html'); + $r->send_http_header; + my $symb=$ENV{'form.userpick'}; + my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb); + my $previous=$ENV{'form.previous'}; +# backward compatibility (bulletin boards used to be 'wrapped') + my $ressymb=$symb; + unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) { + $ressymb=~s|(bulletin___\d+___)|$1adm/wrapper|; + } + my $sort=$ENV{'form.sortposts'}; + my @posters = (); + if (ref($ENV{'form.stuinfo'}) eq 'ARRAY') { + @posters = $ENV{'form.stuinfo'}; + } else { + $posters[0] = $ENV{'form.stuinfo'}; + } + my $numpicks = @posters; + if (defined($ENV{'form.userpick'})) { + my %discinfo = (); + $discinfo{$ressymb.'_userpick'} = join('&',@posters); + &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',\%discinfo,$ENV{'user.domain'},$ENV{'user.name'}); + } + my $feedurl = &Apache::lonnet::clutter($url); + # backward compatibility (bulletin boards used to be 'wrapped') + if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) { + $feedurl=~s|^/adm/wrapper||; + } + &redirect_back($r,$feedurl,&mt('Changed sort/filter').'
','0','0','',$previous,$sort,'','','',$numpicks); + return OK; + } + if ($ENV{'form.applysort'}) { + &Apache::loncommon::content_type($r,'text/html'); + $r->send_http_header; + my $symb=$ENV{'form.applysort'}; + my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb); + my $previous=$ENV{'form.previous'}; + my $sort = $ENV{'form.sortposts'}; + my $rolefilter = $ENV{'form.rolefilter'}; + my $statusfilter = $ENV{'form.statusfilter'}; + my $secpick = $ENV{'form.sectionpick'}; + my $feedurl = &Apache::lonnet::clutter($url); + # backward compatibility (bulletin boards used to be 'wrapped') + if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) { + $feedurl=~s|^/adm/wrapper||; + } + &redirect_back($r,$feedurl,&mt('Changed sort/filter').'
','0','0','',$previous,$sort,$rolefilter,$statusfilter,$secpick); + return OK; + } elsif ($ENV{'form.sortfilter'}) { + &Apache::loncommon::content_type($r,'text/html'); + $r->send_http_header; + my $symb=$ENV{'form.sortfilter'}; + my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb); + my $previous=$ENV{'form.previous'}; + my $feedurl = &Apache::lonnet::clutter($url); + # backward compatibility (bulletin boards used to be 'wrapped') + if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) { + $feedurl=~s|^/adm/wrapper||; + } + &print_sortfilter_options($r,$symb,$previous,$feedurl); + return OK; + } elsif ($ENV{'form.navmaps'}) { my %discinfo = (); my @resources = (); if ($ENV{'form.navmaps'} =~ /:/) { @@ -1160,7 +2901,7 @@ sub handler { } } my $lastkey = $ressymb.'_lastread'; - $discinfo{$lastkey} = time; + $discinfo{$lastkey} = $ENV{'form.navtime'}; } &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',\%discinfo,$ENV{'user.domain'},$ENV{'user.name'}); &Apache::loncommon::content_type($r,'text/html'); @@ -1177,6 +2918,7 @@ sub handler { $lt{'mnpa'} $numitems $lt{'robb'}
+
Continue ENDREDIR @@ -1187,19 +2929,36 @@ ENDREDIR my $symb=$ENV{'form.modifydisp'}; my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb); my $previous=$ENV{'form.previous'}; - my ($dispchg,$markchg) = split/_/,$ENV{'form.changes'}; + my ($dispchgA,$dispchgB,$markchg,$toggchg) = split/_/,$ENV{'form.changes'}; my $feedurl = &Apache::lonnet::clutter($url); # backward compatibility (bulletin boards used to be 'wrapped') if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) { $feedurl=~s|^/adm/wrapper||; } - &print_display_options($r,$symb,$previous,$dispchg,$markchg,$feedurl); + &print_display_options($r,$symb,$previous,$dispchgA,$dispchgB,$markchg,$toggchg,$feedurl); return OK; - } elsif (($ENV{'form.markondisp'}) || ($ENV{'form.markonread'}) || ($ENV{'form.allposts'}) || ($ENV{'form.onlyunread'}) ) { + } elsif (($ENV{'form.markondisp'}) || ($ENV{'form.markonread'}) || ($ENV{'form.allposts'}) || ($ENV{'form.onlyunread'}) || $ENV{'form.onlyunmark'} || $ENV{'form.toggoff'} || $ENV{'form.toggon'} ) { &Apache::loncommon::content_type($r,'text/html'); $r->send_http_header; my $previous=$ENV{'form.previous'}; my ($map,$ind,$url); + if ( ($ENV{'form.toggoff'}) || ($ENV{'form.toggon'}) ) { +# ------------------------------ Modify setting for read/unread toggle for each post + my $symb=$ENV{'form.toggoff'}?$ENV{'form.toggoff'}:$ENV{'form.toggon'}; + my $ressymb = $symb; + ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb); + unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) { + $ressymb=~s|(bulletin___\d+___)|$1adm/wrapper|; + } + my %discinfo = (); + my $toggkey = $ressymb.'_readtoggle'; + if ($ENV{'form.toggon'}) { + $discinfo{$toggkey} = 1; + } elsif ($ENV{'form.toggoff'}) { + $discinfo{$toggkey} = 0; + } + &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',\%discinfo,$ENV{'user.domain'},$ENV{'user.name'}); + } if (($ENV{'form.markondisp'}) || ($ENV{'form.markonread'})) { # ---------------------- Modify setting for identification of 'NEW' posts in this discussion my $symb=$ENV{'form.markondisp'}?$ENV{'form.markondisp'}:$ENV{'form.markonread'}; @@ -1222,9 +2981,16 @@ ENDREDIR } &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',\%discinfo,$ENV{'user.domain'},$ENV{'user.name'}); } - if (($ENV{'form.allposts'}) || ($ENV{'form.onlyunread'})) { + if (($ENV{'form.allposts'}) || ($ENV{'form.onlyunread'}) || ($ENV{'form.onlyunmark'}) ) { # ----------------------------------------------------------------- Modify display setting for this discussion - my $symb=$ENV{'form.allposts'}?$ENV{'form.allposts'}:$ENV{'form.onlyunread'}; + my $symb; + if ($ENV{'form.allposts'}) { + $symb = $ENV{'form.allposts'}; + } elsif ($ENV{'form.onlyunread'}) { + $symb = $ENV{'form.onlyunread'}; + } else { + $symb = $ENV{'form.onlyunmark'}; + } my $ressymb = $symb; ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb); unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) { @@ -1233,19 +2999,22 @@ ENDREDIR my %discinfo = (); if ($ENV{'form.allposts'}) { $discinfo{$ressymb.'_showonlyunread'} = 0; + $discinfo{$ressymb.'_showonlyunmark'} = 0; } elsif ($ENV{'form.onlyunread'}) { $discinfo{$ressymb.'_showonlyunread'} = 1; + } else { + $discinfo{$ressymb.'_showonlyunmark'} = 1; } &Apache::lonnet::put('nohist_'.$ENV{'request.course.id'}.'_discuss',\%discinfo,$ENV{'user.domain'},$ENV{'user.name'}); } - if (($ENV{'form.markonread'}) || ($ENV{'form.allposts'}) || ($ENV{'form.onlyunread'}) ) { + if (($ENV{'form.markonread'}) || ($ENV{'form.allposts'}) || ($ENV{'form.onlyunread'}) || ($ENV{'form.onlyunmark'}) ||($ENV{'form.toggoff'}) || ($ENV{'form.toggon'}) ) { &redirect_back($r,&Apache::lonnet::clutter($url),&mt('Changed display status').'
','0','0','',$previous); } else { &redirect_back($r,&Apache::lonnet::clutter($url),&mt('Changed display status').'
','0','0'); } return OK; } elsif ($ENV{'form.markread'}) { -# ----------------------------------------------------------------- Mark new posts as read +# ----------------------------------------------------------------- Mark new posts not NEW &Apache::loncommon::content_type($r,'text/html'); $r->send_http_header; my $symb=$ENV{'form.markread'}; @@ -1276,13 +3045,27 @@ ENDREDIR my $currenthidden=$contrib{'hidden'}; + my $currentstudenthidden=$contrib{'studenthidden'}; + + my $crs='/'.$ENV{'request.course.id'}; + if ($ENV{'request.course.sec'}) { + $crs.='_'.$ENV{'request.course.sec'}; + } + $crs=~s/\_/\//g; + my $seeid=&Apache::lonnet::allowed('rin',$crs); if ($ENV{'form.hide'}) { $currenthidden.='.'.$idx.'.'; + unless ($seeid) { + $currentstudenthidden.='.'.$idx.'.'; + } } else { $currenthidden=~s/\.$idx\.//g; } my %newhash=('hidden' => $currenthidden); + if ( ($ENV{'form.hide'}) && (!$seeid) ) { + $newhash{'studenthidden'} = $currentstudenthidden; + } &Apache::lonnet::store(\%newhash,$symb,$ENV{'request.course.id'}, $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}, @@ -1336,6 +3119,60 @@ ENDREDIR $r->content_type('text/html'); $r->send_http_header; &show_preview($r); + } elsif ($ENV{'form.attach'}) { +# -------------------------------------------------------- Work on attachments + &Apache::loncommon::content_type($r,'text/html'); + $r->send_http_header; + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['subject','comment','addnewattach','delnewattach','timestamp','numoldver','idx','anondiscuss','discuss']); + my @currnewattach = (); + my @currdelold = (); + my @keepold = (); + &process_attachments(\@currnewattach,\@currdelold,\@keepold); + if (exists($ENV{'form.addnewattach.filename'})) { + unless (length($ENV{'form.addnewattach'})>131072) { + my $subdir = 'feedback/'.$ENV{'form.timestamp'}; + my $newattachment=&Apache::lonnet::userfileupload('addnewattach',undef,$subdir); + push @currnewattach, $newattachment; + } + } + my $attachmenturls = ''; + my $idx = $ENV{'form.idx'}; + my $symb = $ENV{'form.attach'}; + if ($idx) { + my %contrib=&Apache::lonnet::restore($symb,$ENV{'request.course.id'}, + $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}, + $ENV{'course.'.$ENV{'request.course.id'}.'.num'}); + $attachmenturls = $contrib{$idx.':attachmenturl'}; + } + &modify_attachments($r,\@currnewattach,\@currdelold,$symb,$idx,$attachmenturls); + } elsif ($ENV{'form.chgreads'}) { + &Apache::loncommon::content_type($r,'text/html'); + $r->send_http_header; + my ($map,$ind,$url)=&Apache::lonnet::decode_symb($ENV{'form.chgreads'}); + &redirect_back($r,&Apache::lonnet::clutter($url), + &mt('Changed read status').'
','0','0'); + } elsif ($ENV{'form.export'}) { + &Apache::loncommon::content_type($r,'text/html'); + $r->send_http_header; + my $symb=$ENV{'form.export'}; + my $mode; + my $status='OPEN'; + my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb); + my $previous=$ENV{'form.previous'}; + my $feedurl = &Apache::lonnet::clutter($url); + # backward compatibility (bulletin boards used to be 'wrapped') + if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) { + $mode = 'board'; + $feedurl=~s|^/adm/wrapper||; + } + if ($feedurl =~ /\.(problem|exam|quiz|assess|survey|form|library)$/) { + $mode='problem'; + $status=$Apache::inputtags::status[-1]; + } + my $discussion = &list_discussion($mode,$status,$symb); + my $bodytag=&Apache::loncommon::bodytag('Resource Feedback and Discussion'); + $r->print($bodytag.$discussion); + return OK; } else { # ------------------------------------------------------------- Normal feedback my $feedurl=$ENV{'form.postdata'}; @@ -1349,6 +3186,12 @@ ENDREDIR $symb=(split(/\:\:\:/,$ENV{'form.replydisc'}))[0]; my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb); $feedurl=&Apache::lonnet::clutter($url); + } elsif ($ENV{'form.editdisc'}) { + $symb=(split(/\:\:\:/,$ENV{'form.editdisc'}))[0]; + my ($map,$id,$url)=&Apache::lonnet::decode_symb($symb); + $feedurl=&Apache::lonnet::clutter($url); + } elsif ($ENV{'form.origpage'}) { + $symb=""; } else { $symb=&Apache::lonnet::symbread($feedurl); } @@ -1385,7 +3228,7 @@ ENDREDIR unless ($ENV{'form.sendit'}) { my $options=&screen_header($feedurl); if ($options) { - &mail_screen($r,$feedurl,$options); + &mail_screen($r,$feedurl,$options); } else { &fail_redirect($r,$feedurl); } @@ -1407,7 +3250,22 @@ ENDREDIR &Apache::lonnet::delenv('allowed.vgr'); # Get attachments, if any, and not too large my $attachmenturl=''; - if ($ENV{'form.attachment.filename'}) { + if (($ENV{'form.origpage'}) || ($ENV{'form.editdisc'}) || ($ENV{'form.replydisc'})) { + my ($symb,$idx); + if ($ENV{'form.replydisc'}) { + ($symb,$idx)=split(/\:\:\:/,$ENV{'form.replydisc'}); + } elsif ($ENV{'form.editdisc'}) { + ($symb,$idx)=split(/\:\:\:/,$ENV{'form.editdisc'}); + } elsif ($ENV{'form.origpage'}) { + $symb = $ENV{'form.symb'}; + } + my @currnewattach = (); + my @deloldattach = (); + my @keepold = (); + &process_attachments(\@currnewattach,\@deloldattach,\@keepold); + $symb=~s|(bulletin___\d+___)adm/wrapper/|$1|; + $attachmenturl=&construct_attachmenturl(\@currnewattach,\@keepold,$symb,$idx); + } elsif ($ENV{'form.attachment.filename'}) { unless (length($ENV{'form.attachment'})>131072) { $attachmenturl=&Apache::lonnet::userfileupload('attachment',undef,'feedback'); } 500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.