--- loncom/interface/londocs.pm 2004/05/11 06:37:39 1.127
+++ loncom/interface/londocs.pm 2013/01/09 17:22:51 1.530
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Documents
#
-# $Id: londocs.pm,v 1.127 2004/05/11 06:37:39 albertel Exp $
+# $Id: londocs.pm,v 1.530 2013/01/09 17:22:51 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -30,15 +30,23 @@ package Apache::londocs;
use strict;
use Apache::Constants qw(:common :http);
+use Apache::imsexport;
use Apache::lonnet;
use Apache::loncommon;
-use Apache::lonratedt;
-use Apache::lonratsrv;
+use Apache::lonhtmlcommon;
+use LONCAPA::map();
+use Apache::lonratedt();
use Apache::lonxml;
-use Apache::loncreatecourse;
+use Apache::lonclonecourse;
+use Apache::lonnavmaps;
+use Apache::lonnavdisplay();
+use Apache::lonextresedit();
use HTML::Entities;
+use HTML::TokeParser;
use GDBM_File;
use Apache::lonlocal;
+use Cwd;
+use LONCAPA qw(:DEFAULT :match);
my $iconpath;
@@ -49,618 +57,2616 @@ my %alreadyseen=();
my $hadchanges;
-# Available help topics
my %help=();
-# Mapread read maps into lonratedt::global arrays
-# @order and @resources, determines status
-# sets @order - pointer to resources in right order
-# sets @resources - array with the resources with correct idx
-#
sub mapread {
my ($coursenum,$coursedom,$map)=@_;
return
- &Apache::lonratedt::mapread('/uploaded/'.$coursedom.'/'.$coursenum.'/'.
- $map);
+ &LONCAPA::map::mapread('/uploaded/'.$coursedom.'/'.$coursenum.'/'.
+ $map);
}
sub storemap {
- my ($coursenum,$coursedom,$map)=@_;
+ my ($coursenum,$coursedom,$map,$contentchg)=@_;
+ my $report;
+ if (($contentchg) && ($map =~ /^default/)) {
+ $report = 1;
+ }
my ($outtext,$errtext)=
- &Apache::lonratedt::storemap('/uploaded/'.$coursedom.'/'.$coursenum.'/'.
- $map,1);
+ &LONCAPA::map::storemap('/uploaded/'.$coursedom.'/'.$coursenum.'/'.
+ $map,1,$report);
if ($errtext) { return ($errtext,2); }
-
+
$hadchanges=1;
return ($errtext,0);
}
-# ----------------------------------------- Return hash with valid author names
+
sub authorhosts {
my %outhash=();
my $home=0;
my $other=0;
- foreach (keys %ENV) {
- if ($_=~/^user\.role\.(au|ca)\.(.+)$/) {
+ foreach my $key (keys(%env)) {
+ if ($key=~/^user\.role\.(au|ca)\.(.+)$/) {
my $role=$1;
my $realm=$2;
- my ($start,$end)=split(/\./,$ENV{$_});
+ my ($start,$end)=split(/\./,$env{$key});
if (($start) && ($start>time)) { next; }
if (($end) && (time>$end)) { next; }
- my $ca; my $cd;
+ my ($ca,$cd);
if ($1 eq 'au') {
- $ca=$ENV{'user.name'};
- $cd=$ENV{'user.domain'};
+ $ca=$env{'user.name'};
+ $cd=$env{'user.domain'};
} else {
- ($cd,$ca)=($realm=~/^\/(\w+)\/(\w+)$/);
+ ($cd,$ca)=($realm=~/^\/($match_domain)\/($match_username)$/);
}
my $allowed=0;
my $myhome=&Apache::lonnet::homeserver($ca,$cd);
my @ids=&Apache::lonnet::current_machine_ids();
- foreach my $id (@ids) { if ($id eq $myhome) { $allowed=1; } }
+ foreach my $id (@ids) {
+ if ($id eq $myhome) {
+ $allowed=1;
+ last;
+ }
+ }
if ($allowed) {
$home++;
- $outhash{'home_'.$ca.'@'.$cd}=1;
+ $outhash{'home_'.$ca.':'.$cd}=1;
} else {
- $outhash{'otherhome_'.$ca.'@'.$cd}=$myhome;
+ $outhash{'otherhome_'.$ca.':'.$cd}=$myhome;
$other++;
}
}
}
return ($home,$other,%outhash);
}
-# ------------------------------------------------------ Generate "dump" button
-sub dumpbutton {
- my ($home,$other,%outhash)=&authorhosts();
- if ($home+$other==0) { return ''; }
- my $output='
';
- if ($home) {
- return ' '.
- ' ';
- } else {
- return' '.
- &mt('Dump Course DOCS to Construction Space: available on other servers');
- }
+
+sub clean {
+ my ($title)=@_;
+ $title=~s/[^\w\/\!\$\%\^\*\-\_\=\+\;\:\,\\\|\`\~]+/\_/gs;
+ return $title;
}
-# -------------------------------------------------------- Actually dump course
+
sub dumpcourse {
- my $r=shift;
- $r->print('Dump DOCS '.
- &Apache::loncommon::bodytag('Dump Course DOCS to Construction Space').
- '');
+ '
');
}
+ $r->print(&endContentScreen());
}
-
-# Imports the given (name, url) resources into the course
-# coursenum, coursedom, and folder must precede the list
sub group_import {
- my $coursenum = shift;
- my $coursedom = shift;
- my $folder = shift;
- while (@_) {
- my $name = shift;
- my $url = shift;
+ my ($coursenum, $coursedom, $folder, $container, $caller, @files) = @_;
+ my ($donechk,$allmaps,%hierarchy,%titles,%addedmaps,%removefrommap,
+ %removeparam,$importuploaded,$fixuperrors);
+ $allmaps = {};
+ while (@files) {
+ my ($name, $url, $residx) = @{ shift(@files) };
+ if (($url =~ m{^/uploaded/\Q$coursedom\E/\Q$coursenum\E/(default_\d+\.)(page|sequence)$})
+ && ($caller eq 'londocs')
+ && (!&Apache::lonnet::stat_file($url))) {
+
+ my $errtext = '';
+ my $fatal = 0;
+ my $newmapstr = ''."\n".
+ ' '."\n".
+ ' '."\n".
+ ' '."\n".
+ ' ';
+ $env{'form.output'}=$newmapstr;
+ my $result=&Apache::lonnet::finishuserfileupload($coursenum,$coursedom,
+ 'output',$1.$2);
+ if ($result != m|^/uploaded/|) {
+ $errtext.='Map not saved: A network error occurred when trying to save the new map. ';
+ $fatal = 2;
+ }
+ if ($fatal) {
+ return ($errtext,$fatal);
+ }
+ }
if ($url) {
- my $idx = $#Apache::lonratedt::resources + 1;
- $Apache::lonratedt::order[$#Apache::lonratedt::order+1]=$idx;
+ if (($caller eq 'londocs') &&
+ ($folder =~ /^default/)) {
+ unless ($donechk) {
+ my $chome = &Apache::lonnet::homeserver($coursenum,$coursedom);
+ my $cid = $coursedom.'_'.$coursenum;
+ $allmaps =
+ &Apache::loncommon::allmaps_incourse($coursedom,$coursenum,
+ $chome,$cid);
+ $donechk = 1;
+ }
+ if ($url =~ m{^/uploaded/\Q$coursedom\E/\Q$coursenum\E/(default_\d+\.)(page|sequence)$}) {
+ &contained_map_check($url,$folder,\%removefrommap,\%removeparam,
+ \%addedmaps,\%hierarchy,\%titles,$allmaps);
+ $importuploaded = 1;
+ } elsif ($url =~ m{^/res/.+\.(page|sequence)$}) {
+ next if ($allmaps->{$url});
+ }
+ }
+ if (!$residx
+ || defined($LONCAPA::map::zombies[$residx])) {
+ $residx = &LONCAPA::map::getresidx($url,$residx);
+ push(@LONCAPA::map::order, $residx);
+ }
my $ext = 'false';
- if ($url=~/^http:\/\//) { $ext = 'true'; }
- $url =~ s/:/\:/g;
- $name =~ s/:/\:/g;
- $Apache::lonratedt::resources[$idx] =
- join ':', ($name, $url, $ext, 'normal', 'res');
+ if ($url=~m{^http://} || $url=~m{^https://}) { $ext = 'true'; }
+ $url = &LONCAPA::map::qtunescape($url);
+ $name = &LONCAPA::map::qtunescape($name);
+ $LONCAPA::map::resources[$residx] =
+ join(':', ($name, $url, $ext, 'normal', 'res'));
}
}
- return &storemap($coursenum, $coursedom, $folder.'.sequence');
+ if ($importuploaded) {
+ my %import_errors;
+ my %updated = (
+ removefrommap => \%removefrommap,
+ removeparam => \%removeparam,
+ );
+ &apply_fixups($folder,1,$coursedom,$coursenum,\%import_errors,\%updated);
+ if (keys(%import_errors) > 0) {
+ $fixuperrors =
+ ''."\n".
+ &mt('The following files are either dependencies of a web page or references within a folder and/or composite page for which errors occurred during import:')."\n".
+ '
'."\n";
+ foreach my $key (sort(keys(%import_errors))) {
+ $fixuperrors .= ''.$key.' '."\n";
+ }
+ $fixuperrors .= ' '."\n";
+ }
+ }
+ my ($errtext,$fatal) =
+ &storemap($coursenum, $coursedom, $folder.'.'.$container,1);
+ return ($errtext,$fatal,$fixuperrors);
}
-sub breadcrumbs {
- my ($where)=@_;
- &Apache::lonhtmlcommon::clear_breadcrumbs();
- my (@folders)=split('&',$ENV{'form.folderpath'});
- my $folderpath;
- while (@folders) {
- my $folder=shift(@folders);
- my $foldername=shift(@folders);
- if ($folderpath) {$folderpath.='&';}
- $folderpath.=$folder.'&'.$foldername;
- my $url='/adm/coursedocs?folderpath='.
- &Apache::lonnet::escape($folderpath);
- &Apache::lonhtmlcommon::add_breadcrumb(
- {'href'=>$url,
- 'title'=>&Apache::lonnet::unescape($foldername),
- 'text'=>''.
- &Apache::lonnet::unescape($foldername).' '
- });
-
-
+sub log_docs {
+ return &Apache::lonnet::write_log('course','docslog',@_);
+}
+
+{
+ my @oldresources=();
+ my @oldorder=();
+ my $parmidx;
+ my %parmaction=();
+ my %parmvalue=();
+ my $changedflag;
+
+ sub snapshotbefore {
+ @oldresources=@LONCAPA::map::resources;
+ @oldorder=@LONCAPA::map::order;
+ $parmidx=undef;
+ %parmaction=();
+ %parmvalue=();
+ $changedflag=0;
+ }
+
+ sub remember_parms {
+ my ($idx,$parameter,$action,$value)=@_;
+ $parmidx=$idx;
+ $parmaction{$parameter}=$action;
+ $parmvalue{$parameter}=$value;
+ $changedflag=1;
+ }
+
+ sub log_differences {
+ my ($plain)=@_;
+ my %storehash=('folder' => $plain,
+ 'currentfolder' => $env{'form.folder'});
+ if ($parmidx) {
+ $storehash{'parameter_res'}=$oldresources[$parmidx];
+ foreach my $parm (keys(%parmaction)) {
+ $storehash{'parameter_action_'.$parm}=$parmaction{$parm};
+ $storehash{'parameter_value_'.$parm}=$parmvalue{$parm};
+ }
+ }
+ my $maxidx=$#oldresources;
+ if ($#LONCAPA::map::resources>$#oldresources) {
+ $maxidx=$#LONCAPA::map::resources;
+ }
+ for (my $idx=0; $idx<=$maxidx; $idx++) {
+ if ($LONCAPA::map::resources[$idx] ne $oldresources[$idx]) {
+ $storehash{'before_resources_'.$idx}=$oldresources[$idx];
+ $storehash{'after_resources_'.$idx}=$LONCAPA::map::resources[$idx];
+ $changedflag=1;
+ }
+ if ($LONCAPA::map::order[$idx] ne $oldorder[$idx]) {
+ $storehash{'before_order_res_'.$idx}=$oldresources[$oldorder[$idx]];
+ $storehash{'after_order_res_'.$idx}=$LONCAPA::map::resources[$LONCAPA::map::order[$idx]];
+ $changedflag=1;
+ }
+ }
+ $storehash{'maxidx'}=$maxidx;
+ if ($changedflag) { &log_docs(\%storehash); }
}
- return &Apache::lonhtmlcommon::breadcrumbs(undef,undef,undef,undef,undef,0);
}
-sub editor {
- my ($r,$coursenum,$coursedom,$folder,$allowed)=@_;
+sub docs_change_log {
+ my ($r,$coursenum,$coursedom,$folder,$allowed,$crstype,$iconpath)=@_;
+ my $supplementalflag=($env{'form.folderpath'}=~/^supplemental/);
+ my $js = ''."\n";
+ $r->print(&Apache::loncommon::start_page('Content Change Log',$js));
+ $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content Change Log'));
+ $r->print(&startContentScreen(($supplementalflag?'suppdocs':'docs')));
+ my %orderhash;
+ my $container='sequence';
+ my $pathitem;
+ if ($env{'form.folderpath'} =~ /\:1$/) {
+ $container='page';
+ }
+ my $folderpath=$env{'form.folderpath'};
+ if ($folderpath eq '') {
+ $folderpath = 'default&'.&escape(&mt('Main '.$crstype.' Documents').':::::');
+ }
+ $pathitem = ' ';
+ my $readfile="/uploaded/$coursedom/$coursenum/$folder.$container";
+ my $jumpto = $readfile;
+ $jumpto =~ s{^/}{};
+ my $tid = 1;
+ if ($supplementalflag) {
+ $tid = 2;
+ }
+ my ($breadcrumbtrail) =
+ &Apache::lonhtmlcommon::docs_breadcrumbs($allowed,$crstype,1);
+ $r->print($breadcrumbtrail.
+ &generate_edit_table($tid,\%orderhash,undef,$iconpath,$jumpto,
+ $readfile));
+ my %docslog=&Apache::lonnet::dump('nohist_docslog',
+ $env{'course.'.$env{'request.course.id'}.'.domain'},
+ $env{'course.'.$env{'request.course.id'}.'.num'});
+
+ if ((keys(%docslog))[0]=~/^error\:/) { undef(%docslog); }
+
+ my %saveable_parameters = ('show' => 'scalar',);
+ &Apache::loncommon::store_course_settings('docs_log',
+ \%saveable_parameters);
+ &Apache::loncommon::restore_course_settings('docs_log',
+ \%saveable_parameters);
+ if (!$env{'form.show'}) { $env{'form.show'}=10; }
+# FIXME: internationalization seems wrong here
+ my %lt=('hiddenresource' => 'Resources hidden',
+ 'encrypturl' => 'URL hidden',
+ 'randompick' => 'Randomly pick',
+ 'randomorder' => 'Randomly ordered',
+ 'set' => 'set to',
+ 'del' => 'deleted');
+ my $filter = &Apache::loncommon::display_filter('docslog')."\n".
+ $pathitem."\n".
+ ' '.
+ (' 'x2).' ';
+ $r->print(''.
+ '
'.&mt('Display of Content Changes').' '."\n".
+ &makedocslogform($filter,1).
+ ' ');
+ $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
+ ' '.&mt('Time').' '.&mt('User').' '.&mt('Folder').' '.&mt('Before').' '.
+ &mt('After').' '.
+ &Apache::loncommon::end_data_table_header_row());
+ my $shown=0;
+ foreach my $id (sort { $docslog{$b}{'exe_time'}<=>$docslog{$a}{'exe_time'} } (keys(%docslog))) {
+ if ($env{'form.displayfilter'} eq 'currentfolder') {
+ if ($docslog{$id}{'logentry'}{'currentfolder'} ne $folder) { next; }
+ }
+ my @changes=keys(%{$docslog{$id}{'logentry'}});
+ if ($env{'form.displayfilter'} eq 'containing') {
+ my $wholeentry=$docslog{$id}{'exe_uname'}.':'.$docslog{$id}{'exe_udom'}.':'.
+ &Apache::loncommon::plainname($docslog{$id}{'exe_uname'},$docslog{$id}{'exe_udom'});
+ foreach my $key (@changes) {
+ $wholeentry.=':'.$docslog{$id}{'logentry'}{$key};
+ }
+ if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
+ }
+ my $count = 0;
+ my $time =
+ &Apache::lonlocal::locallocaltime($docslog{$id}{'exe_time'});
+ my $plainname =
+ &Apache::loncommon::plainname($docslog{$id}{'exe_uname'},
+ $docslog{$id}{'exe_udom'});
+ my $about_me_link =
+ &Apache::loncommon::aboutmewrapper($plainname,
+ $docslog{$id}{'exe_uname'},
+ $docslog{$id}{'exe_udom'});
+ my $send_msg_link='';
+ if ((($docslog{$id}{'exe_uname'} ne $env{'user.name'})
+ || ($docslog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
+ $send_msg_link =' '.
+ &Apache::loncommon::messagewrapper(&mt('Send message'),
+ $docslog{$id}{'exe_uname'},
+ $docslog{$id}{'exe_udom'});
+ }
+ $r->print(&Apache::loncommon::start_data_table_row());
+ $r->print(''.$time.'
+ '.$about_me_link.
+ ''.$docslog{$id}{'exe_uname'}.
+ ':'.$docslog{$id}{'exe_udom'}.' '.
+ $send_msg_link.' '.
+ $docslog{$id}{'logentry'}{'folder'}.' ');
+ my $is_supp = 0;
+ if ($docslog{$id}{'logentry'}{'currentfolder'} =~ /^supplemental/) {
+ $is_supp = 1;
+ }
+# Before
+ for (my $idx=0;$idx<=$docslog{$id}{'logentry'}{'maxidx'};$idx++) {
+ my $oldname=(split(/\:/,$docslog{$id}{'logentry'}{'before_resources_'.$idx}))[0];
+ my $newname=(split(/\:/,$docslog{$id}{'logentry'}{'after_resources_'.$idx}))[0];
+ if ($oldname ne $newname) {
+ my $shown = &LONCAPA::map::qtescape($oldname);
+ if ($is_supp) {
+ $shown = &Apache::loncommon::parse_supplemental_title($shown);
+ }
+ $r->print($shown);
+ }
+ }
+ $r->print('');
+ for (my $idx=0;$idx<=$docslog{$id}{'logentry'}{'maxidx'};$idx++) {
+ if ($docslog{$id}{'logentry'}{'before_order_res_'.$idx}) {
+ my $shown = &LONCAPA::map::qtescape((split(/\:/,$docslog{$id}{'logentry'}{'before_order_res_'.$idx}))[0]);
+ if ($is_supp) {
+ $shown = &Apache::loncommon::parse_supplemental_title($shown);
+ }
+ $r->print(''.$shown.' ');
+ }
+ }
+ $r->print(' ');
+# After
+ $r->print(' ');
+
+ for (my $idx=0;$idx<=$docslog{$id}{'logentry'}{'maxidx'};$idx++) {
+ my $oldname=(split(/\:/,$docslog{$id}{'logentry'}{'before_resources_'.$idx}))[0];
+ my $newname=(split(/\:/,$docslog{$id}{'logentry'}{'after_resources_'.$idx}))[0];
+ if ($oldname ne '' && $oldname ne $newname) {
+ my $shown = &LONCAPA::map::qtescape($newname);
+ if ($is_supp) {
+ $shown = &Apache::loncommon::parse_supplemental_title(&LONCAPA::map::qtescape($newname));
+ }
+ $r->print($shown);
+ }
+ }
+ $r->print('');
+ for (my $idx=0;$idx<=$docslog{$id}{'logentry'}{'maxidx'};$idx++) {
+ if ($docslog{$id}{'logentry'}{'after_order_res_'.$idx}) {
+ my $shown = &LONCAPA::map::qtescape((split(/\:/,$docslog{$id}{'logentry'}{'after_order_res_'.$idx}))[0]);
+ if ($is_supp) {
+ $shown = &Apache::loncommon::parse_supplemental_title($shown);
+ }
+ $r->print(''.$shown.' ');
+ }
+ }
+ $r->print(' ');
+ if ($docslog{$id}{'logentry'}{'parameter_res'}) {
+ $r->print(&LONCAPA::map::qtescape((split(/\:/,$docslog{$id}{'logentry'}{'parameter_res'}))[0]).':');
+ foreach my $parameter ('randompick','hiddenresource','encrypturl','randomorder') {
+ if ($docslog{$id}{'logentry'}{'parameter_action_'.$parameter}) {
+# FIXME: internationalization seems wrong here
+ $r->print(''.
+ &mt($lt{$parameter}.' '.$lt{$docslog{$id}{'logentry'}{'parameter_action_'.$parameter}}.' [_1]',
+ $docslog{$id}{'logentry'}{'parameter_value_'.$parameter})
+ .' ');
+ }
+ }
+ $r->print(' ');
+ }
+# End
+ $r->print(' '.&Apache::loncommon::end_data_table_row());
+ $shown++;
+ if (!($env{'form.show'} eq &mt('all')
+ || $shown<=$env{'form.show'})) { last; }
+ }
+ $r->print(&Apache::loncommon::end_data_table()."\n".
+ &makesimpleeditform($pathitem)."\n".
+ '');
+ $r->print(&endContentScreen());
+}
- $r->print(&breadcrumbs($folder));
- my $errtext='';
- my $fatal=0;
- ($errtext,$fatal)=
- &mapread($coursenum,$coursedom,$folder.'.sequence');
- if ($#Apache::lonratedt::order<1) {
- $Apache::lonratedt::order[0]=1;
- $Apache::lonratedt::resources[1]='';
+sub update_paste_buffer {
+ my ($coursenum,$coursedom,$folder) = @_;
+
+ return if (!defined($env{'form.markcopy'}));
+ return if (!defined($env{'form.copyfolder'}));
+ return if ($env{'form.markcopy'} < 0);
+
+ my ($errtext,$fatal) = &mapread($coursenum,$coursedom,
+ $env{'form.copyfolder'});
+
+ return if ($fatal);
+
+# Mark for copying
+ my ($title,$url)=split(':',$LONCAPA::map::resources[$LONCAPA::map::order[$env{'form.markcopy'}]]);
+ if (&is_supplemental_title($title)) {
+ &Apache::lonnet::appenv({'docs.markedcopy_supplemental' => $title});
+ ($title) = &Apache::loncommon::parse_supplemental_title($title);
+ } elsif ($env{'docs.markedcopy_supplemental'}) {
+ &Apache::lonnet::delenv('docs.markedcopy_supplemental');
}
- if ($fatal) {
- $r->print(''.$errtext.'
');
+ $url=~s{http(:|:)//https(:|:)//}{https$2//};
+
+ (my $cmd,undef)=split('_',$env{'form.cmd'});
+
+ my %addtoenv = (
+ 'docs.markedcopy_title' => $title,
+ 'docs.markedcopy_url' => $url,
+ 'docs.markedcopy_cmd' => $cmd,
+ );
+ &Apache::lonnet::delenv('docs.markedcopy_nested');
+ &Apache::lonnet::delenv('docs.markedcopy_nestednames');
+ if ($url =~ m{^/uploaded/$match_domain/$match_courseid/(default|supplemental)_?(\d*)\.(page|sequence)$}) {
+ my $prefix = $1;
+ my $subdir =$2;
+ if ($subdir eq '') {
+ $subdir = $prefix;
+ }
+ my (%addedmaps,%removefrommap,%removeparam,%hierarchy,%titles,%allmaps);
+ &contained_map_check($url,$folder,\%removefrommap,\%removeparam,\%addedmaps,
+ \%hierarchy,\%titles,\%allmaps);
+ if (ref($hierarchy{$url}) eq 'HASH') {
+ my ($nested,$nestednames);
+ &recurse_uploaded_maps($url,$subdir,\%hierarchy,\%titles,\$nested,\$nestednames);
+ $nested =~ s/\&$//;
+ $nestednames =~ s/\Q___&&&___\E$//;
+ if ($nested ne '') {
+ $addtoenv{'docs.markedcopy_nested'} = $nested;
+ }
+ if ($nestednames ne '') {
+ $addtoenv{'docs.markedcopy_nestednames'} = $nestednames;
+ }
+ }
+ }
+ &Apache::lonnet::appenv(\%addtoenv);
+ delete($env{'form.markcopy'});
+}
+
+sub recurse_uploaded_maps {
+ my ($url,$dir,$hierarchy,$titlesref,$nestref,$namesref) = @_;
+ if (ref($hierarchy->{$url}) eq 'HASH') {
+ my @maps = map { $hierarchy->{$url}{$_}; } sort { $a <=> $b } (keys(%{$hierarchy->{$url}}));
+ my @titles = map { $titlesref->{$url}{$_}; } sort { $a <=> $b } (keys(%{$titlesref->{$url}}));
+ my (@uploaded,@names,%shorter);
+ for (my $i=0; $i<@maps; $i++) {
+ my ($inner) = ($maps[$i] =~ m{^/uploaded/$match_domain/$match_courseid/(?:default|supplemental)_(\d+)\.(?:page|sequence)$});
+ if ($inner ne '') {
+ push(@uploaded,$inner);
+ push(@names,&escape($titles[$i]));
+ $shorter{$maps[$i]} = $inner;
+ }
+ }
+ $$nestref .= "$dir:".join(',',@uploaded).'&';
+ $$namesref .= "$dir:".(join(',',@names)).'___&&&___';
+ foreach my $map (@maps) {
+ if ($shorter{$map} ne '') {
+ &recurse_uploaded_maps($map,$shorter{$map},$hierarchy,$titlesref,$nestref,$namesref);
+ }
+ }
+ }
+ return;
+}
+
+sub print_paste_buffer {
+ my ($r,$container,$folder,$coursedom,$coursenum) = @_;
+ return if (!defined($env{'docs.markedcopy_url'}));
+
+ my ($is_external,$othercourse,$fromsupp,$is_uploaded_map,$parent);
+ my $extension = (split(/\./,$env{'docs.markedcopy_url'}))[-1];
+ if ($env{'docs.markedcopy_url'} =~ m{^(?:/adm/wrapper/ext|(?:http|https)(?::|:))//} ) {
+ $is_external = 1;
+ }
+
+ my ($canpaste,$nopaste,$othercrs,$areachange);
+ if ($folder =~ /^supplemental/) {
+ $canpaste = &supp_pasteable($env{'docs.markedcopy_url'});
+ unless ($canpaste) {
+ $nopaste = &mt('Paste into Supplemental Content unavailable for this type of content.');
+ }
+ } else {
+ $canpaste = 1;
+ }
+
+ if ($canpaste) {
+ if ($env{'docs.markedcopy_url'} =~ m{^/uploaded/($match_domain)/($match_courseid)/(.+)$}) {
+ my $srcdom = $1;
+ my $srcnum = $2;
+ my $rem = $3;
+ if (($srcdom ne $coursedom) || ($srcnum ne $coursenum)) {
+ $othercourse = 1;
+ if ($env{"user.priv.cm./$srcdom/$srcnum"} =~ /\Q:mdc&F\E/) {
+ if ($canpaste) {
+ $othercrs = ' '.&mt('(from another course).');
+ }
+ } else {
+ $canpaste = 0;
+ $nopaste = &mt('Paste from another course unavailable.')
+ }
+ }
+ if ($rem =~ m{^(default|supplemental)_?(\d*)\.(?:page|sequence)$}) {
+ my $prefix = $1;
+ $parent = $2;
+ if ($folder !~ /^\Q$prefix\E/) {
+ $areachange = 1;
+ }
+ $is_uploaded_map = 1;
+ }
+ }
+ }
+
+ $r->print(''
+ .''.&mt('Clipboard').' ');
+ my ($type,$buffer);
+ if ($is_external) {
+ $type = &mt('External Resource');
+ $buffer = $type.': '.
+ &LONCAPA::map::qtescape($env{'docs.markedcopy_title'}).' ('.
+ &LONCAPA::map::qtescape($env{'docs.markedcopy_url'}).')';
+ } else {
+ my $icon = &Apache::loncommon::icon($extension);
+ if ($extension eq 'sequence' &&
+ $env{'docs.markedcopy_url'} =~ m{/default_\d+\.sequence$ }x) {
+ $icon = &Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL'));
+ $icon .= '/navmap.folder.closed.gif';
+ }
+ $icon = ' ';
+ $buffer = $icon.$type.': '. &Apache::loncommon::parse_supplemental_title(&LONCAPA::map::qtescape($env{'docs.markedcopy_title'}));
+ }
+ if ($canpaste) {
+ $r->print('');
+ } else {
+ $r->print(&mt('Paste buffer contains:').' '.$buffer.
+ ''.$nopaste.'
');
+ }
+ $r->print(' ');
+}
+
+sub recurse_print {
+ my ($r,$dir,$deps,$display) = @_;
+ $r->print($display->{$dir}."\n");
+ if (ref($deps->{$dir}) eq 'ARRAY') {
+ foreach my $subdir (@{$deps->{$dir}}) {
+ &recurse_print($r,$subdir,$deps,$display);
+ }
+ }
+}
+
+sub supp_pasteable {
+ my ($url) = @_;
+ if (($url =~ m{^(?:/adm/wrapper/ext|(?:http|https)(?::|:))//}) ||
+ (($url =~ /\.sequence$/) && ($url =~ m{^/uploaded/})) ||
+ ($url =~ m{^/uploaded/$match_domain/$match_courseid/(docs|supplemental)/(default|\d+)/\d+/}) ||
+ ($url =~ m{^/adm/$match_domain/$match_username/aboutme}) ||
+ ($url =~ m{^/public/$match_domain/$match_courseid/syllabus})) {
+ return 1;
+ }
+ return;
+}
+
+sub paste_popup_js {
+ my %lt = &Apache::lonlocal::texthash(
+ show => 'Show Paste Options',
+ hide => 'Hide Paste Options',
+ );
+ return <<"END";
+
+function showPasteOptions() {
+ document.getElementById('pasteoptions').style.display='block';
+ document.getElementById('pasteoptions').style.textAlign='left';
+ document.getElementById('pasteoptions').style.textFace='normal';
+ document.getElementById('pasteoptionstext').innerHTML =' ';
+ return;
+}
+
+function hidePasteOptions() {
+ document.getElementById('pasteoptions').style.display='none';
+ document.getElementById('pasteoptionstext').innerHTML ='';
+ return;
+}
+
+END
+
+}
+
+
+sub do_paste_from_buffer {
+ my ($coursenum,$coursedom,$folder,$container,$errors) = @_;
+
+# Early out if paste buffer is empty
+ if (!$env{'form.pastemarked'}) {
+ return ();
+ }
+
+# Supplemental content may only include certain types of content
+# Early out if pasted content is not supported in Supplemental area
+ if ($folder =~ /^supplemental/) {
+ unless (&supp_pasteable($env{'docs.markedcopy_url'})) {
+ return (&mt('Paste failed: content type is not supported within Supplemental Content'));
+ }
+ }
+
+# Prepare to paste resource at end of list
+ my $url=&LONCAPA::map::qtescape($env{'docs.markedcopy_url'});
+ my $title=&LONCAPA::map::qtescape($env{'docs.markedcopy_title'});
+
+ my ($is_map,$srcdom,$srcnum,$prefixchg,%before,%after,%mapchanges,%tomove);
+ if ($url=~/\.(page|sequence)$/) {
+ $is_map = 1;
+ }
+ if ($url =~ m{^/uploaded/($match_domain)/($match_courseid)/([^/]+)}) {
+ $srcdom = $1;
+ $srcnum = $2;
+ my $oldprefix = $3;
+# When paste buffer was populated using an active role in a different course
+# check for mdc privilege in the course from which the resource was pasted
+ if (($srcdom ne $coursedom) || ($srcnum ne $coursenum)) {
+ unless ($env{"user.priv.cm./$srcdom/$srcnum"} =~ /\Q:mdc&F\E/) {
+ return (&mt('Paste failed: Item is from a different course which you do not have rights to edit.'));
+ }
+ }
+# When pasting content from Main Content to Supplemental Content and vice versa
+# URLs will contain different paths (which depend on whether pasted item is
+# a folder/page or a document.
+ if (($folder =~ /^supplemental/) && (($oldprefix =~ /^default/) || ($oldprefix eq 'docs'))) {
+ $prefixchg = 1;
+ %before = ( map => 'default',
+ doc => 'docs');
+ %after = ( map => 'supplemental',
+ doc => 'supplemental' );
+ } elsif (($folder =~ /^default/) && ($oldprefix =~ /^supplemental/)) {
+ $prefixchg = 1;
+ %before = ( map => 'supplemental',
+ doc => 'supplemental');
+ %after = ( map => 'default',
+ doc => 'docs');
+ }
+
+# If pasting an uploaded map, get list of contained uploaded maps.
+ my @nested;
+ if ($env{'docs.markedcopy_nested'}) {
+ my ($type) = ($oldprefix =~ /^(default|supplemental)/);
+ my @items = split(/\&/,$env{'docs.markedcopy_nested'});
+ my @deps = map { /\d+:([\d,]+$)/ } @items;
+ foreach my $dep (@deps) {
+ if ($dep =~ /,/) {
+ push(@nested,split(/,/,$dep));
+ } else {
+ push(@nested,$dep);
+ }
+ }
+ foreach my $item (@nested) {
+ if ($env{'form.docs.markedcopy_'.$item} eq 'move') {
+ $tomove{$type.'_'.$item} = 1;
+ }
+ }
+ }
+ }
+
+# Maps need to be copied first
+ my ($oldurl,%removefrommap,%removeparam,%addedmaps,%rewrites,%retitles,%copies,
+ %dbcopies,%zombies,%params,%docmoves,%mapmoves,%newsubdir,%newurls);
+ $oldurl = $url;
+ if ($is_map) {
+# If pasting a map, check if map contains other maps
+ my ($allmaps,%hierarchy,%titles);
+ $allmaps = {};
+ if ($folder =~ /^default/) {
+ $allmaps =
+ &Apache::loncommon::allmaps_incourse($coursedom,$coursenum,
+ $env{"course.$env{'request.course.id'}.home"},
+ $env{'request.course.id'});
+ }
+ &contained_map_check($url,$folder,\%removefrommap,\%removeparam,
+ \%addedmaps,\%hierarchy,\%titles,$allmaps);
+ if ($url=~ m{^/uploaded/}) {
+ my $newurl;
+ unless ($env{'form.docs.markedcopy_options'} eq 'move') {
+ ($newurl,my $error) =
+ &get_newmap_url($url,$folder,$prefixchg,$coursedom,$coursenum,
+ $srcdom,$srcnum,\$title,$allmaps,\%newurls);
+ if ($error) {
+ return ($error);
+ }
+ if ($newurl ne '') {
+ if ($newurl ne $url) {
+ if ($newurl =~ /(?:default|supplemental)_(\d+).(?:sequence|page)$/) {
+ $newsubdir{$url} = $1;
+ }
+ $mapchanges{$url} = 1;
+ }
+ }
+ }
+ if (($srcdom ne $coursedom) || ($srcnum ne $coursenum) || ($prefixchg) ||
+ (($newurl ne '') && ($newurl ne $url))) {
+ unless (&url_paste_fixups($url,$folder,$prefixchg,$coursedom,$coursenum,
+ $allmaps,\%rewrites,\%retitles,\%copies,\%dbcopies,
+ \%zombies,\%params,\%mapmoves,\%mapchanges,\%tomove,
+ \%newsubdir,\%newurls)) {
+ $mapmoves{$url} = 1;
+ }
+ $url = $newurl;
+ } elsif ($env{'docs.markedcopy_nested'}) {
+ &url_paste_fixups($url,$folder,$prefixchg,$coursedom,$coursenum,$allmaps,\%rewrites,
+ \%retitles,\%copies,\%dbcopies,\%zombies,\%params,\%mapmoves,
+ \%mapchanges,\%tomove,\%newsubdir,\%newurls);
+ }
+ } elsif ($url=~m {^/res/}) {
+# published maps can only exists once, so remove it from paste buffer when done
+ &Apache::lonnet::delenv('docs.markedcopy');
+# if pasting published map (main content are only) check map is not already in course
+ if ($folder =~ /^default/) {
+ if ((ref($allmaps) eq 'HASH') && ($allmaps->{$url})) {
+ return (&mt('Paste failed: only one instance of a particular published sequence or page is allowed within each course.'));
+ }
+ }
+ }
+ }
+ if ($url=~ m{/smppg$}) {
+ my $db_name = &Apache::lonsimplepage::get_db_name($url);
+ if ($db_name =~ /^smppage_/) {
+ #simple pages, need to copy the db contents to a new one.
+ my %contents=&Apache::lonnet::dump($db_name,$coursedom,$coursenum);
+ my $now = time();
+ $db_name =~ s{_\d*$ }{_$now}x;
+ my $dbresult=&Apache::lonnet::put($db_name,\%contents,
+ $coursedom,$coursenum);
+ if ($dbresult eq 'ok') {
+ $url =~ s{/(\d*)/smppg$ }{/$now/smppg}x;
+ $title=&mt('Copy of').' '.$title;
+ } else {
+ return (&mt('Paste failed: An error occurred when copying the simple page.'));
+ }
+ }
+ }
+ $title = &LONCAPA::map::qtunescape($title);
+ my $ext='false';
+ if ($url=~m{^http(|s)://}) { $ext='true'; }
+ $url = &LONCAPA::map::qtunescape($url);
+
+# For uploaded files (excluding pages/sequences) path in copied file is changed
+# if paste is from Main to Supplemental (or vice versa), or if pasting between
+# courses.
+
+ my $newidx;
+ unless ($is_map) {
+# Now insert the URL at the bottom
+ $newidx = &LONCAPA::map::getresidx($url);
+ if ($url =~ m{^/uploaded/$match_domain/$match_courseid/(?:docs|supplemental)/(.+)$}) {
+ my $relpath = $1;
+ if ($relpath ne '') {
+ my ($prefix,$subdir,$rem) = ($relpath =~ m{^(default|\d+)/(\d+)/(.+)$});
+ my ($newloc,$newdocsdir) = ($folder =~ /^(default|supplemental)_?(\d*)/);
+ my $newprefix = $newloc;
+ if ($newloc eq 'default') {
+ $newprefix = 'docs';
+ }
+ if ($newdocsdir eq '') {
+ $newdocsdir = 'default';
+ }
+ if (($prefixchg) || ($srcdom ne $coursedom) || ($srcnum ne $coursenum)) {
+ my $newpath = "$newprefix/$newdocsdir/$newidx/$rem";
+ $url =
+ &Apache::lonclonecourse::writefile($env{'request.course.id'},$newpath,
+ &Apache::lonnet::getfile($oldurl));
+ if ($url eq '/adm/notfound.html') {
+ return (&mt('Paste failed: an error occurred saving the file.'));
+ } else {
+ my ($newsubpath) = ($newpath =~ m{^(.*/)[^/]*$});
+ $newsubpath =~ s{/+$}{/};
+ $docmoves{$oldurl} = $newsubpath;
+ }
+ }
+ }
+ }
+ }
+# Apply any changes to maps, or copy dependencies for uploaded HTML pages
+ my ($result,$save_err);
+ my %updated = (
+ rewrites => \%rewrites,
+ zombies => \%zombies,
+ removefrommap => \%removefrommap,
+ removeparam => \%removeparam,
+ dbcopies => \%dbcopies,
+ retitles => \%retitles,
+ );
+ my %info = (
+ newsubdir => \%newsubdir,
+ params => \%params,
+ before => \%before,
+ after => \%after,
+ );
+ my %moves = (
+ copies => \%copies,
+ docmoves => \%docmoves,
+ mapmoves => \%mapmoves,
+ );
+ $result =
+ &apply_fixups($folder,$is_map,$coursedom,$coursenum,$errors,
+ \%updated,\%info,\%moves,$prefixchg,$oldurl,$url,'paste');
+ if ($result eq 'ok') {
+ if ($is_map) {
+ my ($errtext,$fatal) = &mapread($coursenum,$coursedom,
+ $folder.'.'.$container);
+ return $errtext if ($fatal);
+
+ if ($#LONCAPA::map::order<1) {
+ my $idx=&LONCAPA::map::getresidx();
+ if ($idx<=0) { $idx=1; }
+ $LONCAPA::map::order[0]=$idx;
+ $LONCAPA::map::resources[$idx]='';
+ }
+ $newidx = &LONCAPA::map::getresidx($url);
+ }
+ if ($env{'docs.markedcopy_supplemental'}) {
+ if ($folder !~ /^supplemental/) {
+ (undef,undef,$title) =
+ &Apache::loncommon::parse_supplemental_title($env{'docs.markedcopy_supplemental'});
+ }
+ } else {
+ if ($folder=~/^supplemental/) {
+ $title=time.'___&&&___'.$env{'user.name'}.'___&&&___'.
+ $env{'user.domain'}.'___&&&___'.$title;
+ }
+ }
+ $LONCAPA::map::resources[$newidx]= $title.':'.$url.':'.$ext.':normal:res';
+ push(@LONCAPA::map::order, $newidx);
+
+# Store the result
+ my ($errtext,$fatal) =
+ &storemap($coursenum,$coursedom,$folder.'.'.$container,1);
+ if ($fatal) {
+ $save_err = $errtext;
+ }
+ }
+
+ if ($env{'form.docs.markedcopy_options'} eq 'move') {
+ &Apache::lonnet::delenv('docs.markedcopy');
+ &Apache::lonnet::delenv('docs.markedcopy_nested');
+ &Apache::lonnet::delenv('docs.markedcopy_nestednames');
+ }
+ return ($result,$save_err);
+}
+
+sub get_newmap_url {
+ my ($url,$folder,$prefixchg,$coursedom,$coursenum,$srcdom,$srcnum,
+ $titleref,$allmaps,$newurls) = @_;
+ my $newurl;
+ if ($url=~ m{^/uploaded/}) {
+ $$titleref=&mt('Copy of').' '.$$titleref;
+ }
+ my $now = time;
+ my $suffix=$$.int(rand(100)).$now;
+ my ($oldid,$ext) = ($url=~/^(.+)\.(\w+)$/);
+ if ($oldid =~ m{^(/uploaded/$match_domain/$match_courseid/)(\D+)(\d+)$}) {
+ my $path = $1;
+ my $prefix = $2;
+ my $ancestor = $3;
+ if (length($ancestor) > 10) {
+ $ancestor = substr($ancestor,-10,10);
+ }
+ my $newid;
+ if ($prefixchg) {
+ if ($folder =~ /^supplemental/) {
+ $prefix =~ s/^default/supplemental/;
+ } else {
+ $prefix =~ s/^supplemental/default/;
+ }
+ }
+ if (($srcdom eq $coursedom) && ($srcnum eq $coursenum)) {
+ $newurl = $path.$prefix.$ancestor.$suffix.'.'.$ext;
+ } else {
+ $newurl = "/uploaded/$coursedom/$coursenum/$prefix".$now.'.'.$ext;
+ }
+ my $counter = 0;
+ my $is_unique = &uniqueness_check($newurl);
+ if ($folder =~ /^default/) {
+ if ($allmaps->{$newurl}) {
+ $is_unique = 0;
+ }
+ }
+ while ((!$is_unique || $allmaps->{$newurl} || $newurls->{$newurl}) && ($counter < 100)) {
+ $counter ++;
+ $suffix ++;
+ if (($srcdom eq $coursedom) && ($srcnum eq $coursenum)) {
+ $newurl = $path.$prefix.$ancestor.$suffix.'.'.$ext;
+ } else {
+ $newurl = "/uploaded/$coursedom/$coursenum/$prefix".$ancestor.$suffix.'.'.$ext;
+ }
+ $is_unique = &uniqueness_check($newurl);
+ }
+ if ($is_unique) {
+ $newurls->{$newurl} = 1;
+ } else {
+ if ($url=~/\.page$/) {
+ return (undef,&mt('Paste failed: an error occurred creating a unique URL for the composite page'));
+ } else {
+ return (undef,&mt('Paste failed: an error occurred creating a unique URL for the folder'));
+ }
+ }
+ }
+ return ($newurl);
+}
+
+sub dbcopy {
+ my ($url,$coursedom,$coursenum) = @_;
+ if ($url=~ m{/smppg$}) {
+ my $db_name = &Apache::lonsimplepage::get_db_name($url);
+ if ($db_name =~ /^smppage_/) {
+ #simple pages, need to copy the db contents to a new one.
+ my %contents=&Apache::lonnet::dump($db_name,$coursedom,$coursenum);
+ my $now = time();
+ $db_name =~ s{_\d*$ }{_$now}x;
+ my $result=&Apache::lonnet::put($db_name,\%contents,
+ $coursedom,$coursenum);
+ $url =~ s{/(\d*)/smppg$ }{/$now/smppg}x;
+ }
+ }
+ return $url;
+}
+
+sub uniqueness_check {
+ my ($newurl) = @_;
+ my $unique = 1;
+ foreach my $res (@LONCAPA::map::order) {
+ my ($name,$url)=split(/\:/,$LONCAPA::map::resources[$res]);
+ $url=&LONCAPA::map::qtescape($url);
+ if ($newurl eq $url) {
+ $unique = 0;
+ last;
+ }
+ }
+ return $unique;
+}
+
+sub contained_map_check {
+ my ($url,$folder,$removefrommap,$removeparam,$addedmaps,$hierarchy,$titles,
+ $allmaps) = @_;
+ my $content = &Apache::lonnet::getfile($url);
+ unless ($content eq '-1') {
+ my $parser = HTML::TokeParser->new(\$content);
+ $parser->attr_encoded(1);
+ while (my $token = $parser->get_token) {
+ next if ($token->[0] ne 'S');
+ if ($token->[1] eq 'resource') {
+ next if ($token->[2]->{'type'} eq 'zombie');
+ my $ressrc = $token->[2]->{'src'};
+ if ($folder =~ /^supplemental/) {
+ unless (&supp_pasteable($ressrc)) {
+ $removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc;
+ next;
+ }
+ }
+ if ($ressrc =~ m{^/(res|uploaded)/.+\.(sequence|page)$}) {
+ if ($1 eq 'uploaded') {
+ $hierarchy->{$url}{$token->[2]->{'id'}} = $ressrc;
+ $titles->{$url}{$token->[2]->{'id'}} = $token->[2]->{'title'};
+ } else {
+ if ($allmaps->{$ressrc}) {
+ $removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc;
+ } elsif (ref($addedmaps->{$ressrc}) eq 'ARRAY') {
+ $removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc;
+ } else {
+ $addedmaps->{$ressrc} = [$url];
+ }
+ }
+ &contained_map_check($ressrc,$folder,$removefrommap,$removeparam,
+ $addedmaps,$hierarchy,$titles,$allmaps);
+ }
+ } elsif ($token->[1] eq 'param') {
+ if ($folder =~ /^supplemental/) {
+ if (ref($removeparam->{$url}{$token->[2]->{'to'}}) eq 'ARRAY') {
+ push(@{$removeparam->{$url}{$token->[2]->{'to'}}},$token->[2]->{'name'});
+ } else {
+ $removeparam->{$url}{$token->[2]->{'to'}} = [$token->[2]->{'name'}];
+ }
+ }
+ }
+ }
+ }
+ return;
+}
+
+sub url_paste_fixups {
+ my ($oldurl,$folder,$prefixchg,$cdom,$cnum,$allmaps,$rewrites,$retitles,$copies,
+ $dbcopies,$zombies,$params,$mapmoves,$mapchanges,$tomove,$newsubdir,$newurls) = @_;
+ my $checktitle;
+ if (($prefixchg) &&
+ ($oldurl =~ m{^/uploaded/$match_domain/$match_courseid/supplemental})) {
+ $checktitle = 1;
+ }
+ my $skip;
+ if ($oldurl =~ m{^\Q/uploaded/$cdom/$cnum/\E(default|supplemental)(_?\d*)\.(?:page|sequence)$}) {
+ my $mapid = $1.$2;
+ if ($tomove->{$mapid}) {
+ $skip = 1;
+ }
+ }
+ my $file = &Apache::lonnet::getfile($oldurl);
+ return if ($file eq '-1');
+ my $parser = HTML::TokeParser->new(\$file);
+ $parser->attr_encoded(1);
+ my $changed = 0;
+ while (my $token = $parser->get_token) {
+ next if ($token->[0] ne 'S');
+ if ($token->[1] eq 'resource') {
+ my $ressrc = $token->[2]->{'src'};
+ next if ($ressrc eq '');
+ my $id = $token->[2]->{'id'};
+ my $title = $token->[2]->{'title'};
+ if ($checktitle) {
+ if ($title =~ m{\d+\Q___&&&___\E$match_username\Q___&&&___\E$match_domain\Q___&&&___\E(.+)$}) {
+ $retitles->{$oldurl}{$ressrc} = $id;
+ }
+ }
+ next if ($token->[2]->{'type'} eq 'external');
+ if ($token->[2]->{'type'} eq 'zombie') {
+ next if ($skip);
+ $zombies->{$oldurl}{$ressrc} = $id;
+ $changed = 1;
+ } elsif ($ressrc =~ m{^/uploaded/($match_domain)/($match_courseid)/(.+)$}) {
+ my $srcdom = $1;
+ my $srcnum = $2;
+ my $rem = $3;
+ my $newurl;
+ my $mapname;
+ if ($rem =~ /^(default|supplemental)(_?\d*).(sequence|page)$/) {
+ my $prefix = $1;
+ $mapname = $prefix.$2;
+ if ($tomove->{$mapname}) {
+ &url_paste_fixups($ressrc,$folder,$prefixchg,$cdom,$cnum,$allmaps,
+ $rewrites,$retitles,$copies,$dbcopies,$zombies,
+ $params,$mapmoves,$mapchanges,$tomove,$newsubdir,
+ $newurls);
+ next;
+ } else {
+ ($newurl,my $error) =
+ &get_newmap_url($ressrc,$folder,$prefixchg,$cdom,$cnum,
+ $srcdom,$srcnum,\$title,$allmaps,$newurls);
+ if ($newurl =~ /(?:default|supplemental)_(\d+)\.(?:sequence|page)$/) {
+ $newsubdir->{$ressrc} = $1;
+ }
+ if ($error) {
+ next;
+ }
+ }
+ }
+ if (($srcdom ne $cdom) || ($srcnum ne $cnum) || ($prefixchg) ||
+ ($mapchanges->{$oldurl}) || (($newurl ne '') && ($newurl ne $oldurl))) {
+
+ if ($rem =~ /^(default|supplemental)(_?\d*).(sequence|page)$/) {
+ $rewrites->{$oldurl}{$ressrc} = $id;
+ $mapchanges->{$ressrc} = 1;
+ unless (&url_paste_fixups($ressrc,$folder,$prefixchg,$cdom,$cnum,$allmaps,
+ $rewrites,$retitles,$copies,$dbcopies,$zombies,
+ $params,$mapmoves,$mapchanges,$tomove,$newsubdir,
+ $newurls)) {
+ $mapmoves->{$ressrc} = 1;
+ }
+ $changed = 1;
+ } else {
+ $rewrites->{$oldurl}{$ressrc} = $id;
+ $copies->{$oldurl}{$ressrc} = $id;
+ $changed = 1;
+ }
+ }
+ } elsif ($ressrc =~ m{^/adm/($match_domain)/($match_courseid)/(.+)$}) {
+ next if ($skip);
+ my $srcdom = $1;
+ my $srcnum = $2;
+ if (($srcdom ne $cdom) || ($srcnum ne $cnum)) {
+ $rewrites->{$oldurl}{$ressrc} = $id;
+ $dbcopies->{$oldurl}{$ressrc} = $id;
+ $changed = 1;
+ }
+ } elsif ($ressrc =~ m{^/public/($match_domain)/($match_courseid)/(.+)$}) {
+ next if ($skip);
+ my $srcdom = $1;
+ my $srcnum = $2;
+ if (($srcdom ne $cdom) || ($srcnum ne $cnum)) {
+ $rewrites->{$oldurl}{$ressrc} = $id;
+ $dbcopies->{$oldurl}{$ressrc} = $id;
+ $changed = 1;
+ }
+ }
+ } elsif ($token->[1] eq 'param') {
+ next if ($skip);
+ my $to = $token->[2]->{'to'};
+ if ($to ne '') {
+ if (ref($params->{$oldurl}{$to}) eq 'ARRAY') {
+ push(@{$params->{$oldurl}{$to}},$token->[2]->{'name'});
+ } else {
+ @{$params->{$oldurl}{$to}} = ($token->[2]->{'name'});
+ }
+ }
+ }
+ }
+ return $changed;
+}
+
+sub apply_fixups {
+ my ($folder,$is_map,$cdom,$cnum,$errors,$updated,$info,$moves,$prefixchg,
+ $oldurl,$url,$caller) = @_;
+ my (%rewrites,%zombies,%removefrommap,%removeparam,%dbcopies,%retitles,
+ %params,%newsubdir,%before,%after,%copies,%docmoves,%mapmoves);
+ if (ref($updated) eq 'HASH') {
+ if (ref($updated->{'rewrites'}) eq 'HASH') {
+ %rewrites = %{$updated->{'rewrites'}};
+ }
+ if (ref($updated->{'zombies'}) eq 'HASH') {
+ %zombies = %{$updated->{'zombies'}};
+ }
+ if (ref($updated->{'removefrommap'}) eq 'HASH') {
+ %removefrommap = %{$updated->{'removefrommap'}};
+ }
+ if (ref($updated->{'removeparam'}) eq 'HASH') {
+ %removeparam = %{$updated->{'removeparam'}};
+ }
+ if (ref($updated->{'dbcopies'}) eq 'HASH') {
+ %dbcopies = %{$updated->{'dbcopies'}};
+ }
+ if (ref($updated->{'retitles'}) eq 'HASH') {
+ %retitles = %{$updated->{'retitles'}};
+ }
+ }
+ if (ref($info) eq 'HASH') {
+ if (ref($info->{'newsubdir'}) eq 'HASH') {
+ %newsubdir = %{$info->{'newsubdir'}};
+ }
+ if (ref($info->{'params'}) eq 'HASH') {
+ %params = %{$info->{'params'}};
+ }
+ if (ref($info->{'before'}) eq 'HASH') {
+ %before = %{$info->{'before'}};
+ }
+ if (ref($info->{'after'}) eq 'HASH') {
+ %after = %{$info->{'after'}};
+ }
+ }
+ if (ref($moves) eq 'HASH') {
+ if (ref($moves->{'copies'}) eq 'HASH') {
+ %copies = %{$moves->{'copies'}};
+ }
+ if (ref($moves->{'docmoves'}) eq 'HASH') {
+ %docmoves = %{$moves->{'docmoves'}};
+ }
+ if (ref($moves->{'mapmoves'}) eq 'HASH') {
+ %mapmoves = %{$moves->{'mapmoves'}};
+ }
+ }
+ foreach my $key (keys(%copies),keys(%docmoves)) {
+ my @allcopies;
+ if (exists($copies{$key})) {
+ if (ref($copies{$key}) eq 'HASH') {
+ my %added;
+ foreach my $innerkey (keys(%{$copies{$key}})) {
+ if (($innerkey ne '') && (!$added{$innerkey})) {
+ push(@allcopies,$innerkey);
+ $added{$innerkey} = 1;
+ }
+ }
+ undef(%added);
+ }
+ }
+ if ($key eq $oldurl) {
+ if ((exists($docmoves{$key}))) {
+ unless (grep(/^\Q$oldurl\E/,@allcopies)) {
+ push(@allcopies,$oldurl);
+ }
+ }
+ }
+ if (@allcopies > 0) {
+ foreach my $item (@allcopies) {
+ my ($relpath,$oldsubdir,$fname) =
+ ($item =~ m{^(/uploaded/$match_domain/$match_courseid/(?:docs|supplemental)/(default|\d+)/.*/)([^/]+)$});
+ if ($fname ne '') {
+ my $content = &Apache::lonnet::getfile($item);
+ unless ($content eq '-1') {
+ my $storefn;
+ if (($key eq $oldurl) && (exists($docmoves{$key}))) {
+ $storefn = $docmoves{$key};
+ } else {
+ $storefn = $relpath;
+ $storefn =~s{^/uploaded/$match_domain/$match_courseid/}{};
+ if ($prefixchg && $before{'doc'} && $after{'doc'}) {
+ $storefn =~ s/^\Q$before{'doc'}\E/$after{'doc'}/;
+ }
+ if ($newsubdir{$key}) {
+ $storefn =~ s#^(docs|supplemental)/\Q$oldsubdir\E/#$1/$newsubdir{$key}#;
+ }
+ }
+ ©_dependencies($item,$storefn,$relpath,$errors,\$content);
+ my $copyurl =
+ &Apache::lonclonecourse::writefile($env{'request.course.id'},
+ $storefn.$fname,$content);
+ if ($copyurl eq '/adm/notfound.html') {
+ if (exists($docmoves{$oldurl})) {
+ return &mt('Paste failed: an error occurred copying the file.');
+ } elsif (ref($errors) eq 'HASH') {
+ $errors->{$item} = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ foreach my $key (keys(%mapmoves)) {
+ my $storefn=$key;
+ $storefn=~s{^/uploaded/$match_domain/$match_courseid/}{};
+ if ($prefixchg && $before{'map'} && $after{'map'}) {
+ $storefn =~ s/^\Q$before{'map'}\E/$after{'map'}/;
+ }
+ if ($newsubdir{$key}) {
+ $storefn =~ s/^((?:default|supplemental)_)(\d+)/$1$newsubdir{$key}/;
+ }
+ my $mapcontent = &Apache::lonnet::getfile($key);
+ if ($mapcontent eq '-1') {
+ if (ref($errors) eq 'HASH') {
+ $errors->{$key} = 1;
+ }
+ } else {
+ my $newmap =
+ &Apache::lonclonecourse::writefile($env{'request.course.id'},$storefn,
+ $mapcontent);
+ if ($newmap eq '/adm/notfound.html') {
+ if (ref($errors) eq 'HASH') {
+ $errors->{$key} = 1;
+ }
+ }
+ }
+ }
+ my %updates;
+ if ($is_map) {
+ if (ref($updated) eq 'HASH') {
+ foreach my $type (keys(%{$updated})) {
+ if (ref($updated->{$type}) eq 'HASH') {
+ foreach my $key (keys(%{$updated->{$type}})) {
+ $updates{$key} = 1;
+ }
+ }
+ }
+ }
+ foreach my $key (keys(%updates)) {
+ my (%torewrite,%toretitle,%toremove,%remparam,%currparam,%zombie,%newdb);
+ if (ref($rewrites{$key}) eq 'HASH') {
+ %torewrite = %{$rewrites{$key}};
+ }
+ if (ref($retitles{$key}) eq 'HASH') {
+ %toretitle = %{$retitles{$key}};
+ }
+ if (ref($removefrommap{$key}) eq 'HASH') {
+ %toremove = %{$removefrommap{$key}};
+ }
+ if (ref($removeparam{$key}) eq 'HASH') {
+ %remparam = %{$removeparam{$key}};
+ }
+ if (ref($zombies{$key}) eq 'HASH') {
+ %zombie = %{$zombies{$key}};
+ }
+ if (ref($dbcopies{$key}) eq 'HASH') {
+ foreach my $item (keys(%{$dbcopies{$key}})) {
+ $newdb{$item} = &dbcopy($item);
+ }
+ }
+ if (ref($params{$key}) eq 'HASH') {
+ %currparam = %{$params{$key}};
+ }
+ my ($errtext,$fatal) = &LONCAPA::map::mapread($key);
+ if ($fatal) {
+ return $errtext;
+ }
+ for (my $i=0; $i<@LONCAPA::map::zombies; $i++) {
+ if (defined($LONCAPA::map::zombies[$i])) {
+ my ($title,$src,$ext,$type)=split(/\:/,$LONCAPA::map::zombies[$i]);
+ if ($zombie{$src} eq $i) {
+ undef($LONCAPA::map::zombies[$i]);
+ }
+ }
+ }
+ for (my $i=0; $i<@LONCAPA::map::order; $i++) {
+ my $idx = $LONCAPA::map::order[$i];
+ if (defined($LONCAPA::map::resources[$idx])) {
+ my $changed;
+ my ($title,$src,$ext,$type)=split(/\:/,$LONCAPA::map::resources[$idx]);
+ if ((exists($toremove{$idx})) && ($toremove{$idx} eq $src)) {
+ splice(@LONCAPA::map::order,$i,1);
+ if (ref($currparam{$idx}) eq 'ARRAY') {
+ foreach my $name (@{$currparam{$idx}}) {
+ &LONCAPA::map::delparameter($idx,'parameter_'.$name);
+ }
+ }
+ next;
+ }
+ my $origsrc = $src;
+ if ((exists($toretitle{$src})) && ($toretitle{$src} eq $idx)) {
+ if ($title =~ m{^\d+\Q___&&&___\E$match_username\Q___&&&___\E$match_domain\Q___&&&___\E(.+)$}) {
+ $changed = 1;
+ }
+ }
+ if ((exists($torewrite{$src})) && ($torewrite{$src} eq $idx)) {
+ $src =~ s{^/(uploaded|adm|public)/$match_domain/$match_courseid/}{/$1/$cdom/$cnum/};
+ if ($origsrc =~ m{^/uploaded/}) {
+ if ($prefixchg && $before{'map'} && $after{'map'}) {
+ if ($src =~ /\.(page|sequence)$/) {
+ $src =~ s#^(/uploaded/$match_domain/$match_courseid/)\Q$before{'map'}\E#$1$after{'map'}#;
+ } else {
+ $src =~ s#^(/uploaded/$match_domain/$match_courseid/)\Q$before{'doc'}\E#$1$after{'doc'}#;
+ }
+ }
+ if ($newsubdir{$origsrc}) {
+ if ($src =~ /\.(page|sequence)$/) {
+ $src =~ s#^(/uploaded/$match_domain/$match_courseid/(?:default|supplemental)_)(\d+)#$1$newsubdir{$origsrc}#;
+ } else {
+ $src =~ s#^(/uploaded/$match_domain/$match_courseid/\w+/)(\d+)#$1$newsubdir{$origsrc}#;
+ }
+ }
+ }
+ $changed = 1;
+ } elsif ($newdb{$src} ne '') {
+ $src = $newdb{$src};
+ $changed = 1;
+ }
+ if ($changed) {
+ $LONCAPA::map::resources[$idx] = join(':',($title,$src,$ext,$type));
+ }
+ }
+ }
+ foreach my $idx (keys(%remparam)) {
+ if (ref($remparam{$idx}) eq 'ARRAY') {
+ foreach my $name (@{$remparam{$idx}}) {
+ &LONCAPA::map::delparameter($idx,'parameter_'.$name);
+ }
+ }
+ }
+ my $storefn;
+ if ($key eq $oldurl) {
+ $storefn = $url;
+ $storefn=~s{^/uploaded/$match_domain/$match_courseid/}{};
+ } else {
+ $storefn = $key;
+ $storefn=~s{^/uploaded/$match_domain/$match_courseid/}{};
+ if ($prefixchg && $before{'map'} && $after{'map'}) {
+ $storefn =~ s/^\Q$before{'map'}\E/$after{'map'}/;
+ }
+ if ($newsubdir{$key}) {
+ $storefn =~ s/^((?:default|supplemental)_)(\d+)/$1$newsubdir{$key}/;
+ }
+ }
+ my $report;
+ if ($folder !~ /^supplemental/) {
+ $report = 1;
+ }
+ (my $outtext,$errtext) =
+ &LONCAPA::map::storemap("/uploaded/$cdom/$cnum/$storefn",1,$report);
+ if ($errtext) {
+ if ($caller eq 'paste') {
+ return &mt('Paste failed: an error occurred saving the folder or page.');
+ }
+ }
+ }
+ }
+ return 'ok';
+}
+
+sub copy_dependencies {
+ my ($item,$storefn,$relpath,$errors,$contentref) = @_;
+ my $content;
+ if (ref($contentref)) {
+ $content = $$contentref;
} else {
+ $content = &Apache::lonnet::getfile($item);
+ }
+ unless ($content eq '-1') {
+ my $mm = new File::MMagic;
+ my $mimetype = $mm->checktype_contents($content);
+ if ($mimetype eq 'text/html') {
+ my (%allfiles,%codebase,$state);
+ my $res = &Apache::lonnet::extract_embedded_items(undef,\%allfiles,\%codebase,\$content);
+ if ($res eq 'ok') {
+ my ($numexisting,$numpathchanges,$existing);
+ (undef,$numexisting,$numpathchanges,$existing) =
+ &Apache::loncommon::ask_for_embedded_content(
+ '/adm/coursedocs',$state,\%allfiles,\%codebase,
+ {'error_on_invalid_names' => 1,
+ 'ignore_remote_references' => 1,
+ 'docs_url' => $item,
+ 'context' => 'paste'});
+ if ($numexisting > 0) {
+ if (ref($existing) eq 'HASH') {
+ foreach my $dep (keys(%{$existing})) {
+ my $depfile = $dep;
+ unless ($depfile =~ m{^\Q$relpath\E}) {
+ $depfile = $relpath.$dep;
+ }
+ my $depcontent = &Apache::lonnet::getfile($depfile);
+ unless ($depcontent eq '-1') {
+ my $storedep = $dep;
+ $storedep =~ s{^\Q$relpath\E}{};
+ my $dep_url =
+ &Apache::lonclonecourse::writefile(
+ $env{'request.course.id'},
+ $storefn.$storedep,$depcontent);
+ if ($dep_url eq '/adm/notfound.html') {
+ if (ref($errors) eq 'HASH') {
+ $errors->{$depfile} = 1;
+ }
+ } else {
+ ©_dependencies($depfile,$storefn,$relpath,$errors,\$depcontent);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return;
+}
+
+my %parameter_type = ( 'randompick' => 'int_pos',
+ 'hiddenresource' => 'string_yesno',
+ 'encrypturl' => 'string_yesno',
+ 'randomorder' => 'string_yesno',);
+my $valid_parameters_re = join('|',keys(%parameter_type));
+# set parameters
+sub update_parameter {
+
+ return 0 if ($env{'form.changeparms'} !~ /^($valid_parameters_re)$/);
+
+ my $which = $env{'form.changeparms'};
+ my $idx = $env{'form.setparms'};
+ if ($env{'form.'.$which.'_'.$idx}) {
+ my $value = ($which eq 'randompick') ? $env{'form.'.$which.'_'.$idx}
+ : 'yes';
+ &LONCAPA::map::storeparameter($idx, 'parameter_'.$which, $value,
+ $parameter_type{$which});
+ &remember_parms($idx,$which,'set',$value);
+ } else {
+ &LONCAPA::map::delparameter($idx,'parameter_'.$which);
+
+ &remember_parms($idx,$which,'del');
+ }
+ return 1;
+}
+
+
+sub handle_edit_cmd {
+ my ($coursenum,$coursedom) =@_;
+ my ($cmd,$idx)=split('_',$env{'form.cmd'});
+
+ my $ratstr = $LONCAPA::map::resources[$LONCAPA::map::order[$idx]];
+ my ($title, $url, @rrest) = split(':', $ratstr);
+
+ if ($cmd eq 'del') {
+ if (($url=~m|/+uploaded/\Q$coursedom\E/\Q$coursenum\E/|) &&
+ ($url!~/$LONCAPA::assess_page_seq_re/)) {
+ &Apache::lonnet::removeuploadedurl($url);
+ } else {
+ &LONCAPA::map::makezombie($LONCAPA::map::order[$idx]);
+ }
+ splice(@LONCAPA::map::order, $idx, 1);
+
+ } elsif ($cmd eq 'cut') {
+ &LONCAPA::map::makezombie($LONCAPA::map::order[$idx]);
+ splice(@LONCAPA::map::order, $idx, 1);
+
+ } elsif ($cmd eq 'up'
+ && ($idx) && (defined($LONCAPA::map::order[$idx-1]))) {
+ @LONCAPA::map::order[$idx-1,$idx] = @LONCAPA::map::order[$idx,$idx-1];
+
+ } elsif ($cmd eq 'down'
+ && defined($LONCAPA::map::order[$idx+1])) {
+ @LONCAPA::map::order[$idx+1,$idx] = @LONCAPA::map::order[$idx,$idx+1];
+
+ } elsif ($cmd eq 'rename') {
+
+ my $comment = &LONCAPA::map::qtunescape($env{'form.title'});
+ if ($comment=~/\S/) {
+ $LONCAPA::map::resources[$LONCAPA::map::order[$idx]]=
+ $comment.':'.join(':', $url, @rrest);
+ }
+# Devalidate title cache
+ my $renamed_url=&LONCAPA::map::qtescape($url);
+ &Apache::lonnet::devalidate_title_cache($renamed_url);
+ } else {
+ return 0;
+ }
+ return 1;
+}
+
+sub editor {
+ my ($r,$coursenum,$coursedom,$folder,$allowed,$upload_output,$crstype,
+ $supplementalflag,$orderhash,$iconpath,$pathitem)=@_;
+ my ($randompick,$ishidden,$isencrypted,$plain,$is_random_order,$container);
+ if ($allowed) {
+ (my $breadcrumbtrail,$randompick,$ishidden,$isencrypted,$plain,
+ $is_random_order,$container) =
+ &Apache::lonhtmlcommon::docs_breadcrumbs($allowed,$crstype,1);
+ $r->print($breadcrumbtrail);
+ } elsif ($env{'form.folderpath'} =~ /\:1$/) {
+ $container = 'page';
+ } else {
+ $container = 'sequence';
+ }
+
+ my $jumpto;
+
+ unless ($supplementalflag) {
+ $jumpto = "'uploaded/$coursedom/$coursenum/$folder.$container'";
+ }
+
+ unless ($allowed) {
+ $randompick = -1;
+ }
+
+ my ($errtext,$fatal) = &mapread($coursenum,$coursedom,
+ $folder.'.'.$container);
+ return $errtext if ($fatal);
+
+ if ($#LONCAPA::map::order<1) {
+ my $idx=&LONCAPA::map::getresidx();
+ if ($idx<=0) { $idx=1; }
+ $LONCAPA::map::order[0]=$idx;
+ $LONCAPA::map::resources[$idx]='';
+ }
+
# ------------------------------------------------------------ Process commands
# ---------------- if they are for this folder and user allowed to make changes
- if (($allowed) && ($ENV{'form.folder'} eq $folder)) {
+ if (($allowed) && ($env{'form.folder'} eq $folder)) {
# set parameters and change order
- if (defined($ENV{'form.setparms'})) {
- my $idx=$ENV{'form.setparms'};
-# set parameters
- if ($ENV{'form.randpick_'.$idx}) {
- &Apache::lonratedt::storeparameter($idx,'parameter_randompick',$ENV{'form.randpick_'.$idx},'int_pos');
- } else {
- &Apache::lonratedt::delparameter($idx,'parameter_randompick');
- }
- if ($ENV{'form.hidprs_'.$idx}) {
- &Apache::lonratedt::storeparameter($idx,'parameter_hiddenresource','yes','string_yesno');
- } else {
- &Apache::lonratedt::delparameter($idx,'parameter_hiddenresource');
- }
- if ($ENV{'form.encprs_'.$idx}) {
- &Apache::lonratedt::storeparameter($idx,'parameter_encrypturl','yes','string_yesno');
- } else {
- &Apache::lonratedt::delparameter($idx,'parameter_encrypturl');
- }
+ &snapshotbefore();
- if ($ENV{'form.newpos'}) {
-# change order
+ if (&update_parameter()) {
+ ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container);
+ return $errtext if ($fatal);
+ }
- my $newpos=$ENV{'form.newpos'}-1;
- my $currentpos=$ENV{'form.currentpos'}-1;
- my $i;
- my @neworder=();
- if ($newpos>$currentpos) {
-# moving stuff up
- for ($i=0;$i<$currentpos;$i++) {
- $neworder[$i]=$Apache::lonratedt::order[$i];
- }
- for ($i=$currentpos;$i<$newpos;$i++) {
- $neworder[$i]=$Apache::lonratedt::order[$i+1];
- }
- $neworder[$newpos]=$Apache::lonratedt::order[$currentpos];
- for ($i=$newpos+1;$i<=$#Apache::lonratedt::order;$i++) {
- $neworder[$i]=$Apache::lonratedt::order[$i];
- }
- } else {
-# moving stuff down
- for ($i=0;$i<$newpos;$i++) {
- $neworder[$i]=$Apache::lonratedt::order[$i];
- }
- $neworder[$newpos]=$Apache::lonratedt::order[$currentpos];
- for ($i=$newpos+1;$i<$currentpos+1;$i++) {
- $neworder[$i]=$Apache::lonratedt::order[$i-1];
- }
- for ($i=$currentpos+1;$i<=$#Apache::lonratedt::order;$i++) {
- $neworder[$i]=$Apache::lonratedt::order[$i];
- }
- }
- @Apache::lonratedt::order=@neworder;
- }
-# store the changed version
+ if ($env{'form.newpos'} && $env{'form.currentpos'}) {
+# change order
+ my $res = splice(@LONCAPA::map::order,$env{'form.currentpos'}-1,1);
+ splice(@LONCAPA::map::order,$env{'form.newpos'}-1,0,$res);
- ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.sequence');
- if ($fatal) {
- $r->print(''.$errtext.'
');
- return;
- }
-
- }
+ ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container);
+ return $errtext if ($fatal);
+ }
-# upload a file, if present
- if (($ENV{'form.uploaddoc.filename'}) &&
- ($ENV{'form.cmd'}=~/^upload_(\w+)/)) {
- if ( ($folder=~/^$1/) || ($1 eq 'default') ) {
-# this is for a course, not a user, so set coursedoc flag
-# probably the only place in the system where this should be "1"
- my $url=&Apache::lonnet::userfileupload('uploaddoc',1,'docs');
- my $ext='false';
- if ($url=~/^http\:\/\//) { $ext='true'; }
- $url=~s/\:/\:/g;
- my $comment=$ENV{'form.comment'};
- $comment=~s/\\<\;/g;
- $comment=~s/\>/\>\;/g;
- $comment=~s/\:/\:/g;
- if ($folder=~/^supplemental/) {
- $comment=time.'___&&&___'.$ENV{'user.name'}.'___&&&___'.
- $ENV{'user.domain'}.'___&&&___'.$comment;
- }
- my $newidx=$#Apache::lonratedt::resources+1;
- $Apache::lonratedt::resources[$newidx]=
- $comment.':'.$url.':'.$ext.':normal:res';
- $Apache::lonratedt::order[$#Apache::lonratedt::order+1]=
- $newidx;
-
- ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.sequence');
- if ($fatal) {
- $r->print(''.$errtext.'
');
- return;
- }
- }
+ if ($env{'form.pastemarked'}) {
+ my %paste_errors;
+ my ($paste_res,$save_error) =
+ &do_paste_from_buffer($coursenum,$coursedom,$folder,$container,
+ \%paste_errors);
+ if ($save_error ne '') {
+ return $save_error;
+ }
+ if ($paste_res ne 'ok') {
+ $r->print(''.$paste_res.'
');
}
- if ($ENV{'form.cmd'}) {
- my ($cmd,$idx)=split(/\_/,$ENV{'form.cmd'});
- if ($cmd eq 'del') {
- for (my $i=$idx;$i<$#Apache::lonratedt::order;$i++) {
- $Apache::lonratedt::order[$i]=
- $Apache::lonratedt::order[$i+1];
- }
- $#Apache::lonratedt::order--;
- } elsif ($cmd eq 'up') {
- if (($idx) && (defined($Apache::lonratedt::order[$idx-1]))) {
- my $i=$Apache::lonratedt::order[$idx-1];
- $Apache::lonratedt::order[$idx-1]=
- $Apache::lonratedt::order[$idx];
- $Apache::lonratedt::order[$idx]=$i;
- }
- } elsif ($cmd eq 'down') {
- if (defined($Apache::lonratedt::order[$idx+1])) {
- my $i=$Apache::lonratedt::order[$idx+1];
- $Apache::lonratedt::order[$idx+1]=
- $Apache::lonratedt::order[$idx];
- $Apache::lonratedt::order[$idx]=$i;
- }
- } elsif ($cmd eq 'rename') {
- my ($rtitle,@rrest)=split(/\:/,
- $Apache::lonratedt::resources[
- $Apache::lonratedt::order[$idx]]);
- my $comment=
- &HTML::Entities::decode($ENV{'form.title'});
- $comment=~s/\\<\;/g;
- $comment=~s/\>/\>\;/g;
- $comment=~s/\:/\:/g;
- $Apache::lonratedt::resources[
- $Apache::lonratedt::order[$idx]]=
- $comment.':'.join(':',@rrest);
-
+ if (keys(%paste_errors) > 0) {
+ $r->print(''."\n".
+ &mt('The following files are either dependencies of a web page or references within a folder and/or composite page which could not be copied during the paste operation:')."\n".
+ '
'."\n");
+ foreach my $key (sort(keys(%paste_errors))) {
+ $r->print(''.$key.' '."\n");
}
-# Store the changed version
- ($errtext,$fatal)=&storemap($coursenum,$coursedom,
- $folder.'.sequence');
- if ($fatal) {
- $r->print(''.$errtext.'
');
- return;
- }
+ $r->print(' '."\n");
+ }
+ }
+
+ $r->print($upload_output);
+
+ if (&handle_edit_cmd()) {
+ my $contentchg;
+ if ($env{'form.cmd'} =~ /^(del|cut)_/) {
+ $contentchg = 1;
}
+ ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container,$contentchg);
+ return $errtext if ($fatal);
+ }
# Group import/search
- if ($ENV{'form.importdetail'}) {
- my @imports;
- foreach (split(/\&/,$ENV{'form.importdetail'})) {
- if (defined($_)) {
- my ($name,$url)=split(/\=/,$_);
- $name=&Apache::lonnet::unescape($name);
- $url=&Apache::lonnet::unescape($url);
- push @imports, $name, $url;
- }
- }
-# Store the changed version
- ($errtext,$fatal)=group_import($coursenum, $coursedom, $folder,
- @imports);
- if ($fatal) {
- $r->print(''.$errtext.'
');
- return;
+ if ($env{'form.importdetail'}) {
+ my @imports;
+ foreach my $item (split(/\&/,$env{'form.importdetail'})) {
+ if (defined($item)) {
+ my ($name,$url,$residx)=
+ map {&unescape($_)} split(/\=/,$item);
+ if ($url=~ m{^\Q/uploaded/$coursedom/$coursenum/\E(default|supplemental)_new\.(sequence|page)$}) {
+ my ($suffix,$errortxt,$locknotfreed) =
+ &newmap_suffix($1,$2,$coursedom,$coursenum);
+ if ($locknotfreed) {
+ $r->print($locknotfreed);
+ }
+ if ($suffix) {
+ $url =~ s/_new\./_$suffix./;
+ } else {
+ return $errortxt;
+ }
+ }
+ push(@imports, [$name, $url, $residx]);
}
+ }
+ ($errtext,$fatal,my $fixuperrors) =
+ &group_import($coursenum, $coursedom, $folder,$container,
+ 'londocs',@imports);
+ return $errtext if ($fatal);
+ if ($fixuperrors) {
+ $r->print($fixuperrors);
}
+ }
# Loading a complete map
- if (($ENV{'form.importmap'}) && ($ENV{'form.loadmap'})) {
- foreach (&Apache::lonsequence::attemptread(&Apache::lonnet::filelocation('',$ENV{'form.importmap'}))) {
- my $idx=$#Apache::lonratedt::resources;
- $idx++;
- $Apache::lonratedt::resources[$idx]=$_;
- $Apache::lonratedt::order
- [$#Apache::lonratedt::order+1]=$idx;
- }
-
-# Store the changed version
- ($errtext,$fatal)=&storemap($coursenum,$coursedom,
- $folder.'.sequence');
- if ($fatal) {
- $r->print(''.$errtext.'
');
- return;
- }
- }
- }
+ if ($env{'form.loadmap'}) {
+ if ($env{'form.importmap'}=~/\w/) {
+ foreach my $res (&Apache::lonsequence::attemptread(&Apache::lonnet::filelocation('',$env{'form.importmap'}))) {
+ my ($title,$url,$ext,$type)=split(/\:/,$res);
+ my $idx=&LONCAPA::map::getresidx($url);
+ $LONCAPA::map::resources[$idx]=$res;
+ $LONCAPA::map::order[$#LONCAPA::map::order+1]=$idx;
+ }
+ ($errtext,$fatal)=&storemap($coursenum,$coursedom,
+ $folder.'.'.$container,1);
+ return $errtext if ($fatal);
+ } else {
+ $r->print(''.&mt('No map selected.').'
');
+
+ }
+ }
+ &log_differences($plain);
+ }
# ---------------------------------------------------------------- End commands
# ---------------------------------------------------------------- Print screen
- my $idx=0;
- $r->print('');
- foreach (@Apache::lonratedt::order) {
- my ($name,$url)=split(/\:/,$Apache::lonratedt::resources[$_]);
- unless ($name) { $name=(split(/\//,$url))[-1]; }
- unless ($name) { next; }
- $r->print(&entryline($idx,$name,$url,$folder,$allowed,$_,$coursenum));
- $idx++;
+ my $idx=0;
+ my $shown=0;
+ if (($ishidden) || ($isencrypted) || ($randompick>=0) || ($is_random_order)) {
+ $r->print(''.
+ '
'.&mt('Parameters:').' '.
+ ($randompick>=0?''.&mt('randomly pick [quant,_1,resource]',$randompick).' ':'').
+ ($ishidden?''.&mt('contents hidden').' ':'').
+ ($isencrypted?''.&mt('URLs hidden').' ':'').
+ ($is_random_order?''.&mt('random order').' ':'').
+ '');
+ if ($randompick>=0) {
+ $r->print('
'
+ .&mt('Caution: this folder is set to randomly pick a subset'
+ .' of resources. Adding or removing resources from this'
+ .' folder will change the set of resources that the'
+ .' students see, resulting in spurious or missing credit'
+ .' for completed problems, not limited to ones you'
+ .' modify. Do not modify the contents of this folder if'
+ .' it is in active student use.')
+ .'
'
+ );
+ }
+ if ($is_random_order) {
+ $r->print('
'
+ .&mt('Caution: this folder is set to randomly order its'
+ .' contents. Adding or removing resources from this folder'
+ .' will change the order of resources shown.')
+ .'
'
+ );
}
- $r->print('
');
+ $r->print('');
+ }
+
+ my ($to_show,$output);
+
+ &Apache::loncommon::start_data_table_count(); #setup a row counter
+ foreach my $res (@LONCAPA::map::order) {
+ my ($name,$url)=split(/\:/,$LONCAPA::map::resources[$res]);
+ $name=&LONCAPA::map::qtescape($name);
+ $url=&LONCAPA::map::qtescape($url);
+ unless ($name) { $name=(split(/\//,$url))[-1]; }
+ unless ($name) { $idx++; next; }
+ $output .= &entryline($idx,$name,$url,$folder,$allowed,$res,
+ $coursenum,$coursedom,$crstype,
+ $pathitem,$supplementalflag,$container);
+ $idx++;
+ $shown++;
}
+ &Apache::loncommon::end_data_table_count();
+
+ if (($allowed) || ($supplementalflag && $folder eq 'supplemental')) {
+ my $toolslink = ''
+ .&Apache::loncommon::help_open_menu('Navigation Screen',
+ 'Navigation_Screen',undef,'RAT')
+ .' '.&mt('Tools:').' '
+ .'
';
+ if ($shown) {
+ if ($allowed) {
+ $to_show = &Apache::loncommon::start_scrollbox('900px','880px','400px','contentscroll')
+ .&Apache::loncommon::start_data_table(undef,'contentlist')
+ .&Apache::loncommon::start_data_table_header_row()
+ .''.&mt('Move').' '
+ .''.&mt('Actions').' '
+ .''.&mt('Document').' ';
+ if ($folder !~ /^supplemental/) {
+ $to_show .= ''.&mt('Settings').' ';
+ }
+ $to_show .= &Apache::loncommon::end_data_table_header_row()
+ .$output.' '
+ .&Apache::loncommon::end_data_table()
+ .' '
+ .&Apache::loncommon::end_scrollbox();
+ } else {
+ $to_show .= $toolslink
+ .&Apache::loncommon::start_data_table('LC_tableOfContent')
+ .$output.' '
+ .&Apache::loncommon::end_data_table();
+ }
+ } else {
+ if (!$allowed) {
+ $to_show .= $toolslink;
+ }
+ $to_show .= &Apache::loncommon::start_scrollbox('400px','380px','200px','contentscroll')
+ .''
+ .&mt('Currently no documents.')
+ .'
'
+ .&Apache::loncommon::end_scrollbox();
+ }
+ } else {
+ if ($shown) {
+ $to_show = ''
+ .&Apache::loncommon::start_data_table('LC_tableOfContent')
+ .$output
+ .&Apache::loncommon::end_data_table()
+ .'
';
+ } else {
+ $to_show = ''
+ .&mt('Currently no documents.')
+ .'
'
+ }
+ }
+ my $tid = 1;
+ if ($supplementalflag) {
+ $tid = 2;
+ }
+ if ($allowed) {
+ my $readfile="/uploaded/$coursedom/$coursenum/$folder.$container";
+ $r->print(&generate_edit_table($tid,$orderhash,$to_show,$iconpath,$jumpto,
+ $readfile));
+ &print_paste_buffer($r,$container,$folder,$coursedom,$coursenum);
+ } else {
+ $r->print($to_show);
+ }
+ return;
+}
+
+sub process_file_upload {
+ my ($upload_output,$coursenum,$coursedom,$allfiles,$codebase,$uploadcmd) = @_;
+# upload a file, if present
+ my ($parseaction,$showupload,$nextphase,$mimetype);
+ if ($env{'form.parserflag'}) {
+ $parseaction = 'parse';
+ }
+ my $folder=$env{'form.folder'};
+ if ($folder eq '') {
+ $folder='default';
+ }
+ if ( ($folder=~/^$uploadcmd/) || ($uploadcmd eq 'default') ) {
+ my $errtext='';
+ my $fatal=0;
+ my $container='sequence';
+ if ($env{'form.folderpath'} =~ /:1$/) {
+ $container='page';
+ }
+ ($errtext,$fatal)=
+ &mapread($coursenum,$coursedom,$folder.'.'.$container);
+ if ($#LONCAPA::map::order<1) {
+ $LONCAPA::map::order[0]=1;
+ $LONCAPA::map::resources[1]='';
+ }
+ if ($fatal) {
+ $$upload_output = ''.&mt('The uploaded file has not been stored as an error occurred reading the contents of the current folder.').'
';
+ return;
+ }
+ my $destination = 'docs/';
+ if ($folder =~ /^supplemental/) {
+ $destination = 'supplemental/';
+ }
+ if (($folder eq 'default') || ($folder eq 'supplemental')) {
+ $destination .= 'default/';
+ } elsif ($folder =~ /^(default|supplemental)_(\d+)$/) {
+ $destination .= $2.'/';
+ }
+# this is for a course, not a user, so set context to coursedoc.
+ my $newidx=&LONCAPA::map::getresidx();
+ $destination .= $newidx;
+ my $url=&Apache::lonnet::userfileupload('uploaddoc','coursedoc',$destination,
+ $parseaction,$allfiles,
+ $codebase,undef,undef,undef,undef,
+ undef,undef,\$mimetype);
+ if ($url =~ m{^/uploaded/\Q$coursedom\E/\Q$coursenum\E.*/([^/]+)$}) {
+ my $stored = $1;
+ $showupload = ''.&mt('Uploaded [_1]',''.
+ $stored.' ').'
';
+ } else {
+ my ($filename) = ($env{'form.uploaddoc.filename'} =~ m{([^/]+)$});
+
+ $$upload_output = ''.&mt('Unable to save file [_1].',''.$filename.' ').'
';
+ return;
+ }
+ my $ext='false';
+ if ($url=~m{^http://}) { $ext='true'; }
+ $url = &LONCAPA::map::qtunescape($url);
+ my $comment=$env{'form.comment'};
+ $comment = &LONCAPA::map::qtunescape($comment);
+ if ($folder=~/^supplemental/) {
+ $comment=time.'___&&&___'.$env{'user.name'}.'___&&&___'.
+ $env{'user.domain'}.'___&&&___'.$comment;
+ }
+
+ $LONCAPA::map::resources[$newidx]=
+ $comment.':'.$url.':'.$ext.':normal:res';
+ $LONCAPA::map::order[$#LONCAPA::map::order+1]= $newidx;
+ ($errtext,$fatal)=&storemap($coursenum,$coursedom,
+ $folder.'.'.$container,1);
+ if ($fatal) {
+ $$upload_output = ''.$errtext.'
';
+ return;
+ } else {
+ if ($parseaction eq 'parse' && $mimetype eq 'text/html') {
+ $$upload_output = $showupload;
+ my $total_embedded = scalar(keys(%{$allfiles}));
+ if ($total_embedded > 0) {
+ my $uploadphase = 'upload_embedded';
+ my $primaryurl = &HTML::Entities::encode($url,'<>&"');
+ my $state = &embedded_form_elems($uploadphase,$primaryurl,$newidx);
+ my ($embedded,$num) =
+ &Apache::loncommon::ask_for_embedded_content(
+ '/adm/coursedocs',$state,$allfiles,$codebase,{'docs_url' => $url});
+ if ($embedded) {
+ if ($num) {
+ $$upload_output .=
+ ''.&mt('This file contains embedded multimedia objects, which need to be uploaded.').'
'.$embedded;
+ $nextphase = $uploadphase;
+ } else {
+ $$upload_output .= $embedded;
+ }
+ } else {
+ $$upload_output .= &mt('Embedded item(s) already present, so no additional upload(s) required').' ';
+ }
+ } else {
+ $$upload_output .= &mt('No embedded items identified').' ';
+ }
+ $$upload_output = ''.$$upload_output.'
';
+ } elsif (&Apache::loncommon::is_archive_file($mimetype)) {
+ $nextphase = 'decompress_uploaded';
+ my $position = scalar(@LONCAPA::map::order)-1;
+ my $noextract = &return_to_editor();
+ my $archiveurl = &HTML::Entities::encode($url,'<>&"');
+ my %archiveitems = (
+ folderpath => $env{'form.folderpath'},
+ cmd => $nextphase,
+ newidx => $newidx,
+ position => $position,
+ phase => $nextphase,
+ comment => $comment,
+ );
+ my ($destination,$dir_root) = &embedded_destination($coursenum,$coursedom);
+ my @current = &get_dir_list($url,$coursenum,$coursedom,$newidx);
+ $$upload_output = $showupload.
+ &Apache::loncommon::decompress_form($mimetype,
+ $archiveurl,'/adm/coursedocs',$noextract,
+ \%archiveitems,\@current);
+ }
+ }
+ }
+ return $nextphase;
+}
+
+sub get_dir_list {
+ my ($url,$coursenum,$coursedom,$newidx) = @_;
+ my ($destination,$dir_root) = &embedded_destination();
+ my ($dirlistref,$listerror) =
+ &Apache::lonnet::dirlist("$dir_root/$destination/$newidx",$coursedom,$coursenum,1);
+ my @dir_lines;
+ my $dirptr=16384;
+ if (ref($dirlistref) eq 'ARRAY') {
+ foreach my $dir_line (sort
+ {
+ my ($afile)=split('&',$a,2);
+ my ($bfile)=split('&',$b,2);
+ return (lc($afile) cmp lc($bfile));
+ } (@{$dirlistref})) {
+ my ($filename,$dom,undef,$testdir,undef,undef,undef,undef,$size,undef,$mtime,undef,undef,undef,$obs,undef)=split(/\&/,$dir_line,16);
+ $filename =~ s/\s+$//;
+ next if ($filename =~ /^\.\.?$/);
+ my $isdir = 0;
+ if ($dirptr&$testdir) {
+ $isdir = 1;
+ }
+ push(@dir_lines, [$filename,$dom,$isdir,$size,$mtime,$obs]);
+ }
+ }
+ return @dir_lines;
+}
+
+sub is_supplemental_title {
+ my ($title) = @_;
+ return scalar($title =~ m/^(\d+)___&&&___($match_username)___&&&___($match_domain)___&&&___(.*)$/);
}
# --------------------------------------------------------------- An entry line
sub entryline {
- my ($index,$title,$url,$folder,$allowed,$residx,$coursenum)=@_;
- $title=~s/\&colon\;/\:/g;
- $title=&HTML::Entities::encode(&HTML::Entities::decode(
- &Apache::lonnet::unescape($title)),'"<>&\'');
- my $renametitle=$title;
- my $foldertitle=$title;
- my $orderidx=$Apache::lonratedt::order[$index];
- if ($title=~ /^(\d+)___&&&___(\w+)___&&&___(\w+)___&&&___(.*)$/ ) {
- $foldertitle=&Apache::lontexconvert::msgtexconverted($4);
- $renametitle=$4;
- $title=''.&Apache::lonlocal::locallocaltime($1).' '.
- &Apache::loncommon::plainname($2,$3).': '.
- $foldertitle;
+ my ($index,$title,$url,$folder,$allowed,$residx,$coursenum,$coursedom,
+ $crstype,$pathitem,$supplementalflag,$container)=@_;
+ my ($foldertitle,$renametitle);
+ if (&is_supplemental_title($title)) {
+ ($title,$foldertitle,$renametitle) = &Apache::loncommon::parse_supplemental_title($title);
+ } else {
+ $title=&HTML::Entities::encode($title,'"<>&\'');
+ $renametitle=$title;
+ $foldertitle=$title;
}
+
+ my $orderidx=$LONCAPA::map::order[$index];
+
+ $renametitle=~s/\\/\\\\/g;
$renametitle=~s/\"\;/\\\"/g;
- my $line='';
+ $renametitle=~s/ /%20/g;
+ my $line=&Apache::loncommon::start_data_table_row();
+ my ($form_start,$form_end,$form_common);
# Edit commands
- my $folderpath;
- if ($ENV{'form.folderpath'}) {
- $folderpath=&Apache::lonnet::escape($ENV{'form.folderpath'});
- # $htmlfoldername=&HTML::Entities::encode($ENV{'form.foldername'},'<>&"');
+ my ($type, $esc_path, $path, $symb);
+ if ($container eq 'page') {
+ $type = 'page';
+ } else {
+ $type = 'folder';
+ }
+ if ($env{'form.folderpath'}) {
+ $esc_path=&escape($env{'form.folderpath'});
+ $path = &HTML::Entities::encode($env{'form.folderpath'},'<>&"');
+ # $htmlfoldername=&HTML::Entities::encode($env{'form.foldername'},'<>&"');
}
+ my $isexternal;
+ if ($residx) {
+ my $currurl = $url;
+ $currurl =~ s{^http(|s)(:|:)//}{/adm/wrapper/ext/};
+ if ($currurl =~ m{^/adm/wrapper/ext/}) {
+ $isexternal = 1;
+ }
+ if (!$supplementalflag) {
+ my $path = 'uploaded/'.
+ $env{'course.'.$env{'request.course.id'}.'.domain'}.'/'.
+ $env{'course.'.$env{'request.course.id'}.'.num'}.'/';
+ $symb = &Apache::lonnet::encode_symb($path.$folder.".$container",
+ $residx,
+ &Apache::lonnet::declutter($currurl));
+ }
+ }
+ my ($renamelink,%lt);
if ($allowed) {
my $incindex=$index+1;
my $selectbox='';
- if ($folder!~/^supplemental/) {
+ if (($#LONCAPA::map::order>0) &&
+ ((split(/\:/,
+ $LONCAPA::map::resources[$LONCAPA::map::order[0]]))[1]
+ ne '') &&
+ ((split(/\:/,
+ $LONCAPA::map::resources[$LONCAPA::map::order[1]]))[1]
+ ne '')) {
$selectbox=
' '.
- '';
- for (my $i=1;$i<=$#Apache::lonratedt::order+1;$i++) {
+ '';
+ for (my $i=1;$i<=$#LONCAPA::map::order+1;$i++) {
if ($i==$incindex) {
- $selectbox.='('.$i.') ';
+ $selectbox.='('.$i.') ';
} else {
$selectbox.=''.$i.' ';
}
}
$selectbox.=' ';
}
- my %lt=&Apache::lonlocal::texthash(
+ %lt=&Apache::lonlocal::texthash(
'up' => 'Move Up',
'dw' => 'Move Down',
'rm' => 'Remove',
- 'rn' => 'Rename');
+ 'ct' => 'Cut',
+ 'rn' => 'Rename',
+ 'cp' => 'Copy',
+ 'ex' => 'External Resource',
+ 'ed' => 'Edit',
+ 'pr' => 'Preview',
+ 'sv' => 'Save',
+ 'ul' => 'URL',
+ 'ti' => 'Title',
+ );
+ my $nocopy=0;
+ my $nocut=0;
+ my $noremove=0;
+ if ($url=~ m{^/res/.+\.(page|sequence)$}) {
+ # no copy for published maps
+ $nocopy=1;
+ }
+ if ($url=~/^\/res\/lib\/templates\//) {
+ $nocopy=1;
+ $nocut=1;
+ }
+ my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ if ($url eq "/uploaded/$cdom/$cnum/group_allfolders.sequence") {
+ if ($env{'form.folderpath'} =~ /^default&[^\&]+$/) {
+ my %curr_groups = &Apache::longroup::coursegroups();
+ if (keys(%curr_groups) > 0) {
+ $noremove=1;
+ }
+ $nocut=1;
+ $nocopy=1;
+ }
+ } elsif ($url =~ m{^\Q/uploaded/$cdom/$cnum/group_folder_\E(\w+)\.sequence$}) {
+ my $group = $1;
+ if ($env{'form.folderpath'} =~ /^default&[^\&]+\&group_allfolders\&[^\&]+$/) {
+ my %curr_group = &Apache::longroup::coursegroups($cdom,$cnum,$group);
+ if (keys(%curr_group) > 0) {
+ $noremove=1;
+ }
+ }
+ $nocut=1;
+ $nocopy=1;
+ } elsif ($url =~ m{^\Q/adm/$cdom/$cnum/\E(\w+)/smppg$}) {
+ my $group = $1;
+ if ($env{'form.folderpath'} =~ /^default&[^\&]+\&group_allfolders\&[^\&]+\&\Qgroup_folder_$group\E\&[^\&]+$/) {
+ my %curr_group = &Apache::longroup::coursegroups($cdom,$cnum,$group);
+ my %groupsettings = &Apache::longroup::get_group_settings($curr_group{$group});
+ if (keys(%groupsettings) > 0) {
+ $noremove=1;
+ }
+ $nocut=1;
+ $nocopy=1;
+ }
+ } elsif ($env{'form.folderpath'} =~ /^default&[^\&]+\&group_allfolders\&[^\&]+\&group_folder_(\w+)\&/) {
+ my $group = $1;
+ my %curr_group = &Apache::longroup::coursegroups($cdom,$cnum,$group);
+ if ($url =~ /group_boards_\Q$group\E/) {
+ my %curr_group = &Apache::longroup::coursegroups($cdom,$cnum,$group);
+ my %groupsettings = &Apache::longroup::get_group_settings($curr_group{$group});
+ if (keys(%groupsettings) > 0) {
+ if (ref($groupsettings{'functions'}) eq 'HASH') {
+ if ($groupsettings{'functions'}{'discussion'} eq 'on') {
+ $noremove=1;
+ }
+ }
+ }
+ $nocut=1;
+ $nocopy=1;
+ }
+ }
+ my ($copylink,$cutlink,$removelink);
+ my $skip_confirm = 0;
+ if ( $folder =~ /^supplemental/
+ || ($url =~ m{( /smppg$
+ |/syllabus$
+ |/aboutme$
+ |/navmaps$
+ |/bulletinboard$
+ |\.html$)}x)
+ || $isexternal) {
+ $skip_confirm = 1;
+ }
+
+ if ($nocopy) {
+ $copylink=(<$lt{'cp'}
+ENDCOPY
+ } else {
+ $copylink=(<$lt{'cp'}
+ENDCOPY
+ }
+ if ($nocut) {
+ $cutlink=(<$lt{'ct'}
+ENDCUT
+ } else {
+ $cutlink=(<$lt{'ct'}
+ENDCUT
+ }
+ if ($noremove) {
+ $removelink=(<$lt{'rm'}
+ENDREM
+ } else {
+ $removelink=(<$lt{'rm'}
+ENDREM
+ }
+ unless ($isexternal) {
+ $renamelink=(<$lt{'rn'}
+ENDREN
+ }
+ $form_start = '
+ ';
$line.=(<
-
-
-
-
-
-
-
-
-
-
-$selectbox
-
-
-$lt{'rm'}
-
-$lt{'rn'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $form_start
+ $form_common
+ $selectbox
+ $form_end
+
+
+$removelink
+$cutlink
+$copylink
+
+
END
+
}
# Figure out what kind of a resource this is
my ($extension)=($url=~/\.(\w+)$/);
my $uploaded=($url=~/^\/*uploaded\//);
my $icon=&Apache::loncommon::icon($url);
- my $isfolder=0;
- my $folderarg;
+ my $isfolder;
+ my $ispage;
+ my $containerarg;
if ($uploaded) {
- if ($extension eq 'sequence') {
- $icon=$iconpath.'/folder_closed.gif';
- $url=~/$coursenum\/([\/\w]+)\.sequence$/;
- $url='/adm/coursedocs?';
- $folderarg=$1;
- $isfolder=1;
- }
+ if (($extension eq 'sequence') || ($extension eq 'page')) {
+ $url=~/\Q$coursenum\E\/([\/\w]+)\.\Q$extension\E$/;
+ $containerarg = $1;
+ if ($extension eq 'sequence') {
+ $icon=$iconpath.'navmap.folder.closed.gif';
+ $isfolder=1;
+ } else {
+ $icon=$iconpath.'page.gif';
+ $ispage=1;
+ }
+ if ($allowed) {
+ $url='/adm/coursedocs?';
+ } else {
+ $url='/adm/supplemental?';
+ }
+ } else {
+ &Apache::lonnet::allowuploaded('/adm/coursedoc',$url);
+ }
}
- $url=~s/^http\&colon\;\/\//\/adm\/wrapper\/ext\//;
- if ((!$isfolder) && ($residx) && ($folder!~/supplemental/)) {
- my $symb=&Apache::lonnet::symbclean(
- &Apache::lonnet::declutter('uploaded/'.
- $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}.'/'.
- $ENV{'course.'.$ENV{'request.course.id'}.'.num'}.'/'.$folder.
- '.sequence').
- '___'.$residx.'___'.
- &Apache::lonnet::declutter($url));
- (undef,undef,$url)=&Apache::lonnet::decode_symb($symb);
- $url=&Apache::lonnet::clutter($url);
- if ($url=~/^\/*uploaded\//) {
- $url=~/\.(\w+)$/;
- my $embstyle=&Apache::loncommon::fileembstyle($1);
- if (($embstyle eq 'img') || ($embstyle eq 'emb')) {
- $url='/adm/wrapper'.$url;
- } elsif ($embstyle eq 'ssi') {
- #do nothing with these
- } elsif ($url!~/\.(sequence|page)$/) {
- $url='/adm/coursedocs/showdoc'.$url;
- }
- }
- $url.=(($url=~/\?/)?'&':'?').'symb='.&Apache::lonnet::escape($symb);
- }
- my $parameterset=' ';
- if ($isfolder) {
- my $foldername=&Apache::lonnet::escape($foldertitle);
- my $folderpath=$ENV{'form.folderpath'};
+
+ my ($editlink,$extresform);
+ my $orig_url = $url;
+ $orig_url=~s{http(:|:)//https(:|:)//}{https$2//};
+ $url=~s{^http(|s)(:|:)//}{/adm/wrapper/ext/};
+ if (!$supplementalflag && $residx && $symb) {
+ if ((!$isfolder) && (!$ispage)) {
+ (undef,undef,$url)=&Apache::lonnet::decode_symb($symb);
+ $url=&Apache::lonnet::clutter($url);
+ if ($url=~/^\/*uploaded\//) {
+ $url=~/\.(\w+)$/;
+ my $embstyle=&Apache::loncommon::fileembstyle($1);
+ if (($embstyle eq 'img') || ($embstyle eq 'emb')) {
+ $url='/adm/wrapper'.$url;
+ } elsif ($embstyle eq 'ssi') {
+ #do nothing with these
+ } elsif ($url!~/\.(sequence|page)$/) {
+ $url='/adm/coursedocs/showdoc'.$url;
+ }
+ } elsif ($url=~m|^/ext/|) {
+ $url='/adm/wrapper'.$url;
+ }
+ if (&Apache::lonnet::symbverify($symb,$url)) {
+ $url.=(($url=~/\?/)?'&':'?').'symb='.&escape($symb);
+ } else {
+ $url='';
+ }
+ }
+ }
+ my ($rand_pick_text,$rand_order_text);
+ if ($isfolder || $ispage || $extension eq 'sequence' || $extension eq 'page') {
+ my $foldername=&escape($foldertitle);
+ my $folderpath=$env{'form.folderpath'};
if ($folderpath) { $folderpath.='&' };
- $folderpath.=$folderarg.'&'.$foldername;
- $url.='folderpath='.&Apache::lonnet::escape($folderpath);
- $parameterset=&mt('Randomly Pick: ').
- ' ';
- }
- $line.=' '.
- "$title ";
+ if (!$allowed && $supplementalflag) {
+ $folderpath.=$containerarg.'&'.$foldername;
+ $url.='folderpath='.&escape($folderpath);
+ } else {
+# Append randompick number, hidden, and encrypted with ":" to foldername,
+# so it gets transferred between levels
+ $folderpath.=$containerarg.'&'.$foldername.
+ ':'.(&LONCAPA::map::getparameter($orderidx,
+ 'parameter_randompick'))[0]
+ .':'.((&LONCAPA::map::getparameter($orderidx,
+ 'parameter_hiddenresource'))[0]=~/^yes$/i)
+ .':'.((&LONCAPA::map::getparameter($orderidx,
+ 'parameter_encrypturl'))[0]=~/^yes$/i)
+ .':'.((&LONCAPA::map::getparameter($orderidx,
+ 'parameter_randomorder'))[0]=~/^yes$/i)
+ .':'.$ispage;
+ $url.='folderpath='.&escape($folderpath);
+ my $rpicknum = (&LONCAPA::map::getparameter($orderidx,
+ 'parameter_randompick'))[0];
+ my $rpckchk;
+ if ($rpicknum) {
+ $rpckchk = ' checked="checked"';
+ }
+ my $formname = 'edit_rpick_'.$orderidx;
+ $rand_pick_text =
+'';
+ my $ro_set=
+ ((&LONCAPA::map::getparameter($orderidx,'parameter_randomorder'))[0]=~/^yes$/i?' checked="checked"':'');
+ $rand_order_text =
+$form_start.
+$form_common.'
+ '.&mt('Random Order').' ';
+ }
+ } elsif ($supplementalflag && !$allowed) {
+ $url .= ($url =~ /\?/) ? '&':'?';
+ $url .= 'folderpath='.&HTML::Entities::encode($esc_path,'<>&"');
+ if ($title) {
+ $url .= '&title='.&HTML::Entities::encode($renametitle,'<>&"');
+ }
+ if ($isexternal && $orderidx) {
+ $url .= '&idx='.$orderidx;
+ }
+ }
+ my ($tdalign,$tdwidth);
+ if ($allowed) {
+ my $fileloc =
+ &Apache::lonnet::declutter(&Apache::lonnet::filelocation('',$orig_url));
+ if ($isexternal) {
+ ($editlink,$extresform) =
+ &Apache::lonextresedit::extedit_form(0,$residx,$orig_url,$title,$pathitem);
+ } elsif (!$isfolder && !$ispage) {
+ my ($cfile,$home,$switchserver,$forceedit,$forceview) =
+ &Apache::lonnet::can_edit_resource($fileloc,$coursenum,$coursedom,$orig_url);
+ if (($cfile ne '') && ($symb ne '' || $supplementalflag)) {
+ my $jscall =
+ &Apache::lonhtmlcommon::jump_to_editres($cfile,$home,
+ $switchserver,
+ $forceedit,
+ undef,$symb,
+ &escape($env{'form.folderpath'}),
+ $renametitle,'','',1);
+ if ($jscall) {
+ $editlink = ''.&mt('Edit').' '."\n";
+ }
+ }
+ }
+ $tdalign = ' align="right" valign="top"';
+ $tdwidth = ' width="80%"';
+ }
+ my $reinit;
+ if ($crstype eq 'Community') {
+ $reinit = &mt('(re-initialize community to access)');
+ } else {
+ $reinit = &mt('(re-initialize course to access)');
+ }
+ $line.=''.$editlink.$renamelink;
+ if (($url=~m{/adm/(coursedocs|supplemental)}) || (!$allowed && $url)) {
+ $line.=' ';
+ } elsif ($url) {
+ $line.=&Apache::loncommon::modal_link($url.(($url=~/\?/)?'&':'?').'inhibitmenu=yes',
+ ' ',600,500);
+ } else {
+ $line.=' ';
+ }
+ $line.=' ';
+ if (($url=~m{/adm/(coursedocs|supplemental)}) || (!$allowed && $url)) {
+ $line.=''.$title.' ';
+ } elsif ($url) {
+ $line.=&Apache::loncommon::modal_link($url.(($url=~/\?/)?'&':'?').'inhibitmenu=yes',
+ $title,600,500);
+ } else {
+ $line.=$title.' '.$reinit.' ';
+ }
+ $line.="$extresform ";
+ $rand_pick_text = ' ' if ($rand_pick_text eq '');
+ $rand_order_text = ' ' if ($rand_order_text eq '');
if (($allowed) && ($folder!~/^supplemental/)) {
my %lt=&Apache::lonlocal::texthash(
'hd' => 'Hidden',
- 'ec' => 'URL hidden',
- 'sp' => 'Store Parameters');
+ 'ec' => 'URL hidden');
my $enctext=
- ((&Apache::lonratedt::getparameter($orderidx,'parameter_encrypturl'))[0]=~/^yes$/i?' checked="1"':'');
+ ((&LONCAPA::map::getparameter($orderidx,'parameter_encrypturl'))[0]=~/^yes$/i?' checked="checked"':'');
my $hidtext=
- ((&Apache::lonratedt::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i?' checked="1"':'');
+ ((&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i?' checked="checked"':'');
$line.=(<
- $lt{'hd'}
-
- $lt{'ec'}
-$parameterset
-
-
-
+
+ $form_start
+ $form_common
+ $lt{'hd'}
+ $form_end
+
+ $form_start
+ $form_common
+ $lt{'ec'}
+ $form_end
+
+ $rand_pick_text
+ $rand_order_text
ENDPARMS
}
- $line.=" ";
+ $line.=&Apache::loncommon::end_data_table_row();
return $line;
}
-# ---------------------------------------------------------------- tie the hash
+sub newmap_suffix {
+ my ($area,$container,$coursedom,$coursenum) = @_;
+ my ($prefix,$idtype,$errtext,$locknotfreed);
+ $prefix = 'docs';
+ if ($area eq 'supplemental') {
+ $prefix = 'supp';
+ }
+ $prefix .= $container;
+ $idtype = 'concat';
+ my ($suffix,$freedlock,$error) =
+ &Apache::lonnet::get_timebased_id($prefix,'num','uploadedmaps',
+ $coursedom,$coursenum);
+ if (!$suffix) {
+ $errtext = &mt('Failed to acquire a unique timestamp-based suffix for the new folder/page.');
+ if ($error) {
+ $errtext .= ' '.$error;
+ }
+ }
+ if ($freedlock ne 'ok') {
+ $locknotfreed = ''.&mt('There was a problem removing a lockfile. This will prevent creation of additional folders or composite pages in this course. Please contact the domain coordinator for your LON-CAPA domain.').'
';
+ }
+ return ($suffix,$errtext,$locknotfreed);
+}
+
+=pod
+
+=item tiehash()
+
+tie the hash
+
+=cut
sub tiehash {
+ my ($mode)=@_;
$hashtied=0;
- if ($ENV{'request.course.fn'}) {
- if (tie(%hash,'GDBM_File',$ENV{'request.course.fn'}.".db",
- &GDBM_READER(),0640)) {
+ if ($env{'request.course.fn'}) {
+ if ($mode eq 'write') {
+ if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.".db",
+ &GDBM_WRCREAT(),0640)) {
+ $hashtied=2;
+ }
+ } else {
+ if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.".db",
+ &GDBM_READER(),0640)) {
$hashtied=1;
- }
- }
+ }
+ }
+ }
}
sub untiehash {
if ($hashtied) { untie %hash; }
$hashtied=0;
+ return OK;
}
-# --------------------------------------------------------------- check on this
+
+
sub checkonthis {
my ($r,$url,$level,$title)=@_;
+ $url=&unescape($url);
$alreadyseen{$url}=1;
$r->rflush();
if (($url) && ($url!~/^\/uploaded\//) && ($url!~/\*$/)) {
$r->print("\n ");
+ if ($level==0) {
+ $r->print(" ");
+ }
for (my $i=0;$i<=$level*5;$i++) {
$r->print(' ');
}
@@ -669,8 +2675,8 @@ sub checkonthis {
if ($url=~/^\/res\//) {
my $result=&Apache::lonnet::repcopy(
&Apache::lonnet::filelocation('',$url));
- if ($result==OK) {
- $r->print(''.&mt('ok').' ');
+ if ($result eq 'ok') {
+ $r->print(''.&mt('ok').' ');
$r->rflush();
&Apache::lonnet::countacc($url);
$url=~/\.(\w+)$/;
@@ -680,84 +2686,141 @@ sub checkonthis {
for (my $i=0;$i<=$level*5;$i++) {
$r->print(' ');
}
- $r->print('- '.&mt('Rendering').': ');
- my $oldpath=$ENV{'request.filename'};
- $ENV{'request.filename'}=&Apache::lonnet::filelocation('',$url);
- &Apache::lonxml::xmlparse($r,'web',
- &Apache::lonnet::getfile(
- &Apache::lonnet::filelocation('',$url)));
- undef($Apache::lonhomework::parsing_a_problem);
- $ENV{'request.filename'}=$oldpath;
- if (($Apache::lonxml::errorcount) ||
- ($Apache::lonxml::warningcount)) {
- if ($Apache::lonxml::errorcount) {
- $r->print(''.
- $Apache::lonxml::errorcount.' '.
- &mt('error(s)').' ');
+ $r->print('- '.&mt('Rendering:').' ');
+ my ($errorcount,$warningcount)=split(/:/,
+ &Apache::lonnet::ssi_body($url,
+ ('grade_target'=>'web',
+ 'return_only_error_and_warning_counts' => 1)));
+ if (($errorcount) ||
+ ($warningcount)) {
+ if ($errorcount) {
+ $r->print(''.
+ &mt('[quant,_1,error]',$errorcount).' ');
}
- if ($Apache::lonxml::warningcount) {
- $r->print(''.
- $Apache::lonxml::warningcount.' '.
- &mt('warning(s)').' ');
+ if ($warningcount) {
+ $r->print(''.
+ &mt('[quant,_1,warning]',$warningcount).' ');
}
} else {
- $r->print(''.&mt('ok').' ');
+ $r->print(''.&mt('ok').' ');
}
$r->rflush();
}
my $dependencies=
&Apache::lonnet::metadata($url,'dependencies');
- foreach (split(/\,/,$dependencies)) {
- if (($_=~/^\/res\//) && (!$alreadyseen{$_})) {
- &checkonthis($r,$_,$level+1);
+ foreach my $dep (split(/\,/,$dependencies)) {
+ if (($dep=~/^\/res\//) && (!$alreadyseen{$dep})) {
+ &checkonthis($r,$dep,$level+1);
}
}
- } elsif ($result==HTTP_SERVICE_UNAVAILABLE) {
- $r->print(''.&mt('connection down').' ');
- } elsif ($result==HTTP_NOT_FOUND) {
+ } elsif ($result eq 'unavailable') {
+ $r->print(''.&mt('connection down').' ');
+ } elsif ($result eq 'not_found') {
unless ($url=~/\$/) {
- $r->print(''.&mt('not found').' ');
+ $r->print(''.&mt('not found').' ');
} else {
- $r->print(''.&mt('unable to verify variable URL').' ');
+ $r->print(''.&mt('unable to verify variable URL').' ');
}
} else {
- $r->print(''.&mt('access denied').' ');
+ $r->print(''.&mt('access denied').' ');
}
- }
- }
+ }
+ }
}
-#
-# -------------------------------------------------------------- Verify Content
-#
-sub verifycontent {
- my $r=shift;
- my $loaderror=&Apache::lonnet::overloaderror($r);
- if ($loaderror) { return $loaderror; }
- $r->print('Verify Content '.
- &Apache::loncommon::bodytag('Verify Course Documents'));
+=pod
+
+=item list_symbs()
+
+List Content Identifiers
+
+=cut
+
+sub list_symbs {
+ my ($r) = @_;
+
+ my $crstype = &Apache::loncommon::course_type();
+ $r->print(&Apache::loncommon::start_page('List of Content Identifiers'));
+ $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content Identifiers'));
+ $r->print(&startContentScreen('tools'));
+ my $navmap = Apache::lonnavmaps::navmap->new();
+ if (!defined($navmap)) {
+ $r->print(''.&mt('Retrieval of List Failed').' '.
+ ''.
+ &mt('Unable to retrieve information about course contents').
+ '
');
+ &Apache::lonnet::logthis('Symb list failed - could not create navmap object in '.lc($crstype).':'.$env{'request.course.id'});
+ } else {
+ $r->print(''.&mt("$crstype Content Identifiers").' '.
+ &Apache::loncommon::start_data_table().
+ &Apache::loncommon::start_data_table_header_row().
+ ''.&mt('Title').' '.&mt('Identifier').' '.
+ &Apache::loncommon::end_data_table_header_row()."\n");
+ my $count;
+ foreach my $res ($navmap->retrieveResources()) {
+ $r->print(&Apache::loncommon::start_data_table_row().
+ ''.$res->compTitle().' '.
+ ''.$res->symb().' '.
+ &Apache::loncommon::end_data_table_row());
+ $count ++;
+ }
+ if (!$count) {
+ $r->print(&Apache::loncommon::start_data_table_row().
+ ''.&mt("$crstype is empty").' '.
+ &Apache::loncommon::end_data_table_row());
+ }
+ $r->print(&Apache::loncommon::end_data_table());
+ }
+ $r->print(&endContentScreen());
+}
+
+
+sub verifycontent {
+ my ($r) = @_;
+ my $crstype = &Apache::loncommon::course_type();
+ $r->print(&Apache::loncommon::start_page('Verify '.$crstype.' Documents'));
+ $r->print(&Apache::lonhtmlcommon::breadcrumbs('Verify '.$crstype.' Documents'));
+ $r->print(&startContentScreen('tools'));
+ $r->print(''.&mt($crstype.' content verification').' ');
$hashtied=0;
undef %alreadyseen;
%alreadyseen=();
&tiehash();
- foreach (keys %hash) {
- if (($_=~/^src\_(.+)$/) && (!$alreadyseen{$hash{$_}})) {
- &checkonthis($r,$hash{$_},0,$hash{'title_'.$1});
+
+ foreach my $key (keys(%hash)) {
+ if ($hash{$key}=~/\.(page|sequence)$/) {
+ if (($key=~/^src_/) && ($alreadyseen{&unescape($hash{$key})})) {
+ $r->print(''.
+ &mt('The following sequence or page is included more than once in your '.$crstype.':').' '.
+ &unescape($hash{$key}).' '.
+ &mt('Note that grading records for problems included in this sequence or folder will overlap.').' ');
+ }
+ }
+ if (($key=~/^src\_(.+)$/) && (!$alreadyseen{&unescape($hash{$key})})) {
+ &checkonthis($r,$hash{$key},0,$hash{'title_'.$1});
}
}
&untiehash();
- $r->print(''.&mt('Done').'. '.''.
- &mt('Return to DOCS').' ');
+ $r->print(''.&mt('Done').'
');
+ $r->print(&endContentScreen());
}
-# -------------------------------------------------------------- Check Versions
+
+sub devalidateversioncache {
+ my $src=shift;
+ &Apache::lonnet::devalidate_cache_new('courseresversion',$env{'request.course.id'}.'_'.
+ &Apache::lonnet::clutter($src));
+}
sub checkversions {
- my $r=shift;
- $r->print('Check Versions '.
- &Apache::loncommon::bodytag('Check Course Document Versions'));
+ my ($r) = @_;
+ my $crstype = &Apache::loncommon::course_type();
+ $r->print(&Apache::loncommon::start_page("Check $crstype Document Versions"));
+ $r->print(&Apache::lonhtmlcommon::breadcrumbs("Check $crstype Document Versions"));
+ $r->print(&startContentScreen('tools'));
+
my $header='';
my $startsel='';
my $monthsel='';
@@ -768,56 +2831,62 @@ sub checkversions {
my $starttime=0;
my $haschanged=0;
my %setversions=&Apache::lonnet::dump('resourceversions',
- $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
- $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
+ $env{'course.'.$env{'request.course.id'}.'.domain'},
+ $env{'course.'.$env{'request.course.id'}.'.num'});
$hashtied=0;
&tiehash();
my %newsetversions=();
- if ($ENV{'form.setmostrecent'}) {
+ if ($env{'form.setmostrecent'}) {
$haschanged=1;
- foreach (keys %hash) {
- if ($_=~/^ids\_(\/res\/.+)$/) {
+ foreach my $key (keys(%hash)) {
+ if ($key=~/^ids\_(\/res\/.+)$/) {
$newsetversions{$1}='mostrecent';
+ &devalidateversioncache($1);
}
}
- } elsif ($ENV{'form.setcurrent'}) {
+ } elsif ($env{'form.setcurrent'}) {
$haschanged=1;
- foreach (keys %hash) {
- if ($_=~/^ids\_(\/res\/.+)$/) {
+ foreach my $key (keys(%hash)) {
+ if ($key=~/^ids\_(\/res\/.+)$/) {
my $getvers=&Apache::lonnet::getversion($1);
if ($getvers>0) {
$newsetversions{$1}=$getvers;
+ &devalidateversioncache($1);
}
}
}
- } elsif ($ENV{'form.setversions'}) {
+ } elsif ($env{'form.setversions'}) {
$haschanged=1;
- foreach (keys %ENV) {
- if ($_=~/^form\.set_version_(.+)$/) {
+ foreach my $key (keys(%env)) {
+ if ($key=~/^form\.set_version_(.+)$/) {
my $src=$1;
- if (($ENV{$_}) && ($ENV{$_} ne $setversions{$src})) {
- $newsetversions{$src}=$ENV{$_};
+ if (($env{$key}) && ($env{$key} ne $setversions{$src})) {
+ $newsetversions{$src}=$env{$key};
+ &devalidateversioncache($src);
}
}
}
}
if ($haschanged) {
if (&Apache::lonnet::put('resourceversions',\%newsetversions,
- $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
- $ENV{'course.'.$ENV{'request.course.id'}.'.num'}) eq 'ok') {
- $r->print(''.&mt('Your Version Settings have been Stored').' ');
+ $env{'course.'.$env{'request.course.id'}.'.domain'},
+ $env{'course.'.$env{'request.course.id'}.'.num'}) eq 'ok') {
+ $r->print(&Apache::loncommon::confirmwrapper(
+ &Apache::lonhtmlcommon::confirm_success(&mt('Your Version Settings have been Saved'))));
} else {
- $r->print(''.&mt('An Error Occured while Attempting to Store your Version Settings').' ');
+ $r->print(&Apache::loncommon::confirmwrapper(
+ &Apache::lonhtmlcommon::confirm_success(&mt('An Error Occured while Attempting to Save your Version Settings'),1)));
}
- &changewarning($r,'');
+ &mark_hash_old();
}
- if ($ENV{'form.timerange'} eq 'all') {
+ &changewarning($r,'');
+ if ($env{'form.timerange'} eq 'all') {
# show all documents
- $header=&mt('All Documents in Course');
- $allsel=1;
- foreach (keys %hash) {
- if ($_=~/^ids\_(\/res\/.+)$/) {
+ $header=&mt('All Documents in '.$crstype);
+ $allsel=' selected="selected"';
+ foreach my $key (keys(%hash)) {
+ if ($key=~/^ids\_(\/res\/.+)$/) {
my $src=$1;
$changes{$src}=1;
}
@@ -825,30 +2894,30 @@ sub checkversions {
} else {
# show documents which changed
%changes=&Apache::lonnet::dump
- ('versionupdate',$ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
- $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
- my $firstkey=(keys %changes)[0];
+ ('versionupdate',$env{'course.'.$env{'request.course.id'}.'.domain'},
+ $env{'course.'.$env{'request.course.id'}.'.num'});
+ my $firstkey=(keys(%changes))[0];
unless ($firstkey=~/^error\:/) {
- unless ($ENV{'form.timerange'}) {
- $ENV{'form.timerange'}=604800;
+ unless ($env{'form.timerange'}) {
+ $env{'form.timerange'}=604800;
}
- my $seltext=&mt('during the last').' '.$ENV{'form.timerange'}.' '
+ my $seltext=&mt('during the last').' '.$env{'form.timerange'}.' '
.&mt('seconds');
- if ($ENV{'form.timerange'}==-1) {
+ if ($env{'form.timerange'}==-1) {
$seltext='since start of course';
- $startsel='selected';
- $ENV{'form.timerange'}=time;
+ $startsel=' selected="selected"';
+ $env{'form.timerange'}=time;
}
- $starttime=time-$ENV{'form.timerange'};
- if ($ENV{'form.timerange'}==2592000) {
+ $starttime=time-$env{'form.timerange'};
+ if ($env{'form.timerange'}==2592000) {
$seltext=&mt('during the last month').' ('.&Apache::lonlocal::locallocaltime($starttime).')';
- $monthsel='selected';
- } elsif ($ENV{'form.timerange'}==604800) {
+ $monthsel=' selected="selected"';
+ } elsif ($env{'form.timerange'}==604800) {
$seltext=&mt('during the last week').' ('.&Apache::lonlocal::locallocaltime($starttime).')';
- $weeksel='selected';
- } elsif ($ENV{'form.timerange'}==86400) {
+ $weeksel=' selected="selected"';
+ } elsif ($env{'form.timerange'}==86400) {
$seltext=&mt('since yesterday').' ('.&Apache::lonlocal::locallocaltime($starttime).')';
- $daysel='selected';
+ $daysel=' selected="selected"';
}
$header=&mt('Content changed').' '.$seltext;
} else {
@@ -856,172 +2925,291 @@ sub checkversions {
}
}
%setversions=&Apache::lonnet::dump('resourceversions',
- $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
- $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
+ $env{'course.'.$env{'request.course.id'}.'.domain'},
+ $env{'course.'.$env{'request.course.id'}.'.num'});
my %lt=&Apache::lonlocal::texthash
- ('st' => 'Version changes since start of Course',
+ ('st' => 'Version changes since start of '.$crstype,
'lm' => 'Version changes since last Month',
'lw' => 'Version changes since last Week',
'sy' => 'Version changes since Yesterday',
'al' => 'All Resources (possibly large output)',
+ 'cd' => 'Change display',
'sd' => 'Display',
'fi' => 'File',
'md' => 'Modification Date',
'mr' => 'Most recently published Version',
- 've' => 'Version used in Course',
- 'vu' => 'Set Version to be used in Course',
-'sv' => 'Set Versions to be used in Course according to Selections below',
+ 've' => 'Version used in '.$crstype,
+ 'vu' => 'Set Version to be used in '.$crstype,
+'sv' => 'Set Versions to be used in '.$crstype.' according to Selections below',
'sm' => 'Keep all Resources up-to-date with most recent Versions (default)',
'sc' => 'Set all Resource Versions to current Version (Fix Versions)',
- 'di' => 'Differences');
+ 'di' => 'Differences',
+ 'save' => 'Save changes',
+ 'vers' => 'Version choice(s) for specific resources',
+ 'act' => 'Actions');
$r->print(<$header