--- loncom/interface/londocs.pm 2007/01/05 17:55:41 1.266
+++ loncom/interface/londocs.pm 2012/07/05 21:33:39 1.489
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Documents
#
-# $Id: londocs.pm,v 1.266 2007/01/05 17:55:41 albertel Exp $
+# $Id: londocs.pm,v 1.489 2012/07/05 21:33:39 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -33,12 +33,16 @@ use Apache::Constants qw(:common :http);
use Apache::imsexport;
use Apache::lonnet;
use Apache::loncommon;
+use Apache::lonhtmlcommon;
use LONCAPA::map();
use Apache::lonratedt();
use Apache::lonxml;
use Apache::lonclonecourse;
use Apache::lonnavmaps;
+use Apache::lonnavdisplay();
+use Apache::lonuserstate();
use HTML::Entities;
+use HTML::TokeParser;
use GDBM_File;
use Apache::lonlocal;
use Cwd;
@@ -53,15 +57,9 @@ my %alreadyseen=();
my $hadchanges;
-# Available help topics
my %help=();
-# Mapread read maps into LONCAPA::map:: 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)=@_;
@@ -76,25 +74,25 @@ sub storemap {
&LONCAPA::map::storemap('/uploaded/'.$coursedom.'/'.$coursenum.'/'.
$map,1);
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'};
@@ -104,816 +102,177 @@ sub authorhosts {
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();
- my $type = &Apache::loncommon::course_type();
- if ($home+$other==0) { return ''; }
- my $output='
');
+ 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') {
+ 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})
@@ -1184,323 +605,827 @@ sub docs_change_log {
if (!($env{'form.show'} eq &mt('all')
|| $shown<=$env{'form.show'})) { last; }
}
- $r->print(&Apache::loncommon::end_data_table());
- $r->print(&Apache::loncommon::end_page());
+ $r->print(&Apache::loncommon::end_data_table()."\n".
+ &makesimpleeditform($pathitem)."\n".
+ '');
+ $r->print(&endContentScreen());
+}
+
+sub update_paste_buffer {
+ my ($coursenum,$coursedom) = @_;
+
+ 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');
+ }
+ $url=~s{http(:|:)//https(:|:)//}{https$2//};
+
+ &Apache::lonnet::appenv({'docs.markedcopy_title' => $title,
+ 'docs.markedcopy_url' => $url});
+ delete($env{'form.markcopy'});
+}
+
+sub print_paste_buffer {
+ my ($r,$container,$folder) = @_;
+ return if (!defined($env{'docs.markedcopy_url'}));
+
+ my $is_external;
+ my $extension = (split(/\./,$env{'docs.markedcopy_url'}))[-1];
+ if ($env{'docs.markedcopy_url'} =~ m{^(?:/adm/wrapper/ext|(?:http|https)(?::|:))//} ) {
+ $is_external = 1;
+ }
+
+ my $canpaste;
+ if ($folder =~ /^supplemental/) {
+ $canpaste = &supp_pasteable($env{'docs.markedcopy_url'});
+ } else {
+ $canpaste = 1;
+ }
+
+ my $pasteinfo;
+ if ($canpaste) {
+ $pasteinfo = '');
+ } else {
+ $r->print('
'.&mt('Paste into Supplemental Content unavailable for this type of content.').'
');
+ }
+ $r->print('');
+}
+
+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 do_paste_from_buffer {
+ my ($coursenum,$coursedom,$folder) = @_;
+
+ if (!$env{'form.pastemarked'}) {
+ return;
+ }
+
+# Supplemental content may only include certain types of content
+ if ($folder =~ /^supplemental/) {
+ unless (&supp_pasteable($env{'docs.markedcopy_url'})) {
+ return &mt('Paste failed: content type is not supported within Supplemental Content');
+ }
+ }
+
+# paste resource to end of list
+ my $url=&LONCAPA::map::qtescape($env{'docs.markedcopy_url'});
+ my $title=&LONCAPA::map::qtescape($env{'docs.markedcopy_title'});
+# Maps need to be copied first
+ my ($oldurl,%removefrommap,%addedmaps,%rewrites,%copies,%dbcopies,%zombies,%params,
+ %moves,$srcdom,$srcnum);
+ $oldurl = $url;
+ if ($url=~/\.(page|sequence)$/) {
+ # If pasting a map, check if map contains other maps
+ &contained_map_check($url,$folder,\%removefrommap,\%addedmaps);
+ if (keys(%addedmaps) > 0) {
+ &reinit_role($coursedom,$coursenum,$env{"course.$env{'request.course.id'}.home"});
+ }
+ my %allmaps;
+ my $navmap = Apache::lonnavmaps::navmap->new();
+ if (defined($navmap)) {
+ foreach my $res ($navmap->retrieveResources(undef,sub { $_[0]->is_map() },1,0,1)) {
+ $allmaps{$res->src()} = 1;
+ }
+ }
+ if ($url=~ m{^/uploaded/}) {
+ $title=&mt('Copy of').' '.$title;
+ }
+ my $newid=$$.int(rand(100)).time;
+ 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);
+ }
+ $oldid = $path.$prefix.$ancestor;
+ my $counter = 0;
+ my $newurl=$oldid.$newid.'.'.$ext;
+ my $is_unique = &uniqueness_check($newurl);
+ if ($allmaps{$newurl}) {
+ $is_unique = 0;
+ }
+ while (!$is_unique && $allmaps{$newurl} && $counter < 100) {
+ $counter ++;
+ $newid ++;
+ $newurl = $oldid.$newid;
+ $is_unique = &uniqueness_check($newurl);
+ }
+ if ($is_unique) {
+ if ($path =~ m{^/uploaded/($match_domain)/($match_courseid)/$}) {
+ $srcdom = $1;
+ $srcnum = $2;
+ if (($1 ne $coursedom) && ($2 ne $coursenum)) {
+ my $srcdom = $1;
+ my $srcnum = $2;
+ if ($env{"user.priv.cm./$srcdom/$srcnum"} =~ /\Q:mdc&F\E/) {
+ &url_paste_fixups($oldid,$ext,$coursedom,$coursenum,
+ \%allmaps, \%rewrites,\%copies,\%dbcopies,\%zombies,\%params);
+ } else {
+ return &mt('Paste failed: Item is from a different course which you do not have rights to edit');
+ }
+ }
+ }
+ } else {
+ if ($url=~/\.page$/) {
+ return &mt('Paste failed: an error occurred creating a unique URL for the composite page');
+ } else {
+ return &mt('Paste failed: an error occurred creating a unique URL for the folder');
+ }
+ }
+ my $storefn=$newurl;
+ $storefn=~s{^/\w+/$match_domain/$match_username/}{};
+ my $paste_map_result =
+ &Apache::lonclonecourse::writefile($env{'request.course.id'},$storefn,
+ &Apache::lonnet::getfile($url));
+ if ($paste_map_result eq '/adm/notfound.html') {
+ if ($url=~/\.page$/) {
+ return &mt('Paste failed: an error occurred saving the composite page');
+ } else {
+ return &mt('Paste failed: an error occurred saving the folder');
+ }
+ }
+ $url = $newurl;
+ } elsif ($url=~m {^/res/}) {
+# published maps can only exists once, so remove it from paste buffer when done
+ &Apache::lonnet::delenv('docs.markedcopy');
+ if ($allmaps{$url}) {
+ return &mt('Paste failed: only one instance of a particular published sequence or page is allowed within each course.');
+ }
+ }
+ } elsif ($url =~ m{^/uploaded/($match_domain)/($match_courseid)/}) {
+ if (($1 ne $coursedom) || ($2 ne $coursenum)) {
+ $srcdom = $1;
+ $srcnum = $2;
+ 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');
+ }
+ }
+ }
+ 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;
+ $title=&mt('Copy of').' '.$title;
+ }
+ }
+ my ($relpath,$oldprefix,$prefixchg);
+ if ($url =~ m{^/uploaded/$match_domain/$match_courseid/(docs|supplemental)/(.+)$}) {
+ $oldprefix = $1;
+ $relpath = $2;
+ if (($folder =~ /^supplemental/) && ($oldprefix eq 'docs')) {
+ $prefixchg = 1;
+ } elsif (($folder =~ /^default/) && ($oldprefix eq 'supplemental')) {
+ $prefixchg = 1;
+ }
+ }
+ $title = &LONCAPA::map::qtunescape($title);
+ my $ext='false';
+ if ($url=~m{^http(|s)://}) { $ext='true'; }
+ $url = &LONCAPA::map::qtunescape($url);
+# Now insert the URL at the bottom
+ my $newidx = &LONCAPA::map::getresidx($url);
+ if ($relpath ne '') {
+ my ($prefix,$subdir,$rem) = ($relpath =~ m{^(default|\d+)/(\d+)/(.+)$});
+ my ($newloc,$newsubdir) = ($folder =~ /^(default|supplemental)_?(\d*)/);
+ my $newprefix = $newloc;
+ if ($newloc eq 'default') {
+ $newprefix = 'docs';
+ }
+ if ($newsubdir eq '') {
+ $newsubdir = 'default';
+ }
+ if (($prefixchg) || ($srcdom ne '') && ($srcnum ne '')) {
+ my $newpath = "$newprefix/$newsubdir/$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{/+$}{/};
+ $moves{$oldurl} = $newsubpath;
+ }
+ }
+ }
+ my $noparams = 0;
+ if ((ref($params{$oldurl}) eq 'HASH') && ($relpath ne '') && ($folder =~ /^supplemental/)) {
+ $noparams = 1;
+ }
+ &apply_fixups($coursedom,$coursenum,$oldurl,$url,$noparams,\%rewrites,\%copies,
+ \%dbcopies,\%zombies,\%params,\%moves);
+ if ($env{'docs.markedcopy_supplemental'}) {
+ if ($folder =~ /^supplemental/) {
+ $title = $env{'docs.markedcopy_supplemental'};
+ } else {
+ (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);
+ return 'ok';
+# Store the result
+}
+
+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,$addedmaps) = @_;
+ 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'}};
+ next;
+ }
+ }
+ if ($ressrc =~ /\.(sequence|page)$/) {
+ if (ref($addedmaps->{$ressrc}) eq 'ARRAY') {
+ push(@{$addedmaps->{$ressrc}},$url);
+ } else {
+ $addedmaps->{$ressrc} = [$url];
+ }
+ &contained_map_check($ressrc,$folder,$removefrommap,$addedmaps);
+ }
+ } elsif ($token->[1] !~ /^resource|map|link$/) {
+ if ($folder =~ /^supplemental/) {
+ $removefrommap->{$url}{$token->[1]};
+ }
+ }
+ }
+ }
+ return;
+}
+
+sub reinit_role {
+ my ($cdom,$cnum,$chome) = @_;
+ my ($furl,$ferr) = &Apache::lonuserstate::readmap("$cdom/$cnum");
+ unless ($ferr) {
+ &Apache::loncommon::update_content_constraints($cdom,$cnum,$chome,$cdom.'_'.$cnum);
+ }
+ return;
+}
+
+sub url_paste_fixups {
+ my ($oldurl,$ext,$cdom,$cnum,$allmaps,$rewrites,$copies,$dbcopies,$zombies,$params) = @_;
+ my $file = &Apache::lonnet::getfile("$oldurl.$ext");
+ return if ($file eq '-1');
+ my $parser = HTML::TokeParser->new(\$file);
+ $parser->attr_encoded(1);
+ 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 '');
+ next if ($token->[2]->{'type'} eq 'external');
+ my $id = $token->[2]->{'id'};
+ if ($token->[2]->{'type'} eq 'zombie') {
+ $zombies->{$oldurl}{$ressrc} = $id;
+ } elsif ($ressrc =~ m{^/uploaded/($match_domain)/($match_courseid)/(.+)}) {
+ my $srccdom = $1;
+ my $srccnum = $2;
+ my $rem = $3;
+ if (($srccdom ne $cdom) || ($srccnum ne $cnum)) {
+ if ($rem =~ /^(default|supplemental)(_?\d*).(sequence|page)$/) {
+ $rewrites->{$oldurl}{$ressrc} = $id;
+ &url_paste_fixups($ressrc,$3,$cdom,$cnum,$allmaps,$rewrites,$copies,$dbcopies,$zombies,$params);
+ } else {
+ $rewrites->{$oldurl}{$ressrc} = $id;
+ $copies->{$oldurl}{$ressrc} = $id;
+ }
+ }
+ } elsif ($ressrc =~ m{^/adm/($match_domain)/($match_courseid)/(.+)$}) {
+ my $srccdom = $1;
+ my $srccnum = $2;
+ if (($srccdom ne $cdom) || ($srccnum ne $cnum)) {
+ $rewrites->{$oldurl}{$ressrc} = $id;
+ $dbcopies->{$oldurl}{$ressrc} = $id;
+ }
+ } elsif ($ressrc =~ m{^/public/($match_domain)/($match_courseid)/(.+)$}) {
+ my $srccdom = $1;
+ my $srccnum = $2;
+ if (($srccdom ne $cdom) || ($srccnum ne $cnum)) {
+ $rewrites->{$oldurl}{$ressrc} = $id;
+ $dbcopies->{$oldurl}{$ressrc} = $id;
+ }
+ }
+ } elsif ($token->[1] eq 'param') {
+ 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;
+}
+
+sub apply_fixups {
+ my ($cdom,$cnum,$oldurl,$url,$noparams,$rewrites,$copies,$dbcopies,$zombies,$params,
+ $moves) = @_;
+ my (%newdb,%newdoc);
+ if (ref($dbcopies->{$oldurl}) eq 'HASH') {
+ foreach my $item (keys(%{$dbcopies->{$oldurl}})) {
+ $newdb{$item} = &dbcopy($item);
+ }
+ }
+ my @allcopies;
+ if (ref($copies->{$oldurl}) eq 'HASH') {
+ push(@allcopies,keys(%{$copies->{$oldurl}}));
+ }
+ if ((ref($moves) eq 'HASH') && (exists($moves->{$oldurl}))) {
+ push(@allcopies,$oldurl);
+ }
+ if (@allcopies > 0) {
+ foreach my $item (@allcopies) {
+ my $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);
+ if (&Apache::lonnet::extract_embedded_items(undef,\%allfiles,\%codebase,\$content) 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' => $oldurl,
+ 'context' => 'paste'});
+ if ($numexisting > 0) {
+ if (ref($existing) eq 'HASH') {
+ my ($relpath) = ($item =~ m{^(/uploaded/$match_domain/$match_courseid/(?:docs|supplemental)/(?:default|\d+)/.*/)[^/]+$});
+ foreach my $dep (keys(%{$existing})) {
+ $dep =~ s{^\Q$relpath\E}{};
+ my $depfile = $relpath.$dep;
+ my $depstorefn;
+ if ((ref($copies->{$oldurl}) eq 'HASH') &&
+ ($copies->{$oldurl}{$item})) {
+ $depstorefn = $relpath;
+ $depstorefn =~s{^/\w+/$match_domain/$match_courseid/}{};
+ } elsif ((ref($moves) eq 'HASH') &&
+ (exists($moves->{$oldurl}))) {
+ $depstorefn = $moves->{$oldurl};
+ }
+ $depstorefn .= $dep;
+ my $depcontent = &Apache::lonnet::getfile($depfile);
+ unless ($depcontent eq '-1') {
+ &Apache::lonclonecourse::writefile($env{'request.course.id'},$depstorefn,$depcontent);
+ }
+ }
+ }
+ }
+ }
+ }
+ my $storefn=$item;
+ unless (exists($moves->{$oldurl})) {
+ $storefn=~s{^/\w+/$match_domain/$match_courseid/}{};
+ $newdoc{$item} = &Apache::lonclonecourse::writefile($env{'request.course.id'},$storefn,$content);
+ }
+ }
+ }
+ }
+ if (((ref($rewrites->{$oldurl}) eq 'HASH') || (ref($zombies->{$oldurl}) eq 'HASH')) ||
+ ($noparams) || (keys(%newdb) > 0) || (keys(%newdoc) > 0)) {
+ my $map = &Apache::lonnet::getfile($url);
+ my $newcontent;
+ unless ($map eq '-1') {
+ my $parser = HTML::TokeParser->new(\$map);
+ $parser->attr_encoded(1);
+ while (my $token = $parser->get_token) {
+ if ($token->[0] eq 'S') {
+ next if ($token->[2]->{'type'} eq 'zombie');
+ next if (($token->[1] eq 'param') && $noparams);
+ if ($token->[1] eq 'resource') {
+ my $src = $token->[2]->{'src'};
+ my $id = $token->[2]->{'id'};
+ if (($rewrites->{$oldurl}{$src} eq $id) || ($newdb{$src} ne '')
+ || ($newdoc{$src} ne '')) {
+ if (ref($rewrites->{$oldurl}) eq 'HASH') {
+ if ($rewrites->{$oldurl}{$src} eq $id) {
+ $token->[2]->{'src'} =~ s{^(/uploaded|adm|public)/$match_domain/$match_courseid/}{$1/$cdom/$cnum};
+ }
+ } elsif ($newdb{$src} ne '') {
+ $token->[2]->{'src'} = $newdb{$src};
+ }
+ $newcontent .= "<$token->[1] ";
+ foreach my $attr (@{$token->[3]}) {
+ $newcontent .= ' '.$attr.'="'.$token->[2]->{$attr},'"'
+ }
+ $newcontent .= ' />';
+ } else {
+ $newcontent .= $token->[4]."\n";
+ }
+ }
+ } elsif ($token->[0] eq 'E') {
+ $newcontent .= $token->[2]."\n";
+ }
+ }
+ }
+ my $storefn=$url;
+ $storefn=~s{^/\w+/$match_domain/$match_courseid/}{};
+ my $storeres =
+ &Apache::lonclonecourse::writefile($env{'request.course.id'},$storefn,
+ $newcontent);
+ }
+ 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)=@_;
- my $errtext='';
- my $fatal=0;
- my $container='sequence';
- if ($env{'form.pagepath'}) {
- $container='page';
+ my ($r,$coursenum,$coursedom,$folder,$allowed,$upload_output,$crstype,
+ $supplementalflag,$orderhash,$iconpath)=@_;
+ my $container= ($env{'form.pagepath'}) ? 'page'
+ : 'sequence';
+
+ my ($breadcrumbtrail,$randompick,$ishidden,$isencrypted,$plain,$is_random_order) =
+ &breadcrumbs($allowed,$crstype);
+ $r->print($breadcrumbtrail);
+
+ my $jumpto = "uploaded/$coursedom/$coursenum/$folder.$container";
+
+ unless ($allowed) {
+ $randompick = -1;
}
- ($errtext,$fatal)=
- &mapread($coursenum,$coursedom,$folder.'.'.$container);
+
+ 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]='';
}
- if (defined($env{'form.markcopy'})) {
-# Mark for copying
- my ($title,$url)=split(':',$LONCAPA::map::resources[$LONCAPA::map::order[$env{'form.markcopy'}]]);
- $env{'form.markedcopy_title'}=$title;
- $env{'form.markedcopy_url'}=$url;
- }
- my ($breadcrumbtrail,$randompick,$ishidden,$isencrypted,$plain)=&breadcrumbs($folder);
- $r->print($breadcrumbtrail);
- if ($fatal) {
- $r->print('
'.$errtext.'
');
- } else {
+
# ------------------------------------------------------------ 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
- &snapshotbefore();
- if ($env{'form.changeparms'}) {
- my $idx=$env{'form.setparms'};
-# set parameters
- if ($env{'form.changeparms'} eq 'randompick') {
- if ($env{'form.randpick_'.$idx}) {
- &LONCAPA::map::storeparameter($idx,'parameter_randompick',$env{'form.randpick_'.$idx},'int_pos');
- &remember_parms($idx,'randompick','set',$env{'form.randpick_'.$idx});
- } else {
- &LONCAPA::map::delparameter($idx,'parameter_randompick');
- &remember_parms($idx,'randompick','del');
- }
- }
- if ($env{'form.changeparms'} eq 'hiddenresource') {
- if ($env{'form.hidprs_'.$idx}) {
- &LONCAPA::map::storeparameter($idx,'parameter_hiddenresource','yes','string_yesno');
- &remember_parms($idx,'hiddenresource','set',$env{'form.hidprs_'.$idx});
- } else {
- &LONCAPA::map::delparameter($idx,'parameter_hiddenresource');
- &remember_parms($idx,'hiddenresource','del');
- }
- }
- if ($env{'form.changeparms'} eq 'encrypturl') {
- if ($env{'form.encprs_'.$idx}) {
- &LONCAPA::map::storeparameter($idx,'parameter_encrypturl','yes','string_yesno');
- &remember_parms($idx,'encrypturl','set',$env{'form.encprs_'.$idx});
- } else {
- &LONCAPA::map::delparameter($idx,'parameter_encrypturl');
- &remember_parms($idx,'encrypturl','del');
- }
- }
-# store the changed version
- ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container);
- if ($fatal) {
- $r->print('
'.$errtext.'
');
- return;
- }
- }
+ &snapshotbefore();
- if ($env{'form.newpos'}) {
+ if (&update_parameter()) {
+ ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container);
+ return $errtext if ($fatal);
+ }
+
+ if ($env{'form.newpos'} && $env{'form.currentpos'}) {
# change order
- 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]=$LONCAPA::map::order[$i];
- }
- for ($i=$currentpos;$i<$newpos;$i++) {
- $neworder[$i]=$LONCAPA::map::order[$i+1];
- }
- $neworder[$newpos]=$LONCAPA::map::order[$currentpos];
- for ($i=$newpos+1;$i<=$#LONCAPA::map::order;$i++) {
- $neworder[$i]=$LONCAPA::map::order[$i];
- }
- } else {
-# moving stuff down
- for ($i=0;$i<$newpos;$i++) {
- $neworder[$i]=$LONCAPA::map::order[$i];
- }
- $neworder[$newpos]=$LONCAPA::map::order[$currentpos];
- for ($i=$newpos+1;$i<$currentpos+1;$i++) {
- $neworder[$i]=$LONCAPA::map::order[$i-1];
- }
- for ($i=$currentpos+1;$i<=$#LONCAPA::map::order;$i++) {
- $neworder[$i]=$LONCAPA::map::order[$i];
- }
- }
- @LONCAPA::map::order=@neworder;
-# store the changed version
- ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container);
- if ($fatal) {
- $r->print('
'.$errtext.'
');
- return;
- }
- }
-
- if ($env{'form.pastemarked'}) {
-# paste resource to end of list
- my $url=$env{'form.markedcopy_url'};
- my $title=$env{'form.markedcopy_title'};
-# Maps need to be copied first
- if (($url=~/\.(page|sequence)$/) || ($url=~/^\/uploaded\//)) {
- $title=&mt('Copy of').' '.$title;
- my $newid=$$.time;
- $url=~/^(.+)\.(\w+)$/;
- my $newurl=$1.$newid.'.'.$2;
- my $storefn=$newurl;
- $storefn=~s{^/\w+/$match_domain/$match_username/}{};
- &Apache::lonclonecourse::writefile
- ($env{'request.course.id'},$storefn,
- &Apache::lonnet::getfile($url));
- $url=$newurl;
- }
- $title=~s/\\<\;/g;
- $title=~s/\>/\>\;/g;
- $title=~s/\:/\:/g;
- my $ext='false';
- if ($url=~/^http\:\/\//) { $ext='true'; }
- $url=~s/\:/\:/g;
-# Now insert the URL at the bottom
- my $newidx=&LONCAPA::map::getresidx($url);
- $LONCAPA::map::resources[$newidx]=
- $title.':'.$url.':'.$ext.':normal:res';
- $LONCAPA::map::order[1+$#LONCAPA::map::order]=$newidx;
-# Store the result
- ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container);
- if ($fatal) {
- $r->print('
'.$errtext.'
');
- return;
- }
+ my $res = splice(@LONCAPA::map::order,$env{'form.currentpos'}-1,1);
+ splice(@LONCAPA::map::order,$env{'form.newpos'}-1,0,$res);
- }
- $r->print($upload_output);
- if ($env{'form.cmd'}) {
- my ($cmd,$idx)=split(/\_/,$env{'form.cmd'});
- if ($cmd eq 'del') {
- my (undef,$url)=split(':',$LONCAPA::map::resources[$LONCAPA::map::order[$idx]]);
- if (($url=~m|/+uploaded/\Q$coursedom\E/\Q$coursenum\E/|) &&
- ($url!~/\.(page|sequence|problem|exam|quiz|assess|survey|form|library|task)$/)) {
- &Apache::lonnet::removeuploadedurl($url);
- } else {
- &LONCAPA::map::makezombie($LONCAPA::map::order[$idx]);
- }
- for (my $i=$idx;$i<$#LONCAPA::map::order;$i++) {
- $LONCAPA::map::order[$i] = $LONCAPA::map::order[$i+1];
- }
- $#LONCAPA::map::order--;
- } elsif ($cmd eq 'cut') {
- my (undef,$url)=split(':',$LONCAPA::map::resources[$LONCAPA::map::order[$idx]]);
- &LONCAPA::map::makezombie($LONCAPA::map::order[$idx]);
- for (my $i=$idx;$i<$#LONCAPA::map::order;$i++) {
- $LONCAPA::map::order[$i] = $LONCAPA::map::order[$i+1];
- }
- $#LONCAPA::map::order--;
- } elsif ($cmd eq 'up') {
- if (($idx) && (defined($LONCAPA::map::order[$idx-1]))) {
- my $i=$LONCAPA::map::order[$idx-1];
- $LONCAPA::map::order[$idx-1] = $LONCAPA::map::order[$idx];
- $LONCAPA::map::order[$idx] = $i;
- }
- } elsif ($cmd eq 'down') {
- if (defined($LONCAPA::map::order[$idx+1])) {
- my $i=$LONCAPA::map::order[$idx+1];
- $LONCAPA::map::order[$idx+1] = $LONCAPA::map::order[$idx];
- $LONCAPA::map::order[$idx] = $i;
- }
- } elsif ($cmd eq 'rename') {
- my $ratstr = $LONCAPA::map::resources[$LONCAPA::map::order[$idx]];
- my ($rtitle,@rrest)=split(/\:/,
- $LONCAPA::map::resources[$LONCAPA::map::order[$idx]]);
- my $comment=
- &HTML::Entities::decode($env{'form.title'});
- $comment=~s/\\<\;/g;
- $comment=~s/\>/\>\;/g;
- $comment=~s/\:/\:/g;
- if ($comment=~/\S/) {
- $LONCAPA::map::resources[$LONCAPA::map::order[$idx]]=
- $comment.':'.join(':',@rrest);
- }
-# Devalidate title cache
- my $renamed_url=$rrest[0];
-# Has the :-escaping
- $renamed_url=~s/\&colon\;/\:/g;
- &Apache::lonnet::devalidate_title_cache($renamed_url);
- }
-# Store the changed version
- ($errtext,$fatal)=&storemap($coursenum,$coursedom,
- $folder.'.'.$container);
- if ($fatal) {
- $r->print('
'.$errtext.'
');
- return;
- }
+ ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container);
+ return $errtext if ($fatal);
+ }
+
+ if ($env{'form.pastemarked'}) {
+ my $paste_res =
+ &do_paste_from_buffer($coursenum,$coursedom,$folder);
+ if ($paste_res eq 'ok') {
+ ($errtext,$fatal) = &storemap($coursenum,$coursedom,$folder.'.'.$container);
+ return $errtext if ($fatal);
+ } elsif ($paste_res ne '') {
+ $r->print('
'.$paste_res.'
');
}
+ }
+
+ $r->print($upload_output);
+
+ if (&handle_edit_cmd()) {
+ ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container);
+ return $errtext if ($fatal);
+ }
# Group import/search
- if ($env{'form.importdetail'}) {
- my @imports;
-# &Apache::lonnet::logthis("imp detail ".$env{'form.importdetail'});
- foreach (split(/\&/,$env{'form.importdetail'})) {
- if (defined($_)) {
- my ($name,$url)=split(/\=/,$_);
- $name=&unescape($name);
- $url=&unescape($url);
- push @imports, $name, $url;
- }
- }
-# Store the changed version
- ($errtext,$fatal)=&group_import($coursenum, $coursedom, $folder,
- $container,'londocs',@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);
+ push(@imports, [$name, $url, $residx]);
}
- }
+ }
+ ($errtext,$fatal)=&group_import($coursenum, $coursedom, $folder,
+ $container,'londocs',@imports);
+ return $errtext if ($fatal);
+ }
# Loading a complete map
- if ($env{'form.loadmap'}) {
- if ($env{'form.importmap'}=~/\w/) {
- foreach (&Apache::lonsequence::attemptread(&Apache::lonnet::filelocation('',$env{'form.importmap'}))) {
- my ($title,$url,$ext,$type)=split(/\:/,$_);
- my $idx=&LONCAPA::map::getresidx($url);
- $LONCAPA::map::resources[$idx]=$_;
- $LONCAPA::map::order[$#LONCAPA::map::order+1]=$idx;
- }
-# Store the changed version
- ($errtext,$fatal)=&storemap($coursenum,$coursedom,
- $folder.'.'.$container);
- if ($fatal) {
- $r->print('
'.$errtext.'
');
- return;
- }
- } else {
- $r->print('
'.&mt('No map selected.').'
');
- }
- }
- &log_differences($plain);
- }
+ 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);
+ return $errtext if ($fatal);
+ } else {
+ $r->print('
'.&mt('No map selected.').'
');
+
+ }
+ }
+ &log_differences($plain);
+ }
# ---------------------------------------------------------------- End commands
# ---------------------------------------------------------------- Print screen
- my $idx=0;
- my $shown=0;
- if (($ishidden) || ($isencrypted) || ($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.').'
');
+ $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.')
+ .'
'
+ .&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.')
+ .'
\n");
- if ($env{'form.markedcopy_url'}) {
- $r->print(<');
- }
+ &Apache::loncommon::head_subbox(
+ &Apache::lonhtmlcommon::start_funclist().
+ &Apache::lonhtmlcommon::add_item_funclist(
+ ''.
+ ''.
+ ''.$funcname.'').
+ &Apache::lonhtmlcommon::end_funclist()));
+ }
+ $r->print($to_show);
}
+ return;
}
sub process_file_upload {
my ($upload_output,$coursenum,$coursedom,$allfiles,$codebase,$uploadcmd) = @_;
# upload a file, if present
- my $parseaction;
- if ($env{'form.parserflag'}) {
+ my ($parseaction,$showupload,$nextphase,$mimetype);
+ if ($env{'form.parserflag'}) {
$parseaction = 'parse';
}
- my $phase_status;
my $folder=$env{'form.folder'};
if ($folder eq '') {
$folder='default';
@@ -1519,7 +1444,8 @@ sub process_file_upload {
$LONCAPA::map::resources[1]='';
}
if ($fatal) {
- return 'failed';
+ $$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/) {
@@ -1530,20 +1456,28 @@ sub process_file_upload {
} elsif ($folder =~ /^(default|supplemental)_(\d+)$/) {
$destination .= $2.'/';
}
-# this is for a course, not a user, so set coursedoc flag
-# probably the only place in the system where this should be "1"
+# 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',1,$destination,
+ my $url=&Apache::lonnet::userfileupload('uploaddoc','coursedoc',$destination,
$parseaction,$allfiles,
- $codebase);
+ $codebase,undef,undef,undef,undef,
+ undef,undef,\$mimetype);
+ if ($url =~ m{^/uploaded/\Q$coursedom\E/\Q$coursenum\E.*/([^/]+)$}) {
+ my $stored = $1;
+ $showupload = '
'.&mt('Unable to save file [_1].',''.$filename.'').'
';
+ return;
+ }
my $ext='false';
- if ($url=~/^http\:\/\//) { $ext='true'; }
- $url=~s/\:/\:/g;
+ if ($url=~m{^http://}) { $ext='true'; }
+ $url = &LONCAPA::map::qtunescape($url);
my $comment=$env{'form.comment'};
- $comment=~s/\\<\;/g;
- $comment=~s/\>/\>\;/g;
- $comment=~s/\:/\:/g;
+ $comment = &LONCAPA::map::qtunescape($comment);
if ($folder=~/^supplemental/) {
$comment=time.'___&&&___'.$env{'user.name'}.'___&&&___'.
$env{'user.domain'}.'___&&&___'.$comment;
@@ -1555,132 +1489,147 @@ sub process_file_upload {
($errtext,$fatal)=&storemap($coursenum,$coursedom,
$folder.'.'.$container);
if ($fatal) {
- $$upload_output .= '
'.$errtext.'
';
- return 'failed';
+ $$upload_output = '
'.$errtext.'
';
+ return;
} else {
- if ($parseaction eq 'parse') {
- my $total_embedded = keys(%{$allfiles});
+ if ($parseaction eq 'parse' && $mimetype eq 'text/html') {
+ $$upload_output = $showupload;
+ my $total_embedded = scalar(keys(%{$allfiles}));
if ($total_embedded > 0) {
- my $num = 0;
- $$upload_output .= 'This file contains embedded multimedia objects, which need to be uploaded to LON-CAPA.
- ';
} else {
- $$upload_output .= 'No embedded items identified ';
+ $$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'},
+ pagepath => $env{'form.pagepath'},
+ 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 $phase_status;
+ return $nextphase;
}
-sub process_secondary_uploads {
- my ($upload_output,$coursedom,$coursenum,$formname,$num,$newidx) = @_;
- my $folder=$env{'form.folder'};
- my $destination = 'docs/';
- if ($folder =~ /^supplemental/) {
- $destination = 'supplemental/';
- }
- if (($folder eq 'default') || ($folder eq 'supplemental')) {
- $destination .= 'default/';
- } elsif ($folder =~ /^(default|supplemental)_(\d+)$/) {
- $destination .= $2.'/';
+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]);
+ }
}
- $destination .= $newidx;
- my ($url,$filename);
- $url=&Apache::lonnet::userfileupload($formname.$num,1,$destination);
- ($filename) = ($url =~ m{^/uploaded/\Q$coursedom\E/\Q$coursenum\E/\Q$destination\E/(.+)$});
- return $filename;
+ 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(
- &unescape($title)),'"<>&\'');
- my $renametitle=$title;
- my $foldertitle=$title;
- my $pagetitle=$title;
- my $orderidx=$LONCAPA::map::order[$index];
- if ($title=~ /^(\d+)___&&&___($match_username)___&&&___($match_domain)___&&&___(.*)$/ ) {
- $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,$crstype)=@_;
+ my ($foldertitle,$pagetitle,$renametitle);
+ if (&is_supplemental_title($title)) {
+ ($title,$foldertitle,$renametitle) = &Apache::loncommon::parse_supplemental_title($title);
+ $pagetitle = $foldertitle;
+ } else {
+ $title=&HTML::Entities::encode($title,'"<>&\'');
+ $renametitle=$title;
+ $foldertitle=$title;
+ $pagetitle=$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 $container;
- my $folderpath;
+ my ($container, $type, $esc_path, $path, $symb);
if ($env{'form.folderpath'}) {
+ $type = 'folder';
$container = 'sequence';
- $folderpath=&escape($env{'form.folderpath'});
+ $esc_path=&escape($env{'form.folderpath'});
+ $path = &HTML::Entities::encode($env{'form.folderpath'},'<>&"');
# $htmlfoldername=&HTML::Entities::encode($env{'form.foldername'},'<>&"');
}
- my ($pagepath,$pagesymb);
if ($env{'form.pagepath'}) {
- $container = 'page';
- $pagepath=&escape($env{'form.pagepath'});
- $pagesymb=&escape($env{'form.pagesymb'});
+ $type = $container = 'page';
+ $esc_path=&escape($env{'form.pagepath'});
+ $path = &HTML::Entities::encode($env{'form.pagepath'},'<>&"');
+ $symb=&escape($env{'form.pagesymb'});
}
my $cpinfo='';
- if ($env{'form.markedcopy_url'}) {
- $cpinfo='&markedcopy_url='.
- &escape($env{'form.markedcopy_url'}).
- '&markedcopy_title='.
- &escape($env{'form.markedcopy_title'});
- }
if ($allowed) {
my $incindex=$index+1;
my $selectbox='';
- if (($folder!~/^supplemental/) &&
- ($#LONCAPA::map::order>0) &&
+ if (($#LONCAPA::map::order>0) &&
((split(/\:/,
- $LONCAPA::map::resources[$LONCAPA::map::order[0]]))[1]
- ne '') &&
+ $LONCAPA::map::resources[$LONCAPA::map::order[0]]))[1]
+ ne '') &&
((split(/\:/,
- $LONCAPA::map::resources[$LONCAPA::map::order[1]]))[1]
+ $LONCAPA::map::resources[$LONCAPA::map::order[1]]))[1]
ne '')) {
$selectbox=
''.
- '
";
+ $line.=&Apache::loncommon::end_data_table_row();
return $line;
}
-# ---------------------------------------------------------------- tie the hash
+=pod
+
+=item tiehash()
+
+tie the hash
+
+=cut
sub tiehash {
my ($mode)=@_;
@@ -1915,7 +1937,7 @@ sub tiehash {
$hashtied=1;
}
}
- }
+ }
}
sub untiehash {
@@ -1924,7 +1946,8 @@ sub untiehash {
return OK;
}
-# --------------------------------------------------------------- check on this
+
+
sub checkonthis {
my ($r,$url,$level,$title)=@_;
@@ -1933,6 +1956,9 @@ sub checkonthis {
$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(' ');
}
@@ -1942,7 +1968,7 @@ sub checkonthis {
my $result=&Apache::lonnet::repcopy(
&Apache::lonnet::filelocation('',$url));
if ($result eq 'ok') {
- $r->print(''.&mt('ok').'');
+ $r->print(''.&mt('ok').'');
$r->rflush();
&Apache::lonnet::countacc($url);
$url=~/\.(\w+)$/;
@@ -1952,7 +1978,7 @@ sub checkonthis {
for (my $i=0;$i<=$level*5;$i++) {
$r->print(' ');
}
- $r->print('- '.&mt('Rendering').': ');
+ $r->print('- '.&mt('Rendering:').' ');
my ($errorcount,$warningcount)=split(/:/,
&Apache::lonnet::ssi_body($url,
('grade_target'=>'web',
@@ -1960,96 +1986,118 @@ sub checkonthis {
if (($errorcount) ||
($warningcount)) {
if ($errorcount) {
- $r->print(''.
- $errorcount.' '.
- &mt('error(s)').' ');
+ $r->print(''.
+ &mt('[quant,_1,error]',$errorcount).'');
}
if ($warningcount) {
- $r->print(''.
- $warningcount.' '.
- &mt('warning(s)').'');
+ $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 eq 'unavailable') {
- $r->print(''.&mt('connection down').'');
+ $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').'');
}
- }
- }
+ }
+ }
}
-#
-# ----------------------------------------------------------------- List Symbs
-#
+
+=pod
+
+=item list_symbs()
+
+List Content Identifiers
+
+=cut
+
sub list_symbs {
my ($r) = @_;
- $r->print(&Apache::loncommon::start_page('Symb List'));
- $r->print(&Apache::lonhtmlcommon::breadcrumbs('Symb List'));
+ 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();
- $r->print("
\n");
- foreach my $res ($navmap->retrieveResources()) {
- $r->print($res->compTitle()."\t".$res->symb()."\n");
+ 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('
\n");
- $r->print(''.&mt('Return to DOCS').'');
}
-#
-# -------------------------------------------------------------- Verify Content
-#
sub verifycontent {
my ($r) = @_;
- my $type = &Apache::loncommon::course_type();
- my $loaderror=&Apache::lonnet::overloaderror($r);
- if ($loaderror) { return $loaderror; }
- $r->print(&Apache::loncommon::start_page('Verify '.$type.' Documents'));
- $r->print(&Apache::lonhtmlcommon::breadcrumbs('Verify '.$type.' Documents'));
+ 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 ($hash{$_}=~/\.(page|sequence)$/) {
- if (($_=~/^src_/) && ($alreadyseen{&unescape($hash{$_})})) {
- $r->print(''.
- &mt('The following sequence or page is included more than once in your '.$type.': ').
- &unescape($hash{$_}).' '.
- &mt('Note that grading records for problems included in this sequence or folder will overlap.'));
+
+ 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 (($_=~/^src\_(.+)$/) && (!$alreadyseen{&unescape($hash{$_})})) {
- &checkonthis($r,$hash{$_},0,$hash{'title_'.$1});
+ if (($key=~/^src\_(.+)$/) && (!$alreadyseen{&unescape($hash{$key})})) {
+ &checkonthis($r,$hash{$key},0,$hash{'title_'.$1});
}
}
&untiehash();
- $r->print('
');
}
-# -------------------------------------------------------------- Check Versions
-
sub devalidateversioncache {
my $src=shift;
&Apache::lonnet::devalidate_cache_new('courseresversion',$env{'request.course.id'}.'_'.
@@ -2058,9 +2106,11 @@ sub devalidateversioncache {
sub checkversions {
my ($r) = @_;
- my $type = &Apache::loncommon::course_type();
- $r->print(&Apache::loncommon::start_page("Check $type Document Versions"));
- $r->print(&Apache::lonhtmlcommon::breadcrumbs("Check $type Document Versions"));
+ 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='';
@@ -2079,16 +2129,16 @@ sub checkversions {
my %newsetversions=();
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'}) {
$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;
@@ -2098,11 +2148,11 @@ sub checkversions {
}
} 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);
}
}
@@ -2111,20 +2161,22 @@ sub checkversions {
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'}.'.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)));
}
&mark_hash_old();
}
&changewarning($r,'');
if ($env{'form.timerange'} eq 'all') {
# show all documents
- $header=&mt('All Documents in '.$type);
+ $header=&mt('All Documents in '.$crstype);
$allsel=1;
- foreach (keys %hash) {
- if ($_=~/^ids\_(\/res\/.+)$/) {
+ foreach my $key (keys(%hash)) {
+ if ($key=~/^ids\_(\/res\/.+)$/) {
my $src=$1;
$changes{$src}=1;
}
@@ -2134,7 +2186,7 @@ sub checkversions {
%changes=&Apache::lonnet::dump
('versionupdate',$env{'course.'.$env{'request.course.id'}.'.domain'},
$env{'course.'.$env{'request.course.id'}.'.num'});
- my $firstkey=(keys %changes)[0];
+ my $firstkey=(keys(%changes))[0];
unless ($firstkey=~/^error\:/) {
unless ($env{'form.timerange'}) {
$env{'form.timerange'}=604800;
@@ -2166,26 +2218,32 @@ sub checkversions {
$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 '.$type,
+ ('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 '.$type,
- 'vu' => 'Set Version to be used in '.$type,
-'sv' => 'Set Versions to be used in '.$type.' 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
');
- $r->print('
'.&mt('Done').'.
');
+ $r->print('
'.&Apache::loncommon::end_data_table_row().
+ &Apache::loncommon::end_data_table().
+ '');
&untiehash();
}
@@ -2342,23 +2412,26 @@ sub changewarning {
$message='Changes will become active for your current session after [_1], or the next time you log in.';
}
$r->print("\n\n".
-''."\n".
+''."\n".
''."\n\n");
+ &mt('re-initializing '.$course_type).'" onclick="reinit(this.form)" />').
+$help{'Caching'}.''."\n\n");
}
-# =========================================== Breadcrumbs for special functions
sub init_breadcrumbs {
my ($form,$text)=@_;
&Apache::lonhtmlcommon::clear_breadcrumbs();
- &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/coursedocs",
- text=>&Apache::loncommon::course_type()." Documents",
+ &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/coursedocs?tools=1",
+ text=>&Apache::loncommon::course_type().' Editor',
faq=>273,
bug=>'Instructor Interface',
help => 'Docs_Adding_Course_Doc'});
@@ -2368,22 +2441,85 @@ sub init_breadcrumbs {
bug=>'Instructor Interface'});
}
-# ================================================================ Main Handler
+# subroutine to list form elements
+sub create_list_elements {
+ my @formarr = @_;
+ my $list = '';
+ for my $button (@formarr){
+ for my $picture(keys %$button) {
+ $list .= &Apache::lonhtmlcommon::htmltag('li', $picture.' '.$button->{$picture}, {class => 'LC_menubuttons_inline_text'});
+ }
+ }
+ return $list;
+}
+
+# subroutine to create ul from list elements
+sub create_form_ul {
+ my $list = shift;
+ my $ul = &Apache::lonhtmlcommon::htmltag('ul',$list, {class => 'LC_ListStyleNormal'});
+ return $ul;
+}
+
+#
+# Start tabs
+#
+
+sub startContentScreen {
+ my ($mode) = @_;
+ my $output = '