image type
+ # or a tag inside or
+ if (($lctag eq 'label' && defined($parms{'description'}))
+ || ($lctag eq 'image') || ($lctag eq 'import')) {
+ my $next_token=$parser[-1]->get_token();
+ if ($next_token->[0] eq 'T') {
+ $next_token->[1] =~ s/[\n\r\f]+//g;
+ if ($next_token->[1] =~ m{^\Q/res/$coursedom/$coursenum/\E}si) {
+ $next_token->[1] =~ s{^\Q/res/$coursedom/$coursenum/\E}{/res/$cd/$ca/$subdir/}si;
+ $changes ++;
+ }
+ }
+ $parser[-1]->unget_token($next_token);
+ }
+ if ($lctag eq 'applet') {
+ my $havecodebase=0;
+ foreach my $key (keys(%parms)) {
+ if (lc($key) eq 'codebase') {
+ if ($parms{$key} =~ m{^\Q/res/$coursedom/$coursenum/\E}si) {
+ $parms{$key} =~ s{^\Q/res/$coursedom/$coursenum/\E}{/res/$cd/$ca/$subdir/}si;
+ $changes ++;
+ }
+ $havecodebase = 1;
+ }
+ }
+ unless ($havecodebase) {
+ foreach my $key (keys(%parms)) {
+ if ($key =~ /(archive|code|object)/i) {
+ if ($parms{$key} =~ m{^\Q/res/$coursedom/$coursenum/\E}si) {
+ $parms{$key} =~ s{^\Q/res/$coursedom/$coursenum/\E}{/res/$cd/$ca/$subdir/si};
+ $changes ++;
+ }
+ }
+ }
+ }
+ }
+ my $newparmstring='';
+ my $endtag='';
+ foreach my $parkey (keys(%parms)) {
+ if ($parkey eq '/') {
+ $endtag=' /';
+ } else {
+ my $quote=($parms{$parkey}=~/\"/?"'":'"');
+ $newparmstring.=' '.$parkey.'='.$quote.$parms{$parkey}.$quote;
+ }
+ }
+ if (!$endtag) { if ($token->[4]=~m:/>$:) { $endtag=' /'; }; }
+ $outstring.='<'.$tag.$newparmstring.$endtag.'>';
+ if ($lctag eq 'm' || $lctag eq 'answer' || $lctag eq 'display' ||
+ $lctag eq 'tex') {
+ $outstring.=&Apache::lonxml::get_all_text_unbalanced('/'.$lctag,\@parser);
+ } elsif ($lctag eq 'script') {
+ if ($parms{'type'} eq 'loncapa/perl') {
+ $outstring.=&Apache::lonxml::get_all_text_unbalanced('/'.$lctag,\@parser);
+ } else {
+ my $needsupdate;
+ my $script = &Apache::lonxml::get_all_text_unbalanced('/'.$lctag,\@parser);
+ if ($script =~ m{\.addMediaSrc\((["'])((?!\1).+)\1\);}) {
+ my $src = $2;
+ if ($src =~ m{^\Q/res/$coursedom/$coursenum/\E}si) {
+ $needsupdate = 1;
+ }
+ }
+ if ($script =~ /\(document,\s*(['"])script\1,\s*\[([^\]]+)\]\);/s) {
+ my $scriptslist = $2;
+ my @srcs = split(/\s*,\s*/,$scriptslist);
+ foreach my $src (@srcs) {
+ if ($src =~ /(["'])(?:(?!\1).)+\.js\1/) {
+ my $quote = $1;
+ my ($url) = ($src =~ m/\Q$quote\E([^$quote]+)\Q$quote\E/);
+ if ($url =~ m{^\Q/res/$coursedom/$coursenum/\E}si) {
+ $needsupdate = 1;
+ }
+ }
+ }
+ }
+ if ($script =~ m{loadScript\(\s*(['"])((?:(?!\1).)+\.js)\1,\s*function}is) {
+ my $src = $2;
+ if ($src =~ m{^\Q/res/$coursedom/$coursenum/\E}si) {
+ $needsupdate = 1;
+ }
+ }
+ if ($needsupdate) {
+ $script =~ s{^\Q/res/$coursedom/$coursenum/\E}{/res/$cd/$ca/$subdir/gsi};
+ $changes ++;
+ }
+ $outstring .= $script;
+ }
+ }
+ } elsif ($token->[0] eq 'E') {
+ if ($token->[2]) {
+ unless ($token->[1] eq 'allow') {
+ $outstring.=''.$token->[1].'>';
+ }
+ }
+ } else {
+ $outstring.=$token->[1];
+ }
+ }
+ pop(@parser);
+ }
+ if ($changes) {
+ if (open(my $fh,'>',$dest)) {
+ print $fh $outstring;
+ close($fh);
+ }
+ }
+}
+
sub group_import {
my ($coursenum, $coursedom, $folder, $container, $caller, $ltitoolsref, @files) = @_;
my ($donechk,$allmaps,%hierarchy,%titles,%addedmaps,%removefrommap,
@@ -719,7 +1703,7 @@ sub group_import {
$url = $1;
my $marker = $2;
my $info = $3;
- my ($toolid,%toolhash,%toolsettings);
+ my ($toolid,$toolprefix,$tooltype,%toolhash,%toolsettings);
my @extras = ('linktext','explanation','crslabel','crstitle','crsappend');
my @toolinfo = split(/:/,$info);
if ($residx) {
@@ -728,6 +1712,12 @@ sub group_import {
} else {
$toolid = shift(@toolinfo);
}
+ if ($toolid =~ /^c/) {
+ $tooltype = 'crs';
+ $toolprefix = 'c';
+ } else {
+ $tooltype = 'dom';
+ }
$toolid =~ s/\D//g;
($toolhash{'target'},$toolhash{'width'},$toolhash{'height'},
$toolhash{'linktext'},$toolhash{'explanation'},$toolhash{'crslabel'},
@@ -741,127 +1731,130 @@ sub group_import {
$toolhash{'gradable'} =~ s/\D+//g;
}
if (ref($ltitoolsref) eq 'HASH') {
- if (ref($ltitoolsref->{$toolid}) eq 'HASH') {
- my @deleted;
- $toolhash{'id'} = $toolid;
- if (($toolhash{'target'} eq 'iframe') || ($toolhash{'target'} eq 'tab') ||
- ($toolhash{'target'} eq 'window')) {
- if ($toolhash{'target'} eq 'window') {
- foreach my $item ('width','height') {
- $toolhash{$item} =~ s/^\s+//;
- $toolhash{$item} =~ s/\s+$//;
- if ($toolhash{$item} =~ /\D/) {
- delete($toolhash{$item});
- if ($residx) {
- if ($toolsettings{$item}) {
- push(@deleted,$item);
+ if (ref($ltitoolsref->{$tooltype}) eq 'HASH') {
+ if (ref($ltitoolsref->{$tooltype}->{$toolid}) eq 'HASH') {
+ my %tools = %{$ltitoolsref->{$tooltype}->{$toolid}};
+ my @deleted;
+ $toolhash{'id'} = $toolprefix.$toolid;
+ if (($toolhash{'target'} eq 'iframe') || ($toolhash{'target'} eq 'tab') ||
+ ($toolhash{'target'} eq 'window')) {
+ if ($toolhash{'target'} eq 'window') {
+ foreach my $item ('width','height') {
+ $toolhash{$item} =~ s/^\s+//;
+ $toolhash{$item} =~ s/\s+$//;
+ if ($toolhash{$item} =~ /\D/) {
+ delete($toolhash{$item});
+ if ($residx) {
+ if ($toolsettings{$item}) {
+ push(@deleted,$item);
+ }
}
}
}
}
- }
- } elsif ($residx) {
- $toolhash{'target'} = $toolsettings{'target'};
- if ($toolhash{'target'} eq 'window') {
- foreach my $item ('width','height') {
- $toolhash{$item} = $toolsettings{$item};
+ } elsif ($residx) {
+ $toolhash{'target'} = $toolsettings{'target'};
+ if ($toolhash{'target'} eq 'window') {
+ foreach my $item ('width','height') {
+ $toolhash{$item} = $toolsettings{$item};
+ }
+ }
+ } elsif (ref($tools{'display'}) eq 'HASH') {
+ $toolhash{'target'} = $tools{'display'}{'target'};
+ if ($toolhash{'target'} eq 'window') {
+ $toolhash{'width'} = $tools{'display'}{'width'};
+ $toolhash{'height'} = $tools{'display'}{'height'};
}
}
- } elsif (ref($ltitoolsref->{$toolid}->{'display'}) eq 'HASH') {
- $toolhash{'target'} = $ltitoolsref->{$toolid}->{'display'}->{'target'};
- if ($toolhash{'target'} eq 'window') {
- $toolhash{'width'} = $ltitoolsref->{$toolid}->{'display'}->{'width'};
- $toolhash{'height'} = $ltitoolsref->{$toolid}->{'display'}->{'height'};
- }
- }
- if ($toolhash{'target'} eq 'iframe') {
- foreach my $item ('width','height','linktext','explanation') {
- delete($toolhash{$item});
- if ($residx) {
- if ($toolsettings{$item}) {
- push(@deleted,$item);
+ if ($toolhash{'target'} eq 'iframe') {
+ foreach my $item ('width','height','linktext','explanation') {
+ delete($toolhash{$item});
+ if ($residx) {
+ if ($toolsettings{$item}) {
+ push(@deleted,$item);
+ }
}
}
- }
- } elsif ($toolhash{'target'} eq 'tab') {
- foreach my $item ('width','height') {
- delete($toolhash{$item});
- if ($residx) {
- if ($toolsettings{$item}) {
- push(@deleted,$item);
+ } elsif ($toolhash{'target'} eq 'tab') {
+ foreach my $item ('width','height') {
+ delete($toolhash{$item});
+ if ($residx) {
+ if ($toolsettings{$item}) {
+ push(@deleted,$item);
+ }
}
}
}
- }
- if (ref($ltitoolsref->{$toolid}->{'crsconf'}) eq 'HASH') {
- foreach my $item ('label','title','linktext','explanation') {
- my $crsitem;
- if (($item eq 'label') || ($item eq 'title')) {
- $crsitem = 'crs'.$item;
- } else {
- $crsitem = $item;
- }
- if ($ltitoolsref->{$toolid}->{'crsconf'}->{$item}) {
- $toolhash{$crsitem} =~ s/^\s+//;
- $toolhash{$crsitem} =~ s/\s+$//;
- if ($toolhash{$crsitem} eq '') {
+ if (ref($tools{'crsconf'}) eq 'HASH') {
+ foreach my $item ('label','title','linktext','explanation') {
+ my $crsitem;
+ if (($item eq 'label') || ($item eq 'title')) {
+ $crsitem = 'crs'.$item;
+ } else {
+ $crsitem = $item;
+ }
+ if ($tools{'crsconf'}{$item}) {
+ $toolhash{$crsitem} =~ s/^\s+//;
+ $toolhash{$crsitem} =~ s/\s+$//;
+ if ($toolhash{$crsitem} eq '') {
+ delete($toolhash{$crsitem});
+ }
+ } else {
delete($toolhash{$crsitem});
}
- } else {
- delete($toolhash{$crsitem});
- }
- if (($residx) && (exists($toolsettings{$crsitem}))) {
- unless (exists($toolhash{$crsitem})) {
- push(@deleted,$crsitem);
+ if (($residx) && (exists($toolsettings{$crsitem}))) {
+ unless (exists($toolhash{$crsitem})) {
+ push(@deleted,$crsitem);
+ }
}
}
}
- }
- if ($toolhash{'passback'}) {
- my $gradesecret = UUID::Tiny::create_uuid_as_string(UUID_V4);
- $toolhash{'gradesecret'} = $gradesecret;
- $toolhash{'gradesecretdate'} = time;
- }
- if ($toolhash{'roster'}) {
- my $rostersecret = UUID::Tiny::create_uuid_as_string(UUID_V4);
- $toolhash{'rostersecret'} = $rostersecret;
- $toolhash{'rostersecretdate'} = time;
- }
- my $changegradable;
- if (($residx) && ($folder =~ /^default/)) {
- if ($toolsettings{'gradable'}) {
- unless (($toolhash{'gradable'}) || (defined($LONCAPA::map::zombies[$residx]))) {
- push(@deleted,'gradable');
- $changegradable = 1;
- }
- } elsif ($toolhash{'gradable'}) {
- $changegradable = 1;
+ if ($toolhash{'passback'}) {
+ my $gradesecret = UUID::Tiny::create_uuid_as_string(UUID_V4);
+ $toolhash{'gradesecret'} = $gradesecret;
+ $toolhash{'gradesecretdate'} = time;
+ }
+ if ($toolhash{'roster'}) {
+ my $rostersecret = UUID::Tiny::create_uuid_as_string(UUID_V4);
+ $toolhash{'rostersecret'} = $rostersecret;
+ $toolhash{'rostersecretdate'} = time;
}
- if (($caller eq 'londocs') && (defined($LONCAPA::map::zombies[$residx]))) {
- $changegradable = 1;
+ my $changegradable;
+ if (($residx) && ($folder =~ /^default/)) {
if ($toolsettings{'gradable'}) {
- $toolhash{'gradable'} = 1;
+ unless (($toolhash{'gradable'}) || (defined($LONCAPA::map::zombies[$residx]))) {
+ push(@deleted,'gradable');
+ $changegradable = 1;
+ }
+ } elsif ($toolhash{'gradable'}) {
+ $changegradable = 1;
+ }
+ if (($caller eq 'londocs') && (defined($LONCAPA::map::zombies[$residx]))) {
+ $changegradable = 1;
+ if ($toolsettings{'gradable'}) {
+ $toolhash{'gradable'} = 1;
+ }
}
}
- }
- my $putres = &Apache::lonnet::put('exttool_'.$marker,\%toolhash,$coursedom,$coursenum);
- if ($putres eq 'ok') {
- if (@deleted) {
- &Apache::lonnet::del('exttool_'.$marker,\@deleted,$coursedom,$coursenum);
- }
- if (($changegradable) && ($folder =~ /^default/)) {
- my $val;
- if ($toolhash{'gradable'}) {
- $val = 'yes';
- } else {
- $val = 'no';
+ my $putres = &Apache::lonnet::put('exttool_'.$marker,\%toolhash,$coursedom,$coursenum);
+ if ($putres eq 'ok') {
+ if (@deleted) {
+ &Apache::lonnet::del('exttool_'.$marker,\@deleted,$coursedom,$coursenum);
+ }
+ if (($changegradable) && ($folder =~ /^default/)) {
+ my $val;
+ if ($toolhash{'gradable'}) {
+ $val = 'yes';
+ } else {
+ $val = 'no';
+ }
+ &LONCAPA::map::storeparameter($residx,'parameter_0_gradable',$val,
+ 'string_yesno');
+ &remember_parms($residx,'gradable','set',$val);
}
- &LONCAPA::map::storeparameter($residx,'parameter_0_gradable',$val,
- 'string_yesno');
- &remember_parms($residx,'gradable','set',$val);
+ } else {
+ return (&mt('Failed to save update to external tool.'),1);
}
- } else {
- return (&mt('Failed to save update to external tool.'),1);
}
}
}
@@ -1207,7 +2200,13 @@ sub docs_change_log {
}
$r->print('');
if ($docslog{$id}{'logentry'}{'parameter_res'}) {
- $r->print(&LONCAPA::map::qtescape((split(/\:/,$docslog{$id}{'logentry'}{'parameter_res'}))[0]).':');
+ my ($title,$url) = split(/\:/,$docslog{$id}{'logentry'}{'parameter_res'},3);
+ if ($title eq '') {
+ ($title) = ($url =~ m{/([^/]+)$});
+ } elsif ($is_supp) {
+ $title = &Apache::loncommon::parse_supplemental_title($title);
+ }
+ $r->print(&LONCAPA::map::qtescape($title).':');
foreach my $parameter ('randompick','hiddenresource','encrypturl','randomorder','gradable') {
if ($docslog{$id}{'logentry'}{'parameter_action_'.$parameter}) {
# FIXME: internationalization seems wrong here
@@ -1405,7 +2404,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
@@ -1418,11 +2417,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/) {
@@ -1460,17 +2461,56 @@ 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;
$nopaste = &mt('Paste from another course unavailable.');
}
}
+ } elsif ($url =~ m{/res/($match_domain)/($match_username)/}) {
+ my ($audom,$auname) = ($1,$2);
+ unless (($auname eq $coursenum) && ($audom eq $coursedom)) {
+ if (&Apache::lonnet::is_course($audom,$auname)) {
+ $canpaste = 0;
+ $nopaste = &mt('Paste from another course unavailable.');
+ }
+ }
}
if ($canpaste) {
push(@pasteable,$suffix);
@@ -1763,9 +2803,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});
@@ -1804,13 +2847,53 @@ 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;
+ } elsif ($url =~ m{^/res/($match_domain)/($match_courseid)/}) {
+ my ($audom,$auname) = ($1,$2);
+# When buffer was populated using an active role in a different course
+# disallow pasting of published resources from Course Authoring Space
+ unless (($auname eq $coursenum) && ($audom eq $coursedom)) {
+ if (&Apache::lonnet::is_course($audom,$auname)) {
+ $othcrsres{$suffix} = 1;
+ next;
+ }
+ }
}
$srcmapidx{$suffix} = $mapidx;
push(@dopaste,$suffix);
@@ -1862,6 +2945,8 @@ 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.',
);
@@ -1890,7 +2975,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) {
@@ -1989,12 +3076,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;
@@ -2163,6 +3265,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)) {
@@ -2211,6 +3317,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) = @_;
@@ -2272,7 +3402,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'};
@@ -2316,6 +3447,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) =
@@ -2335,13 +3577,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')) {
@@ -2496,18 +3765,37 @@ 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;
next;
}
}
+ if ($ressrc =~ m{^/res/($match_domain)/($match_courseid)/}) {
+ my ($srcdom,$srcnum) = ($1,$2);
+ unless (($srcnum eq $coursenum) && ($srcdom eq $coursedom)) {
+ if (&Apache::lonnet::is_course($srcdom,$srcnum)) {
+ $removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc;
+ next;
+ }
+ }
+ }
if ($ressrc =~ m{^/(res|uploaded)/.+\.(sequence|page)$}) {
if ($1 eq 'uploaded') {
$hierarchy->{$url}{$token->[2]->{'id'}} = $ressrc;
@@ -2642,7 +3930,7 @@ sub url_paste_fixups {
if ($is_exttool) {
$exttoolchg = 1;
}
- } elsif (($rem =~ m{\d+/ext\.tool$}) &&
+ } elsif (($is_exttool) &&
($env{'form.docs.markedcopy_options'} ne 'move')) {
$dbcopies->{$oldurl}{$id}{'src'} = $ressrc;
$dbcopies->{$oldurl}{$id}{'cdom'} = $srcdom;
@@ -2702,7 +3990,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'}};
@@ -2853,6 +4143,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') {
@@ -2873,10 +4164,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;
}
@@ -3015,6 +4359,10 @@ sub apply_fixups {
}
}
}
+ if (($updatetoolscache) || (@updatetoolsenc)) {
+ &update_ltitools_caches($cdom,$cnum,$updatetoolscache,
+ \@updatetoolsenc);
+ }
}
return ('ok',\@msgs,$lockmsg);
}
@@ -3109,7 +4457,7 @@ sub update_parameter {
my ($name,$url)=split(/\:/,$LONCAPA::map::resources[$res]);
$name=&LONCAPA::map::qtescape($name);
$url=&LONCAPA::map::qtescape($url);
- next unless ($name && $url);
+ next unless $url;
my $is_map;
if ($url =~ m{/uploaded/.+\.(page|sequence)$}) {
$is_map = 1;
@@ -3562,7 +4910,7 @@ sub editor {
}
if ((!$allowed) && ($folder =~ /^supplemental_\d+$/)) {
- my ($supplemental) = &Apache::lonnet::get_supplemental($coursenum,$coursedom);
+ my ($supplemental) = &Apache::loncommon::get_supplemental($coursenum,$coursedom);
if (ref($supplemental) eq 'HASH') {
if ((ref($supplemental->{'hidden'}) eq 'HASH') &&
(ref($supplemental->{'ids'}) eq 'HASH')) {
@@ -3739,7 +5087,7 @@ sub multiple_check_form {
return unless (ref($listsref) eq 'HASH');
my $disabled;
unless ($canedit) {
- $disabled = 'disabled="disabled"';
+ $disabled = ' disabled="disabled"';
}
my $output =
' '."\n".
''.
''.
- ' '.&mt('Copy').
+ ' '.&mt('Copy').
' '.
''."\n";
}
@@ -3992,11 +5340,13 @@ sub entryline {
my ($index,$title,$url,$folder,$allowed,$residx,$coursenum,$coursedom,
$crstype,$pathitem,$supplementalflag,$container,$filtersref,$currgroups,
$ltitoolsref,$canedit,$isencrypted,$ishidden,$navmapref,$hostname)=@_;
- my ($foldertitle,$renametitle,$oldtitle);
+ my ($foldertitle,$renametitle,$oldtitle,$encodedtitle);
if (&is_supplemental_title($title)) {
($title,$foldertitle,$renametitle) = &Apache::loncommon::parse_supplemental_title($title);
+ $encodedtitle=$title;
} else {
$title=&HTML::Entities::encode($title,'"<>&\'');
+ $encodedtitle=$title;
$renametitle=$title;
$foldertitle=$title;
}
@@ -4292,7 +5642,7 @@ END
$nomodal = 1;
}
}
- my ($checkencrypt,$shownurl);
+ my $checkencrypt;
if (!$env{'request.role.adv'}) {
if (((&LONCAPA::map::getparameter($orderidx,'parameter_encrypturl'))[0]=~/^yes$/i) ||
($isencrypted) || (&Apache::lonnet::EXT('resource.0.encrypturl',$symb) =~ /^yes$/i)) {
@@ -4312,7 +5662,7 @@ END
my $currenc = $env{'request.enc'};
$env{'request.enc'} = 1;
$shownsymb = &Apache::lonenc::encrypted($symb);
- $shownurl = &Apache::lonenc::encrypted($url);
+ my $shownurl = &Apache::lonenc::encrypted($url);
if (&Apache::lonnet::symbverify($symb,$url)) {
$url = $shownurl;
} else {
@@ -4327,7 +5677,8 @@ END
$url = &Apache::lonnet::clutter($url);
}
}
- $shownurl = $url;
+ } else {
+ $url = '';
}
unless ($env{'request.role.adv'}) {
if ((&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i) {
@@ -4338,8 +5689,8 @@ END
$hiddenres = 1;
}
}
- if ($url ne '') {
- $url = $shownurl.(($shownurl=~/\?/)?'&':'?').'symb='.&escape($shownsymb);
+ if (($url ne '') && ($shownsymb ne '')) {
+ $url .= (($url=~/\?/)?'&':'?').'symb='.&escape($shownsymb);
}
}
} elsif ($supplementalflag) {
@@ -4368,7 +5719,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')
@@ -4474,7 +5825,7 @@ $form_common."\n".
' '.&mt('Random Order').' '.
$form_end;
}
- } elsif ($supplementalflag && !$allowed) {
+ } elsif ($supplementalflag) {
my $isexttool;
if ($url=~m{^/adm/$coursedom/$coursenum/\d+/ext\.tool$}) {
$url='/adm/wrapper'.$url;
@@ -4483,7 +5834,7 @@ $form_end;
$url .= ($url =~ /\?/) ? '&':'?';
$url .= 'folderpath='.&HTML::Entities::encode($esc_path,'<>&"');
if ($title) {
- $url .= '&title='.&HTML::Entities::encode($renametitle,'<>&"');
+ $url .= '&title='.$encodedtitle;
}
if ((($isexternal) || ($isexttool)) && $orderidx) {
$url .= '&idx='.$orderidx;
@@ -4537,7 +5888,7 @@ $form_end;
} else {
$reinit = &mt('(re-initialize course to access)');
}
- $line.=''.$editlink.$renamelink;
+ $line.=' '.$editlink.$renamelink.' ';
if ($orig_url =~ /$LONCAPA::assess_re/) {
$line.= ' ';
if ($curralias ne '') {
@@ -4548,7 +5899,7 @@ $form_end;
$lt{'sa'}.'';
}
}
- $line.='';
+ $line.=' ';
my ($link,$nolink);
if (($url=~m{/adm/(coursedocs|supplemental)}) || (!$allowed && $url)) {
if ($allowed && !$env{'request.role.adv'} && !$isfolder && !$ispage) {
@@ -4569,12 +5920,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;
@@ -4644,7 +6003,7 @@ $form_end;
my ($enctext,$hidtext,$formhidden,$formurlhidden);
if ((&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i) {
$hidtext = ' checked="checked"';
- if (($ishash) && (ref($filtersref->{'randomorder'}) eq 'ARRAY')) {
+ if (($ishash) && (ref($filtersref->{'hiddenresource'}) eq 'ARRAY')) {
push(@{$filtersref->{'hiddenresource'}},$orderidx);
}
}
@@ -5028,7 +6387,7 @@ sub short_urls {
}
my %currtiny = &Apache::lonnet::dump('tiny',$cdom,$cnum);
$r->print(&Apache::loncourserespicker::create_picker($navmap,'shorturls',$formname,$crstype,undef,
- undef,undef,undef,undef,undef,\%currtiny,$readonly));
+ undef,undef,undef,undef,undef,\%currtiny,undef,$readonly));
}
$r->print(&endContentScreen());
}
@@ -5503,6 +6862,7 @@ sub handler {
my $crstype = &Apache::loncommon::course_type();
my $coursenum=$env{'course.'.$env{'request.course.id'}.'.num'};
my $coursedom=$env{'course.'.$env{'request.course.id'}.'.domain'};
+ my $coursehome=$env{'course.'.$env{'request.course.id'}.'.home'};
# get docroot
my $londocroot = $r->dir_config('lonDocRoot');
@@ -5518,7 +6878,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
@@ -5589,8 +6951,15 @@ 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 || $canview) && ($env{'form.copyauthored'})) {
+ &init_breadcrumbs('copyauthored','Copy from Course Authoring to User Authoring');
+ my $readonly;
+ if (!$canedit) {
+ $readonly = 1;
+ }
+ ©crsauthored($r,$coursenum,$coursedom,$coursehome,$readonly);
} elsif ($canedit && $env{'form.exportcourse'}) {
&init_breadcrumbs('exportcourse','IMS Export');
&Apache::imsexport::exportcourse($r);
@@ -5693,8 +7062,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; }
@@ -5716,6 +7088,7 @@ sub handler {
my $containertag;
my $pathitem;
my %ltitools;
+ my $posslti;
my $hiddentop;
my $navmap;
my $filterFunc = sub { my $res = shift; return (!$res->randomout() && !$res->is_map()) };
@@ -5769,9 +7142,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();
}
@@ -5784,7 +7157,7 @@ sub handler {
}
# If allowed and user's role is not advanced check folderpath is not hidden
my $hidden_and_empty;
- if (($allowed) && (!$env{'request.role.adv'}) && ($env{'form.folderpath'} ne '')) {
+ if (($allowed) && (!$env{'request.role.adv'}) && ($env{'form.folderpath'} ne '')) {
my ($folderurl,$foldername,$hiddenfolder);
my @pathitems = split(/\&/,$env{'form.folderpath'});
my $folder = $pathitems[-2];
@@ -5800,7 +7173,7 @@ sub handler {
if ($supplementalflag) {
($foldername,$hiddenfolder) = ($pathitems[-1] =~ /^([^:]*)::(|1):::$/);
$foldername = &HTML::Entities::decode(&unescape($foldername));
- my ($supplemental) = &Apache::lonnet::get_supplemental($coursenum,$coursedom);
+ my ($supplemental) = &Apache::loncommon::get_supplemental($coursenum,$coursedom);
if (ref($supplemental) eq 'HASH') {
my ($suppmap,$suppmapnum);
if ($folder eq 'supplemental') {
@@ -5949,8 +7322,19 @@ sub handler {
}
}
my $tabidstr = join("','",@tabids);
- %ltitools = &Apache::lonnet::get_domain_lti($coursedom,'consumer');
- my $posslti = keys(%ltitools);
+ my (%domtools,%crstools);
+ my %tooltypes = &Apache::loncommon::usable_exttools();
+ if ($tooltypes{'dom'}) {
+ %domtools = &Apache::lonnet::get_domain_lti($coursedom,'consumer');
+ }
+ if ($tooltypes{'crs'}) {
+ %crstools = &Apache::lonnet::get_course_lti($coursenum,$coursedom,'consumer');
+ }
+ %ltitools = (
+ dom => \%domtools,
+ crs => \%crstools,
+ );
+ $posslti = scalar(keys(%domtools)) + scalar(keys(%crstools));
my $hostname = $r->hostname();
$script .= &editing_js($udom,$uname,$supplementalflag,$coursedom,$coursenum,$posslti,
$londocroot,$canedit,$hostname,\$navmap).
@@ -5989,8 +7373,10 @@ sub handler {
if ($showdoc) {
my $args;
if ($supplementalflag) {
- my $brcrum = &Apache::lonhtmlcommon::docs_breadcrumbs(undef,$crstype,undef,$env{'form.title'},1);
- $args = {'bread_crumbs' => $brcrum};
+ my $title = &HTML::Entities::encode($env{'form.title'},'\'"<>&');
+ my $brcrum = &Apache::lonhtmlcommon::docs_breadcrumbs(undef,$crstype,undef,$title,1);
+ $args = {'bread_crumbs' => $brcrum,
+ 'bread_crumbs_nomenu' => 1};
} else {
$args = {'force_register' => $showdoc};
}
@@ -6019,8 +7405,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";
@@ -6105,7 +7496,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)) {
# -----------------------------------------------------------------------------
@@ -6113,8 +7504,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',
@@ -6132,6 +7523,7 @@ sub handler {
'stpr' => 'Standard Problem',
'news' => 'New sub-directory',
'crpr' => 'Create Problem',
+ 'swit' => 'Switch Server',
'drbx' => 'Drop Box',
'scuf' => 'External Scores (handgrade, upload, clicker)',
'bull' => 'Discussion Board',
@@ -6152,6 +7544,7 @@ sub handler {
'dire' => 'Directory:',
'cate' => 'Category:',
'tmpl' => 'Template:',
+ 'empd' => 'No resources found',
'comment' => 'Comment',
'parse' => 'Upload embedded images/multimedia files if HTML file',
'bb5' => 'Blackboard 5',
@@ -6201,10 +7594,7 @@ sub handler {
my $fileupload=(<
-
-
FIUP
-
my $checkbox=(<$lt{'parse'}?
@@ -6224,6 +7614,8 @@ CHBO
$lt{'imsf'}
$fileupload
+
+
$lt{'cms'}:
@@ -6250,6 +7642,8 @@ IMSFORM
$lt{'upfi'}
$fileupload
+
+
$lt{'title'}:
@@ -6288,28 +7682,56 @@ FUFORM
SEDFFORM
- my $importcrsresform;
- my ($numdirs,$pickfile) =
- &Apache::loncommon::import_crsauthor_form('crsresimportform','coursepath','coursefile',
- "resize_scrollbox('contentscroll','1','0');",
- undef,'res');
- if ($pickfile) {
- $importcrsresform=(<
-
+
+
+ $rolehomes
+
+
RESFORM
+ }
my $specialdocumentsform;
my @specialdocumentsforma;
@@ -6816,7 +8179,7 @@ NGFFORM
my @external = (
{' '=>$extresourcesform}
);
- if (keys(%ltitools)) {
+ if ($posslti) {
push(@external,
{' '=>$exttoolform},
);
@@ -6837,9 +8200,13 @@ NGFFORM
@gradingforma=(
{' '=>$newsmpproblemform},
{' '=>$newdropboxform},
- {' '=>$newexuploadform},
- {' '=>$crsresform},
+ {' '=>$newexuploadform}
);
+ if ($crsresform) {
+ push(@gradingforma,
+ {' '=>$crsresform}
+ );
+ }
$gradingform = &create_form_ul(&create_list_elements(@gradingforma));
@communityforma=(
@@ -6853,9 +8220,9 @@ NGFFORM
my %orderhash = (
'aa' => ['Upload',$fileuploadform],
- 'bb' => ['Import',$importpubform],
- 'cc' => ['External',$externalform],
- 'dd' => ['Grading',$gradingform],
+ 'bb' => ['External',$externalform],
+ 'cc' => ['Import',$importpubform],
+ 'dd' => ['Assessment',$gradingform],
'ff' => ['Other',$specialdocumentsform],
);
unless ($container eq 'page') {
@@ -6908,6 +8275,8 @@ unless ($container eq 'page') {
$lt{'upfi'}
$fileupload
+
+
@@ -6920,6 +8289,7 @@ unless ($container eq 'page') {
$pathitem
+
SUPDOCFORM
@@ -6999,7 +8369,7 @@ my @specialdocs = (
my @supexternal = (
{' '
=>$supextform});
- if (keys(%ltitools)) {
+ if ($posslti) {
push(@supexternal,
{' '
=>$supexttoolform});
@@ -7231,7 +8601,7 @@ sub remove_archive {
}
sub generate_admin_menu {
- my ($crstype,$canedit) = @_;
+ my ($crstype,$canedit,$coursenum,$coursedom) = @_;
my $lc_crstype = lc($crstype);
my ($home,$other,%outhash)=&authorhosts();
my %lt= ( # do not translate here
@@ -7239,14 +8609,17 @@ sub generate_admin_menu {
'cv' => 'Check/Set Resource Versions',
'ls' => 'List Resource Identifiers',
'ct' => 'Display/Set Shortened URLs for Deep-linking',
+ 'ca' => "Enter $crstype Authoring Space",
'imse' => 'Export contents to IMS Archive',
- 'dcd' => "Copy $crstype Content to Authoring Space",
+ 'dcd' => 'Copy uploaded content to Authoring Space',
+ 'cpc' => 'Copy from Course Authoring to User Authoring',
);
- my ($candump,$dumpurl);
+ my ($candump,$dumpurl,$exportcrsurl);
if ($home + $other > 0) {
$candump = 'F';
if ($home) {
$dumpurl = "javascript:injectData(document.courseverify,'dummy','dumpcourse','$lt{'dcd'}')";
+ $exportcrsurl = "javascript:injectData(document.courseverify,'dummy','copyauthored','$lt{'cpc'}')";
} else {
my @hosts;
foreach my $aurole (keys(%outhash)) {
@@ -7260,8 +8633,10 @@ sub generate_admin_menu {
&HTML::Entities::encode($env{'request.role'},'"<>&').'&origurl='.
&HTML::Entities::encode('/adm/coursedocs?dumpcourse=1','"<>&');
$dumpurl = "javascript:dump_needs_switchserver('$switchto')";
+ $exportcrsurl = $dumpurl;
} else {
$dumpurl = "javascript:choose_switchserver_window()";
+ $exportcrsurl = $dumpurl;
}
}
}
@@ -7299,6 +8674,33 @@ sub generate_admin_menu {
]
});
if ($canedit) {
+ my ($crsauname,$crsaudom,$crshome);
+ if (($coursenum ne '') && ($coursedom ne '')) {
+ my $crsauthorurl = "/priv/$coursedom/$coursenum/";
+ ($crsauname,$crsaudom,$crshome) = &Apache::lonnet::constructaccess($crsauthorurl);
+ if (($crsauname eq $coursenum) && ($crsaudom eq $coursedom)) {
+ my @ids=&Apache::lonnet::current_machine_ids();
+ my $linkurl;
+ if (grep(/^\Q$crshome\E$/,@ids)) {
+ $linkurl = $crsauthorurl;
+ } else {
+ my $jscall = &Apache::lonhtmlcommon::jump_to_editres($crsauthorurl,$crshome,1);
+ if ($jscall) {
+ $linkurl = 'javascript:'.$jscall;
+ }
+ }
+ if ((ref($menu[0]) eq 'HASH') && (ref($menu[0]->{'items'}) eq 'ARRAY') && ($linkurl)) {
+ push(@{$menu[0]->{items}},
+ { linktext => $lt{'ca'},
+ url => $linkurl,
+ permission => 'F',
+ help => 'Docs_Course_Authorspace',
+ icon => 'impcrsau.png',
+ linktitle => $lt{'ca'},
+ });
+ }
+ }
+ }
push(@menu,
{ categorytitle=>'Export',
items =>[
@@ -7318,6 +8720,18 @@ sub generate_admin_menu {
},
]
});
+ if (($crsauname eq $coursenum) && ($crsaudom eq $coursedom)) {
+ if ((ref($menu[1]) eq 'HASH') && (ref($menu[1]->{'items'}) eq 'ARRAY')) {
+ push(@{$menu[1]->{items}},
+ { linktext => $lt{'cpc'},
+ url => $exportcrsurl,
+ permission => 'F',
+ help => 'Docs_Export_Course_Author',
+ icon => 'res.png',
+ linktitle => $lt{'cpc'},
+ });
+ }
+ }
}
return '