--- loncom/interface/londocs.pm 2023/07/16 03:50:54 1.703
+++ loncom/interface/londocs.pm 2024/06/07 14:37:55 1.710
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Documents
#
-# $Id: londocs.pm,v 1.703 2023/07/16 03:50:54 raeburn Exp $
+# $Id: londocs.pm,v 1.710 2024/06/07 14:37:55 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -102,6 +102,7 @@ sub authorhosts {
my %outhash=();
my $home=0;
my $other=0;
+ my @ids=&Apache::lonnet::current_machine_ids();
foreach my $key (keys(%env)) {
if ($key=~/^user\.role\.(au|ca)\.(.+)$/) {
my $role=$1;
@@ -118,7 +119,6 @@ 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;
@@ -263,8 +263,8 @@ ENDJS
add_entries => {'onload' => "hide_searching();"},
};
}
- $r->print(&Apache::loncommon::start_page('Copy '.$crstype.' Content to Authoring Space',$js,$starthash)."\n".
- &Apache::lonhtmlcommon::breadcrumbs('Copy '.$crstype.' Content to Authoring Space')."\n");
+ $r->print(&Apache::loncommon::start_page('Copy uploaded content to Authoring Space',$js,$starthash)."\n".
+ &Apache::lonhtmlcommon::breadcrumbs('Copy uploaded content to Authoring Space')."\n");
$r->print(&startContentScreen('tools'));
my ($home,$other,%outhash)=&authorhosts();
unless ($home) {
@@ -1419,7 +1419,7 @@ sub print_paste_buffer {
}
my @currpaste = split(/,/,$env{'docs.markedcopies'});
- my ($pasteitems,@pasteable);
+ my ($pasteitems,@pasteable,$same_institution,$checkedsameinst);
my $clipboardcount = 0;
# Construct identifiers for current contents of user's paste buffer
@@ -1432,11 +1432,13 @@ sub print_paste_buffer {
($url ne '')) {
$clipboardcount ++;
my ($is_external,$othercourse,$fromsupp,$is_uploaded_map,$parent,
- $canpaste,$nopaste,$othercrs,$areachange,$is_exttool);
+ $canpaste,$nopaste,$othercrs,$areachange,$is_exttool,$toolcdom,
+ $toolcnum,$marker);
my $extension = (split(/\./,$env{'docs.markedcopy_url_'.$suffix}))[-1];
if ($url =~ m{^(?:/adm/wrapper/ext|(?:http|https)(?::|:))//} ) {
$is_external = 1;
- } elsif ($url =~ m{^/adm/$match_domain/$match_courseid/\d+/ext\.tool$}) {
+ } elsif ($url =~ m{^/adm/($match_domain)/($match_courseid)/(\d+)/ext\.tool$}) {
+ ($toolcdom,$toolcnum,$marker) = ($1,$2,$3);
$is_exttool = 1;
}
if ($folder =~ /^supplemental/) {
@@ -1474,11 +1476,42 @@ sub print_paste_buffer {
if ($cid ne $env{'request.course.id'}) {
my ($srcdom,$srcnum) = split(/_/,$cid);
if ($env{"user.priv.cm./$srcdom/$srcnum"} =~ /\Q:mdc&F\E/) {
- if (($is_exttool) && ($srcdom ne $coursedom)) {
- $canpaste = 0;
- $nopaste = &mt('Paste from another domain unavailable.');
- } else {
- $othercrs = '
'.&mt('(from another course)');
+ if ($is_exttool) {
+ if ($toolcdom ne $coursedom) {
+ $canpaste = 0;
+ $nopaste = &mt('Paste from another domain unavailable.');
+ } elsif ($toolcnum ne $coursenum) {
+ my %toolsettings =
+ &Apache::lonnet::dump('exttool_'.$marker,$toolcdom,$toolcnum);
+ my %tooltypes = &Apache::loncommon::usable_exttools();
+ if ((($toolsettings{'id'} =~ /^c\d+$/) && (!$tooltypes{'crs'})) ||
+ (($toolsettings{'id'} =~ /^\d+$/) && (!$tooltypes{'dom'}))) {
+ $canpaste = 0;
+ $nopaste = &mt('Paste from another course unavailable.');
+ } elsif ($toolsettings{'id'} =~ /^c\d+$/) {
+ unless ($checkedsameinst) {
+ my $primary_id = &Apache::lonnet::domain($coursedom,'primary');
+ my $intdom = &Apache::lonnet::internet_dom($primary_id);
+ if ($intdom ne '') {
+ my $internet_names =
+ &Apache::lonnet::get_internet_names($Apache::lonnet::perlvar{'lonHostID'});
+ if (ref($internet_names) eq 'ARRAY') {
+ if (grep(/^\Q$intdom\E$/,@{$internet_names})) {
+ $same_institution = 1;
+ }
+ }
+ }
+ $checkedsameinst = 1;
+ }
+ if ($same_institution) {
+ $othercrs = '
'.&mt('(from another course)');
+ } else {
+ $nopaste = &mt('Paste from another course unavailable.');
+ }
+ } else {
+ $othercrs = '
'.&mt('(from another course)');
+ }
+ }
}
} else {
$canpaste = 0;
@@ -1785,9 +1818,12 @@ sub do_paste_from_buffer {
return();
}
- my (%msgs,%before,%after,@dopaste,%is_map,%notinsupp,%notincrs,%notindom,%duplicate,
- %prefixchg,%srcdom,%srcnum,%srcmapidx,%marktomove,$save_err,$lockerrors,$allresult);
-
+ my (%msgs,%before,%after,@dopaste,%is_map,%notinsupp,%notincrs,%notindom,
+ %othcrstool,%othcrsres,%duplicate,%prefixchg,%srcdom,%srcnum,%srcmapidx,
+ %marktomove,$save_err,$lockerrors,$allresult,%currcrsltitools,
+ %currltititles,$currltimax,$gotcrsltitools);
+ $currltimax = 0;
+ $gotcrsltitools = 0;
foreach my $suffix (@topaste) {
my $url=&LONCAPA::map::qtescape($env{'docs.markedcopy_url_'.$suffix});
my $cid=&LONCAPA::map::qtescape($env{'docs.markedcopy_crs_'.$suffix});
@@ -1826,10 +1862,40 @@ sub do_paste_from_buffer {
}
}
# When buffer was populated using an active role in a different course
-# disallow pasting of External Tool if course is in a different domain.
- if (($url =~ m{/ext\.tool$}) && ($srcd ne $coursedom)) {
- $notindom{$suffix} = 1;
- next;
+# disallow pasting of External Tool if course is in a different domain,
+# or if External Tool use is not permitted in this course.
+ if ($url =~ m{^/adm/($match_domain)/($match_courseid)/(\d+)/ext\.tool$}) {
+ my ($toolcdom,$toolcnum,$marker) = ($1,$2,$3);
+ if ($toolcdom ne $coursedom) {
+ $notindom{$suffix} = 1;
+ next;
+ } elsif ($toolcnum ne $coursenum) {
+ my %toolsettings =
+ &Apache::lonnet::dump('exttool_'.$marker,$toolcdom,$toolcnum);
+ my %tooltypes = &Apache::loncommon::usable_exttools();
+ if ((($toolsettings{'id'} =~ /^c\d+$/) && (!$tooltypes{'crs'})) ||
+ (($toolsettings{'id'} =~ /^\d+$/) && (!$tooltypes{'dom'}))) {
+ $othcrstool{$suffix} = 1;
+ next;
+ }
+ if ($toolsettings{'id'} =~ /^c\d+$/) {
+ unless ($gotcrsltitools) {
+ %currcrsltitools =
+ &Apache::lonnet::get_course_lti($coursenum,$coursedom,'consumer');
+ foreach my $item (sort(keys(%currcrsltitools))) {
+ if (ref($currcrsltitools{$item}) eq 'HASH') {
+ $currltimax ++;
+ if (ref($currltititles{$currcrsltitools{$item}{'title'}}) eq 'ARRAY') {
+ push(@{$currltititles{$currcrsltitools{$item}{'title'}}},$item);
+ } else {
+ $currltititles{$currcrsltitools{$item}{'title'}} = [$item];
+ }
+ }
+ }
+ $gotcrsltitools = 1;
+ }
+ }
+ }
}
$srcdom{$suffix} = $srcd;
$srcnum{$suffix} = $srcn;
@@ -1894,6 +1960,7 @@ sub do_paste_from_buffer {
notinsupp => 'Paste failed: content type is not supported within Supplemental Content',
notincrs => 'Paste failed: Item is from a different course which you do not have rights to edit.',
notindom => 'Paste failed: Item is an external tool from a course in a different domain.',
+ othcrstool => 'Paste failed: Item is an external tool from a different course, for which use is not allowed in this course.',
othcrsres => 'Paste failed: Item is a course-authored resource from a different course',
duplicate => 'Paste failed: only one instance of a particular published sequence or page is allowed within each course.',
);
@@ -1923,7 +1990,9 @@ sub do_paste_from_buffer {
# Retrieve information about all course maps in main content area
my $allmaps = {};
- my (@toclear,%mapurls,%lockerrs,%msgerrs,%results,$donechk);
+ my (@toclear,%mapurls,%lockerrs,%msgerrs,%results,$donechk,
+ @updatetoolsenc,$updatetoolscache,$checkedsameinst,
+ $same_institution);
# Loop over the items to paste
foreach my $suffix (@dopaste) {
@@ -2022,12 +2091,27 @@ sub do_paste_from_buffer {
$fromothercrs = 1;
$info{'cdom'} = $srcdom{$suffix};
$info{'cnum'} = $srcnum{$suffix};
+ unless ($checkedsameinst) {
+ my $primary_id = &Apache::lonnet::domain($coursedom,'primary');
+ my $intdom = &Apache::lonnet::internet_dom($primary_id);
+ if ($intdom ne '') {
+ my $internet_names =
+ &Apache::lonnet::get_internet_names($Apache::lonnet::perlvar{'lonHostID'});
+ if (ref($internet_names) eq 'ARRAY') {
+ if (grep(/^\Q$intdom\E$/,@{$internet_names})) {
+ $same_institution = 1;
+ }
+ }
+ }
+ $checkedsameinst = 1;
+ }
}
}
unless (($env{'form.docs.markedcopy_options_'.$suffix} eq 'move') && (!$fromothercrs)) {
my (%lockerr,$msg);
my ($newurl,$result,$errtext) =
- &dbcopy(\%info,$coursedom,$coursenum,\%lockerr);
+ &dbcopy(\%info,$coursedom,$coursenum,\%lockerr,\%currltititles,
+ \$currltimax,\@updatetoolsenc,\$updatetoolscache,$same_institution);
if ($result eq 'ok') {
$url = $newurl;
$title=&mt('Copy of').' '.$title;
@@ -2196,6 +2280,10 @@ sub do_paste_from_buffer {
}
}
}
+ if (($updatetoolscache) || (@updatetoolsenc)) {
+ &update_ltitools_caches($coursedom,$coursenum,$updatetoolscache,
+ \@updatetoolsenc);
+ }
&clear_from_buffer(\@toclear,\@currpaste);
my $msgsarray;
foreach my $suffix (keys(%msgs)) {
@@ -2244,6 +2332,30 @@ sub clear_from_buffer {
return $numdel;
}
+sub update_ltitools_caches {
+ my ($coursedom,$coursenum,$updatetoolscache,$updatetoolsenc) = @_;
+ my $hashid=$coursedom.'_'.$coursenum;
+ if ($updatetoolscache) {
+ &Apache::lonnet::devalidate_cache_new('courseltitools',$hashid);
+ }
+ if ((ref($updatetoolsenc) eq 'ARRAY') &&
+ (@{$updatetoolsenc})) {
+ my @ids=&Apache::lonnet::current_machine_ids();
+ my $updatedone;
+ foreach my $lonhost (@{$updatetoolsenc}) {
+ if (grep(/^\Q$lonhost\E$/,@ids)) {
+ unless ($updatedone) {
+ &Apache::lonnet::devalidate_cache_new('crsltitoolsenc',$hashid);
+ }
+ $updatedone = 1;
+ } else {
+ &Apache::lonnet::remote_devalidate_cache($lonhost,["crsltitoolsenc:$hashid"]);
+ }
+ }
+ }
+ return;
+}
+
sub get_newmap_url {
my ($url,$folder,$prefixchg,$coursedom,$coursenum,$srcdom,$srcnum,
$titleref,$allmaps,$newurls) = @_;
@@ -2305,7 +2417,8 @@ sub get_newmap_url {
}
sub dbcopy {
- my ($dbref,$coursedom,$coursenum,$lockerrorsref) = @_;
+ my ($dbref,$coursedom,$coursenum,$lockerrorsref,$currltititles,
+ $currltimax,$updatetoolsenc,$updatetoolscache,$same_institution) = @_;
my ($url,$result,$errtext);
if (ref($dbref) eq 'HASH') {
$url = $dbref->{'src'};
@@ -2349,6 +2462,117 @@ sub dbcopy {
my %contents=&Apache::lonnet::dump($db_name,
$dbref->{'cdom'},
$dbref->{'cnum'});
+ my ($toolcopyerror,$toolpassback,$toolroster,%toolinfo,$oldtoolid,$defincrs);
+ if ($url eq '/adm/'.$dbref->{'cdom'}.'/'.$dbref->{'cnum'}."/$marker/ext.tool") {
+ if ($contents{'id'} =~ /^(|c)(\d+)$/) {
+ $oldtoolid = $2;
+ if ($1 eq 'c') {
+ $defincrs = 1;
+ %toolinfo =
+ &Apache::lonnet::get('ltitools',[$oldtoolid],$dbref->{'cdom'},$dbref->{'cnum'});
+ } else {
+ %toolinfo= &Apache::lonnet::get_domain_lti($dbref->{'cdom'},'consumer');
+ }
+ if (ref($toolinfo{$oldtoolid}) eq 'HASH') {
+ if ($toolinfo{$oldtoolid}{'passback'}) {
+ $toolpassback = 1;
+ }
+ if ($toolinfo{$oldtoolid}{'roster'}) {
+ $toolroster = 1;
+ }
+ } else {
+ $toolcopyerror = 1;
+ $errtext = &mt('Could not retrieve original settings for pasted external tool.');
+ }
+ }
+ unless (($dbref->{'cnum'} eq $coursenum) && ($dbref->{'cdom'} eq $coursedom)) {
+ $url = "/adm/$coursedom/$coursenum/$marker/ext.tool";
+ if ($contents{'crstitle'} ne '') {
+ $contents{'crstitle'} = $env{'course.'.$coursedom.'_'.$coursenum.'.description'};
+ }
+ if (($defincrs) && (!$toolcopyerror)) {
+ my %newtool;
+ my $oldcdom = $dbref->{'cdom'};
+ my $oldcnum = $dbref->{'cnum'};
+ my $title = $toolinfo{$oldtoolid}{'title'};
+ if (ref($currltititles) eq 'HASH') {
+ if (exists($currltititles->{$title})) {
+ $title .= ' (copied from another course)';
+ }
+ }
+ my ($newid,$iderror) =
+ &Apache::lonnet::get_ltitools_id('course',$coursedom,$coursenum,$title);
+ if ($newid =~ /^\d+$/) {
+ %{$newtool{$newid}} = %{$toolinfo{$oldtoolid}};
+ $newtool{$newid}{'title'} = $title;
+ if (ref($currltimax)) {
+ $newtool{$newid}{'order'} = $$currltimax;
+ }
+ if ($newtool{$newid}{'image'} =~ m{^\Q/uploaded/$oldcdom/$oldcnum/toollogo/$oldtoolid/\E([^/]+)$}) {
+ my $fname = $1;
+ my $content = &Apache::lonnet::getfile($newtool{$newid}{'image'});
+ if ($content eq '-1') {
+ delete($newtool{$newid}{'image'});
+ } else {
+ $env{'form.'.$suffix.'.image'} = $content;
+ my $newlogo =
+ &Apache::lonnet::finishuserfileupload($coursenum,$coursedom,$suffix.'.image',"toollogo/$newid/$fname");
+ delete($env{'form.'.$suffix.'.image'});
+ if ($newlogo =~ m{^/uploaded/}) {
+ $newtool{$newid}{'image'} = $newlogo;
+ } else {
+ delete($newtool{$newid}{'image'});
+ }
+ }
+ }
+ my $newusable;
+ if ($same_institution) {
+ my %oldtoolsenc = &Apache::lonnet::eget('nohist_toolsenc',[$oldtoolid],$oldcdom,$oldcnum);
+ if (ref($oldtoolsenc{$oldtoolid}) eq 'HASH') {
+ my %newtoolsenc;
+ %{$newtoolsenc{$newid}} = %{$oldtoolsenc{$oldtoolid}};
+ my $putres = &Apache::lonnet::put('nohist_toolsenc',\%newtoolsenc,$coursedom,$coursenum,1);
+ if ($putres eq 'ok') {
+ if (ref($updatetoolsenc) eq 'ARRAY') {
+ my $newhome = &Apache::lonnet::homeserver($coursenum,$coursedom);
+ unless (grep(/^\Q$newhome\E$/,@{$updatetoolsenc})) {
+ push(@{$updatetoolsenc},$newhome);
+ }
+ }
+ $newusable = 1;
+ }
+ }
+ }
+ if ($newtool{$newid}{'usable'}) {
+ unless ($newusable) {
+ delete($newtool{$newid}{'usable'});
+ }
+ }
+ my $putres = &Apache::lonnet::put('ltitools',\%newtool,$coursedom,$coursenum);
+ if ($putres eq 'ok') {
+ $contents{'id'} = "c$newid";
+ if (ref($updatetoolscache)) {
+ $$updatetoolscache ++;
+ }
+ if (ref($currltititles->{$title}) eq 'ARRAY') {
+ push(@{$currltititles->{$title}},$newid);
+ } else {
+ $currltititles->{$title} = [$newid];
+ }
+ if (ref($currltimax)) {
+ $$currltimax ++;
+ }
+ } else {
+ $toolcopyerror = 1;
+ $errtext = &mt('Unable to save external tool definition in Course Settings.');
+ }
+ } else {
+ $toolcopyerror = 1;
+ $errtext = &mt('Unable to retrieve new tool ID when adding external tool definition to Course Settings.');
+ }
+ }
+ }
+ }
if (exists($contents{'uploaded.photourl'})) {
my $photo = $contents{'uploaded.photourl'};
my ($subdir,$fname) =
@@ -2368,13 +2592,40 @@ sub dbcopy {
}
}
$db_name =~ s{_\d*$ }{_$suffix}x;
- if (($prefix eq 'exttool') && ($dbref->{'delgradable'}) && ($contents{'gradable'})) {
- delete($contents{'gradable'});
+ if ($prefix eq 'exttool') {
+ unless ($toolcopyerror) {
+ foreach my $key ('oldgradesecret','gradesecret','gradesecretdate','oldrostersecret','rostersecret','rostersecretdate') {
+ if (exists($contents{$key})) {
+ delete($contents{$key});
+ }
+ }
+ if ($dbref->{'delgradable'}) {
+ if (exists($contents{'gradable'})) {
+ delete($contents{'gradable'});
+ }
+ }
+ if ($toolpassback) {
+ if ($contents{'gradable'}) {
+ my $gradesecret = UUID::Tiny::create_uuid_as_string(UUID_V4);
+ $contents{'gradesecret'} = $gradesecret;
+ $contents{'gradesecretdate'} = time;
+ }
+ }
+ if ($toolroster) {
+ my $rostersecret = UUID::Tiny::create_uuid_as_string(UUID_V4);
+ $contents{'rostersecret'} = $rostersecret;
+ $contents{'rostersecretdate'} = time;
+ }
+ }
}
- $result=&Apache::lonnet::put($db_name,\%contents,
- $coursedom,$coursenum);
- if ($result eq 'ok') {
- $url =~ s{/(\d*)/(smppg|bulletinboard|ext\.tool)$}{/$suffix/$2}x;
+ if (($prefix eq 'exttool') && ($toolcopyerror)) {
+ $result = 'error';
+ } else {
+ $result=&Apache::lonnet::put($db_name,\%contents,
+ $coursedom,$coursenum);
+ if ($result eq 'ok') {
+ $url =~ s{/(\d*)/(smppg|bulletinboard|ext\.tool)$}{/$suffix/$2}x;
+ }
}
}
if (($freedlock ne 'ok') && (ref($lockerrorsref) eq 'HASH')) {
@@ -2529,12 +2780,22 @@ sub contained_map_check {
if ($token->[1] eq 'resource') {
next if ($token->[2]->{'type'} eq 'zombie');
my $ressrc = $token->[2]->{'src'};
- if ($ressrc =~ m{^/adm/($match_domain)/$match_courseid/\d+/ext\.tool$}) {
- my $srcdom = $1;
+ if ($ressrc =~ m{^/adm/($match_domain)/($match_courseid)/(\d+)/ext\.tool$}) {
+ my ($srcdom,$srcnum,$marker) = ($1,$2,$3);
unless ($srcdom eq $coursedom) {
$removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc;
next;
}
+ unless ($srcnum eq $coursenum) {
+ my %toolsettings =
+ &Apache::lonnet::dump('exttool_'.$marker,$srcdom,$srcnum);
+ my %tooltypes = &Apache::loncommon::usable_exttools();
+ if ((($toolsettings{'id'} =~ /^c\d+$/) && (!$tooltypes{'crs'})) ||
+ (($toolsettings{'id'} =~ /^\d+$/) && (!$tooltypes{'dom'}))) {
+ $removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc;
+ next;
+ }
+ }
} elsif ($folder =~ /^supplemental/) {
unless (&supp_pasteable($ressrc)) {
$removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc;
@@ -2744,7 +3005,9 @@ sub apply_fixups {
$oldurl,$url,$caller) = @_;
my (%rewrites,%zombies,%removefrommap,%removeparam,%dbcopies,%retitles,
%params,%newsubdir,%before,%after,%copies,%docmoves,%mapmoves,@msgs,
- %resdatacopy,%lockerrors,$lockmsg);
+ %resdatacopy,%lockerrors,$lockmsg,%currcrsltitools,$gotcrsltitools,
+ %currltititles,$currltimax);
+ $currltimax = 0;
if (ref($updated) eq 'HASH') {
if (ref($updated->{'rewrites'}) eq 'HASH') {
%rewrites = %{$updated->{'rewrites'}};
@@ -2895,6 +3158,7 @@ sub apply_fixups {
}
}
}
+ my ($updatetoolscache,@updatetoolsenc,$same_institution,$checkedsameinst);
foreach my $key (keys(%updates)) {
my (%torewrite,%toretitle,%toremove,%remparam,%currparam,%zombie,%newdb);
if (ref($rewrites{$key}) eq 'HASH') {
@@ -2915,10 +3179,63 @@ sub apply_fixups {
if (ref($dbcopies{$key}) eq 'HASH') {
foreach my $idx (keys(%{$dbcopies{$key}})) {
if (ref($dbcopies{$key}{$idx}) eq 'HASH') {
+ my $oldurl = $dbcopies{$key}{$idx}{'src'};
+ my $oldcdom = $dbcopies{$key}{$idx}{'cdom'};
+ my $oldcnum = $dbcopies{$key}{$idx}{'cnum'};
+ my $oldmarker;
+ if ($oldurl =~ m{^\Q/adm/$oldcdom/$oldcnum/\E(\d+)/ext\.tool$}) {
+ $oldmarker = $1;
+ unless (($gotcrsltitools) ||
+ (($oldcnum eq $cnum) && ($oldcdom eq $cdom))) {
+ my %oldtoolsettings=&Apache::lonnet::dump('exttool_'.$oldmarker,$oldcdom,$oldcnum);
+ if ($oldtoolsettings{'id'} =~ /^c\d+$/) {
+ unless ($gotcrsltitools) {
+ %currcrsltitools =
+ &Apache::lonnet::get_course_lti($cnum,$cdom,'consumer');
+ foreach my $item (sort(keys(%currcrsltitools))) {
+ if (ref($currcrsltitools{$item}) eq 'HASH') {
+ $currltimax ++;
+ if (ref($currltititles{$currcrsltitools{$item}{'title'}}) eq 'ARRAY') {
+ push(@{$currltititles{$currcrsltitools{$item}{'title'}}},$item);
+ } else {
+ $currltititles{$currcrsltitools{$item}{'title'}} = [$item];
+ }
+ }
+ }
+ $gotcrsltitools = 1;
+ }
+ unless ($checkedsameinst) {
+ my $primary_id = &Apache::lonnet::domain($cdom,'primary');
+ my $intdom = &Apache::lonnet::internet_dom($primary_id);
+ if ($intdom ne '') {
+ my $internet_names =
+ &Apache::lonnet::get_internet_names($Apache::lonnet::perlvar{'lonHostID'});
+ if (ref($internet_names) eq 'ARRAY') {
+ if (grep(/^\Q$intdom\E$/,@{$internet_names})) {
+ $same_institution = 1;
+ }
+ }
+ }
+ $checkedsameinst = 1;
+ }
+ }
+ }
+ }
my ($newurl,$result,$errtext) =
- &dbcopy($dbcopies{$key}{$idx},$cdom,$cnum,\%lockerrors);
+ &dbcopy($dbcopies{$key}{$idx},$cdom,$cnum,\%lockerrors,\%currltititles,
+ \$currltimax,\@updatetoolsenc,\$updatetoolscache,$same_institution);
if ($result eq 'ok') {
$newdb{$idx} = $newurl;
+ if ($newurl =~ /ext\.tool$/) {
+ if ($torewrite{$idx} eq "/adm/$oldcdom/$oldcnum/$oldmarker/ext.tool") {
+ if ($newurl =~ m{^\Q/adm/$cdom/$cnum/\E(\d+)/ext.tool$}) {
+ my $newmarker = $1;
+ unless ($oldmarker eq $newmarker) {
+ $torewrite{$idx} = "/adm/$oldcdom/$oldcnum/$newmarker/ext.tool";
+ }
+ }
+ }
+ }
} elsif (ref($errors) eq 'HASH') {
$errors->{$key} = 1;
}
@@ -3057,6 +3374,10 @@ sub apply_fixups {
}
}
}
+ if (($updatetoolscache) || (@updatetoolsenc)) {
+ &update_ltitools_caches($cdom,$cnum,$updatetoolscache,
+ \@updatetoolsenc);
+ }
}
return ('ok',\@msgs,$lockmsg);
}
@@ -4413,7 +4734,7 @@ END
}
$nomodal = 1;
}
- } elsif (($uploaded) && (!$allowed) && ($url ne '/adm/supplemental?')) {
+ } elsif (($uploaded) && ($url ne '/adm/supplemental?') && ($url ne '/adm/coursedocs?')) {
my $embstyle=&Apache::loncommon::fileembstyle($extension);
unless ($embstyle eq 'ssi') {
if (($embstyle eq 'img')
@@ -4519,7 +4840,7 @@ $form_common."\n".
''.
$form_end;
}
- } elsif ($supplementalflag && !$allowed) {
+ } elsif ($supplementalflag) {
my $isexttool;
if ($url=~m{^/adm/$coursedom/$coursenum/\d+/ext\.tool$}) {
$url='/adm/wrapper'.$url;
@@ -4614,12 +4935,20 @@ $form_end;
$anchor = '#'.&HTML::Entities::encode($anchor,'"<>&');
}
}
- if ((!$supplementalflag) && ($nomodal) && ($hostname ne '')) {
+ if (($nomodal) && ($hostname ne '')) {
$link = 'http://'.$hostname.$url;
} else {
$link = $url;
}
- $link = &js_escape($link.(($url=~/\?/)?'&':'?').'inhibitmenu=yes'.$anchor);
+ my $inhibitmenu;
+ if ((($supplementalflag) && ($allowed) && ($url =~ m{^/adm/wrapper/})) ||
+ (($allowed) && (($url =~ m{^/adm/(viewclasslist|$match_domain/$match_username/aboutme)(\?|$)}) ||
+ ($url =~ m{^/public/$match_domain/$match_courseid/syllabus(\?|$)})))) {
+ $inhibitmenu = 'only_body=1';
+ } else {
+ $inhibitmenu = 'inhibitmenu=yes';
+ }
+ $link = &js_escape($link.(($url=~/\?/)?'&':'?').$inhibitmenu.$anchor);
if ($allowed && !$env{'request.role.adv'} && !$isfolder && !$ispage && !$uploaded) {
if ((&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i) {
$nolink = 1;
@@ -5563,7 +5892,9 @@ sub handler {
'Load_Map','Supplemental','Score_Upload_Form',
'Adding_Pages','Importing_LON-CAPA_Resource',
'Importing_IMS_Course','Uploading_From_Harddrive',
- 'Course_Roster','Web_Page','Dropbox','Simple_Problem') {
+ 'Course_Roster','Web_Page','Dropbox','Simple_Problem',
+ 'Standard_Problem','Course_Resources',
+ 'Search_LON-CAPA_Resource','Import_Stored_Links') {
$help{$topic}=&Apache::loncommon::help_open_topic('Docs_'.$topic);
}
# Composite help files
@@ -5634,7 +5965,7 @@ sub handler {
&init_breadcrumbs('versions','Check/Set Resource Versions','Docs_Check_Resource_Versions');
&checkversions($r,$canedit);
} elsif ($canedit && $env{'form.dumpcourse'}) {
- &init_breadcrumbs('dumpcourse','Copy '.&Apache::loncommon::course_type().' Content to Authoring Space');
+ &init_breadcrumbs('dumpcourse','Copy uploaded content to Authoring Space');
&dumpcourse($r);
} elsif ($canedit && $env{'form.exportcourse'}) {
&init_breadcrumbs('exportcourse','IMS Export');
@@ -5738,8 +6069,11 @@ sub handler {
}
if ($env{'form.forcesupplement'}) { $supplementalflag=1; }
if ($env{'form.forcestandard'}) { $supplementalflag=0; }
- unless ($allowed) { $supplementalflag=1; }
- unless ($standard) { $supplementalflag=1; }
+ unless (($supplementalflag) ||
+ ($r->uri =~ m{^/adm/coursedocs/showdoc/uploaded/\Q$coursedom\E/\Q$coursenum\E/docs/})) {
+ unless ($allowed) { $supplementalflag=1; }
+ unless ($standard) { $supplementalflag=1; }
+ }
my $toolsflag=0;
if ($env{'form.tools'}) { $toolsflag=1; }
@@ -5815,9 +6149,9 @@ sub handler {
&Apache::loncommon::validate_folderpath($supplementalflag,$allowed,$coursenum,$coursedom);
}
}
-
-# If we are not allowed to make changes, all we can see are supplemental docs
- if (!$allowed) {
+
+# Set folderpath if we are not allowed to make changes and this is supplemental content
+ if ((!$allowed) && ($supplementalflag)) {
unless ($env{'form.folderpath'} =~ /^supplemental/) {
$env{'form.folderpath'} = &supplemental_base();
}
@@ -6048,7 +6382,8 @@ sub handler {
if ($supplementalflag) {
my $title = &HTML::Entities::encode($env{'form.title'},'\'"<>&');
my $brcrum = &Apache::lonhtmlcommon::docs_breadcrumbs(undef,$crstype,undef,$title,1);
- $args = {'bread_crumbs' => $brcrum};
+ $args = {'bread_crumbs' => $brcrum,
+ 'bread_crumbs_nomenu' => 1};
} else {
$args = {'force_register' => $showdoc};
}
@@ -6077,8 +6412,13 @@ sub handler {
}
}
my $brcrum = &Apache::lonhtmlcommon::docs_breadcrumbs(undef,$crstype);
+ my $args = {'bread_crumbs' => $brcrum};
+ unless (($env{'form.folderpath'} eq '') ||
+ ($env{'form.folder'} eq 'supplemental')) {
+ $args->{'bread_crumbs_nomenu'} = 1;
+ }
$r->print(&Apache::loncommon::start_page("Supplemental $crstype Content",undef,
- {'bread_crumbs' => $brcrum,}));
+ $args));
} else {
my ($breadtext,$breadtitle,$helpitem);
$breadtext = "$crstype Editor";
@@ -6163,7 +6503,7 @@ sub handler {
if ($allowed && $toolsflag) {
$r->print(&startContentScreen('tools'));
- $r->print(&generate_admin_menu($crstype,$canedit));
+ $r->print(&generate_admin_menu($crstype,$canedit,$coursenum,$coursedom));
$r->print(&endContentScreen());
} elsif ((!$showdoc) && (!$uploadphase)) {
# -----------------------------------------------------------------------------
@@ -6171,8 +6511,8 @@ sub handler {
'copm' => 'All documents out of a published map into this folder',
'upfi' => 'Upload File',
'upld' => 'Upload Content',
- 'srch' => 'Search',
- 'impo' => 'Import',
+ 'srch' => 'Search Repository',
+ 'impo' => 'Import from Repository',
'lnks' => 'Import from Stored Links',
'impm' => 'Import from Assembled Map',
'imcr' => 'Import from Course Resources',
@@ -6349,13 +6689,33 @@ FUFORM
SEDFFORM
- my $importcrsresform;
- my ($numdirs,$pickfile) =
- &Apache::loncommon::import_crsauthor_form('coursepath','coursefile',
- "resize_scrollbox('contentscroll','1','0');",
- undef,'res');
- if ($pickfile) {
- $importcrsresform=(<