File:
[LON-CAPA] /
loncom /
interface /
londocs.pm
Revision
1.454:
download - view:
text,
annotated -
select for diffs
Mon Jul 4 13:01:53 2011 UTC (13 years, 1 month ago) by
raeburn
Branches:
MAIN
CVS tags:
HEAD
- More options when exporting course content as IMS package.
Export single rendering of selected problems in a course to testbank file.
(MSU requirement for third party customized secure exam platform).
Work in progress.
1: # The LearningOnline Network
2: # Documents
3: #
4: # $Id: londocs.pm,v 1.454 2011/07/04 13:01:53 raeburn Exp $
5: #
6: # Copyright Michigan State University Board of Trustees
7: #
8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
9: #
10: # LON-CAPA is free software; you can redistribute it and/or modify
11: # it under the terms of the GNU General Public License as published by
12: # the Free Software Foundation; either version 2 of the License, or
13: # (at your option) any later version.
14: #
15: # LON-CAPA is distributed in the hope that it will be useful,
16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18: # GNU General Public License for more details.
19: #
20: # You should have received a copy of the GNU General Public License
21: # along with LON-CAPA; if not, write to the Free Software
22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23: #
24: # /home/httpd/html/adm/gpl.txt
25: #
26: # http://www.lon-capa.org/
27: #
28:
29:
30:
31: package Apache::londocs;
32:
33: use strict;
34: use Apache::Constants qw(:common :http);
35: use Apache::imsexport;
36: use Apache::lonnet;
37: use Apache::loncommon;
38: use Apache::lonhtmlcommon;
39: use LONCAPA::map();
40: use Apache::lonratedt();
41: use Apache::lonxml;
42: use Apache::lonclonecourse;
43: use Apache::lonnavmaps;
44: use HTML::Entities;
45: use GDBM_File;
46: use Apache::lonlocal;
47: use Cwd;
48: use LONCAPA qw(:DEFAULT :match);
49:
50: my $iconpath;
51:
52: my %hash;
53:
54: my $hashtied;
55: my %alreadyseen=();
56:
57: my $hadchanges;
58:
59:
60: my %help=();
61:
62:
63: sub mapread {
64: my ($coursenum,$coursedom,$map)=@_;
65: return
66: &LONCAPA::map::mapread('/uploaded/'.$coursedom.'/'.$coursenum.'/'.
67: $map);
68: }
69:
70: sub storemap {
71: my ($coursenum,$coursedom,$map)=@_;
72: my ($outtext,$errtext)=
73: &LONCAPA::map::storemap('/uploaded/'.$coursedom.'/'.$coursenum.'/'.
74: $map,1);
75: if ($errtext) { return ($errtext,2); }
76:
77: $hadchanges=1;
78: return ($errtext,0);
79: }
80:
81:
82:
83: sub authorhosts {
84: my %outhash=();
85: my $home=0;
86: my $other=0;
87: foreach my $key (keys(%env)) {
88: if ($key=~/^user\.role\.(au|ca)\.(.+)$/) {
89: my $role=$1;
90: my $realm=$2;
91: my ($start,$end)=split(/\./,$env{$key});
92: if (($start) && ($start>time)) { next; }
93: if (($end) && (time>$end)) { next; }
94: my ($ca,$cd);
95: if ($1 eq 'au') {
96: $ca=$env{'user.name'};
97: $cd=$env{'user.domain'};
98: } else {
99: ($cd,$ca)=($realm=~/^\/($match_domain)\/($match_username)$/);
100: }
101: my $allowed=0;
102: my $myhome=&Apache::lonnet::homeserver($ca,$cd);
103: my @ids=&Apache::lonnet::current_machine_ids();
104: foreach my $id (@ids) { if ($id eq $myhome) { $allowed=1; } }
105: if ($allowed) {
106: $home++;
107: $outhash{'home_'.$ca.'@'.$cd}=1;
108: } else {
109: $outhash{'otherhome_'.$ca.'@'.$cd}=$myhome;
110: $other++;
111: }
112: }
113: }
114: return ($home,$other,%outhash);
115: }
116:
117:
118: sub dumpbutton {
119: my ($home,$other,%outhash)=&authorhosts();
120: my $crstype = &Apache::loncommon::course_type();
121: if ($home+$other==0) { return ''; }
122: if ($home) {
123: my $link =
124: "<a class='LC_menubuttons_link' href='javascript:injectData(document.courseverify, \"dummy\", \"dumpcourse\", \""
125: .&mt('Dump '.$crstype.' Documents to Construction Space')
126: ."\")'>"
127: .&mt('Dump '.$crstype.' Documents to Construction Space')
128: .'</a>';
129: return
130: $link.' '
131: .&Apache::loncommon::help_open_topic('Docs_Dump_Course_Docs')
132: .'<br />';
133: } else {
134: return
135: &mt('Dump '.$crstype.' Documents to Construction Space: available on other servers');
136: }
137: }
138:
139: sub clean {
140: my ($title)=@_;
141: $title=~s/[^\w\/\!\$\%\^\*\-\_\=\+\;\:\,\\\|\`\~]+/\_/gs;
142: return $title;
143: }
144:
145:
146:
147: sub dumpcourse {
148: my ($r) = @_;
149: my $crstype = &Apache::loncommon::course_type();
150: $r->print(&Apache::loncommon::start_page('Dump '.$crstype.' Documents to Construction Space').
151: '<form name="dumpdoc" action="" method="post">');
152: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Dump '.$crstype.' Documents to Construction Space'));
153: my ($home,$other,%outhash)=&authorhosts();
154: unless ($home) { return ''; }
155: my $origcrsid=$env{'request.course.id'};
156: my %origcrsdata=&Apache::lonnet::coursedescription($origcrsid);
157: if (($env{'form.authorspace'}) && ($env{'form.authorfolder'}=~/\w/)) {
158: # Do the dumping
159: unless ($outhash{'home_'.$env{'form.authorspace'}}) { return ''; }
160: my ($ca,$cd)=split(/\@/,$env{'form.authorspace'});
161: $r->print('<h3>'.&mt('Copying Files').'</h3>');
162: my $title=$env{'form.authorfolder'};
163: $title=&clean($title);
164: my %replacehash=();
165: foreach my $key (keys(%env)) {
166: if ($key=~/^form\.namefor\_(.+)/) {
167: $replacehash{$1}=$env{$key};
168: }
169: }
170: my $crs='/uploaded/'.$env{'request.course.id'}.'/';
171: $crs=~s/\_/\//g;
172: foreach my $item (keys(%replacehash)) {
173: my $newfilename=$title.'/'.$replacehash{$item};
174: $newfilename=~s/\.(\w+)$//;
175: my $ext=$1;
176: $newfilename=&clean($newfilename);
177: $newfilename.='.'.$ext;
178: my @dirs=split(/\//,$newfilename);
179: my $path='/home/'.$ca.'/public_html';
180: my $makepath=$path;
181: my $fail=0;
182: for (my $i=0;$i<$#dirs;$i++) {
183: $makepath.='/'.$dirs[$i];
184: unless (-e $makepath) {
185: unless(mkdir($makepath,0777)) { $fail=1; }
186: }
187: }
188: $r->print('<br /><tt>'.$item.'</tt> => <tt>'.$newfilename.'</tt>: ');
189: if (my $fh=Apache::File->new('>'.$path.'/'.$newfilename)) {
190: if ($item=~/\.(sequence|page|html|htm|xml|xhtml)$/) {
191: print $fh &Apache::lonclonecourse::rewritefile(
192: &Apache::lonclonecourse::readfile($env{'request.course.id'},$item),
193: (%replacehash,$crs => '')
194: );
195: } else {
196: print $fh
197: &Apache::lonclonecourse::readfile($env{'request.course.id'},$item);
198: }
199: $fh->close();
200: } else {
201: $fail=1;
202: }
203: if ($fail) {
204: $r->print('<span class="LC_error">'.&mt('fail').'</span>');
205: } else {
206: $r->print('<span class="LC_success">'.&mt('ok').'</span>');
207: }
208: }
209: } else {
210: # Input form
211: unless ($home==1) {
212: $r->print(
213: '<h3>'.&mt('Select the Construction Space').'</h3><select name="authorspace">');
214: }
215: foreach my $key (sort(keys(%outhash))) {
216: if ($key=~/^home_(.+)$/) {
217: if ($home==1) {
218: $r->print(
219: '<input type="hidden" name="authorspace" value="'.$1.'" />');
220: } else {
221: $r->print('<option value="'.$1.'">'.$1.' - '.
222: &Apache::loncommon::plainname(split(/\@/,$1)).'</option>');
223: }
224: }
225: }
226: unless ($home==1) {
227: $r->print('</select>');
228: }
229: my $title=$origcrsdata{'description'};
230: $title=~s/[\/\s]+/\_/gs;
231: $title=&clean($title);
232: $r->print('<h3>'.&mt('Folder in Construction Space').'</h3>'
233: .'<input type="text" size="50" name="authorfolder" value="'.$title.'" /><br />');
234: &tiehash();
235: $r->print('<h3>'.&mt('Filenames in Construction Space').'</h3>'
236: .&Apache::loncommon::start_data_table()
237: .&Apache::loncommon::start_data_table_header_row()
238: .'<th>'.&mt('Internal Filename').'</th>'
239: .'<th>'.&mt('Title').'</th>'
240: .'<th>'.&mt('Save as ...').'</th>'
241: .&Apache::loncommon::end_data_table_header_row());
242: foreach my $file (&Apache::lonclonecourse::crsdirlist($origcrsid,'userfiles')) {
243: $r->print(&Apache::loncommon::start_data_table_row()
244: .'<td>'.$file.'</td>');
245: my ($ext)=($file=~/\.(\w+)$/);
246: my $title=$hash{'title_'.$hash{
247: 'ids_/uploaded/'.$origcrsdata{'domain'}.'/'.$origcrsdata{'num'}.'/'.$file}};
248: $r->print('<td>'.($title?$title:' ').'</td>');
249: if (!$title) {
250: $title=$file;
251: } else {
252: $title=~s|/|_|g;
253: }
254: $title=~s/\.(\w+)$//;
255: $title=&clean($title);
256: $title.='.'.$ext;
257: $r->print("\n<td><input type='text' size='60' name='namefor_".$file."' value='".$title."' /></td>"
258: .&Apache::loncommon::end_data_table_row());
259: }
260: $r->print(&Apache::loncommon::end_data_table());
261: &untiehash();
262: $r->print(
263: '<p><input type="submit" name="dumpcourse" value="'.&mt("Dump $crstype Documents").'" /></p></form>');
264: }
265: }
266:
267:
268:
269: sub exportbutton {
270: my $crstype = &Apache::loncommon::course_type();
271: return "<a class='LC_menubuttons_link' href='javascript:injectData(document.courseverify, \"dummy\", \"exportcourse\", \"".&mt('IMS Export')."\")'>".&mt('IMS Export')."</a>".
272: &Apache::loncommon::help_open_topic('Docs_Export_Course_Docs').'<br />';
273: }
274:
275:
276:
277: sub exportcourse {
278: my $r=shift;
279: my $crstype = &Apache::loncommon::course_type();
280: my %discussiontime = &Apache::lonnet::dump('discussiontimes',
281: $env{'course.'.$env{'request.course.id'}.'.domain'}, $env{'course.'.$env{'request.course.id'}.'.num'});
282: my $numdisc = keys(%discussiontime);
283: my $numprobs = 0;
284: my $navmap = Apache::lonnavmaps::navmap->new();
285: if (!defined($navmap)) {
286: $r->print(&Apache::loncommon::start_page('Export '.$crstype.' to IMS Package').
287: '<h2>'.&mt('IMS Export Failed').'</h2>'.
288: '<div class="LC_error">');
289: if ($crstype eq 'Community') {
290: $r->print(&mt('Unable to retrieve information about community contents'));
291: } else {
292: $r->print(&mt('Unable to retrieve information about course contents'));
293: }
294: $r->print('</div><a href="/adm/coursedocs">');
295: if ($crstype eq 'Community') {
296: $r->print(&mt('Return to Community Editor'));
297: } else {
298: $r->print(&mt('Return to Course Editor'));
299: }
300: $r->print('</a>');
301: &Apache::lonnet::logthis('IMS export failed - could not create navmap object in '.lc($crstype).':'.$env{'request.course.id'});
302: return;
303: }
304: my $it=$navmap->getIterator(undef,undef,undef,1,undef,undef);
305: my $curRes;
306: my $outcome;
307:
308: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
309: ['finishexport']);
310: if ($env{'form.finishexport'}) {
311: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
312: ['archive','discussion']);
313:
314: my $format = $env{'form.format'};
315: my @exportitems = &Apache::loncommon::get_env_multiple('form.archive');
316: my @discussions = &Apache::loncommon::get_env_multiple('form.discussion');
317: if (@exportitems == 0 && @discussions == 0) {
318: $outcome =
319: '<p class="LC_warning">'
320: .&mt('As you did not select any content items or discussions'
321: .' for export, an IMS package has not been created.')
322: .'</p>'
323: .'<p>'
324: .&mt('Please [_1]go back[_2] to select either content items'
325: .' or discussions for export.'
326: ,'<a href="javascript:history.go(-1)">'
327: ,'</a>')
328: .'</p>';
329: } else {
330: my $now = time;
331: my %symbs;
332: my $manifestok = 0;
333: my $imsresources;
334: my $tempexport;
335: my $copyresult;
336: my $testbank;
337: my $ims_manifest = &create_ims_store($now,\$manifestok,\$outcome,\$tempexport,$format,\$testbank);
338: if ($manifestok) {
339: &build_package($now,$navmap,\@exportitems,\@discussions,\$outcome,$tempexport,\$copyresult,$ims_manifest,$format,$testbank);
340: close($ims_manifest);
341:
342: #Create zip file in prtspool
343: my $imszipfile = '/prtspool/'.
344: $env{'user.name'}.'_'.$env{'user.domain'}.'_'.
345: time.'_'.rand(1000000000).'.zip';
346: my $cwd = &Cwd::getcwd();
347: my $imszip = '/home/httpd/'.$imszipfile;
348: chdir $tempexport;
349: open(OUTPUT, "zip -r $imszip * 2> /dev/null |");
350: close(OUTPUT);
351: chdir $cwd;
352: $outcome .= '<p>'
353: .&mt('[_1]Your IMS package[_2] is ready for download.'
354: ,'<a href="'.$imszipfile.'">','</a>')
355: .'</p>';
356: if ($copyresult) {
357: $outcome .= '<p class="LC_error">'
358: .&mt('The following errors occurred during export - [_1]'
359: ,$copyresult)
360: .'</p>';
361: }
362: } else {
363: $outcome = '<p class="LC_error">'
364: .&mt('Unfortunately you will not be able to retrieve'
365: .' an IMS archive of your course at this time,'
366: .' because there was a problem creating a'
367: .' manifest file.')
368: .'</p>'
369: .'<p><a href="javascript:history.go(-1)">'
370: .&mt('Go Back')
371: .'</a></p>';
372: }
373: }
374: $r->print(&Apache::loncommon::start_page('Export '.$crstype.' to IMS Package'));
375: $r->print(&Apache::lonhtmlcommon::breadcrumbs('IMS Export'));
376: $r->print($outcome);
377: $r->print(&Apache::loncommon::end_page());
378: } else {
379: my $display='<form name="exportdoc" action="" method="post">'."\n".
380: '<p>'.
381: &mt('Choose which items you wish to export from your '.$crstype.'.').
382: '</p>'.
383: '<div class="LC_columnSection"><fieldset>'.
384: '<legend>'.&mt('Content items').'</legend>'.
385: '<input type="button" value="'.&mt('check all').'" '.
386: 'onclick="javascript:checkAll(document.exportdoc.archive)" />'.
387: ' <input type="button" value="'.&mt('uncheck all').'"'.
388: ' onclick="javascript:uncheckAll(document.exportdoc.archive)" /></fieldset>';
389: if ($numdisc > 0) {
390: $display .= '<fieldset>'.
391: '<legend>'.&mt('Discussion posts').'</legend>'.
392: '<input type="button" value="'.&mt('check all').'"'.
393: ' onclick="javascript:checkAll(document.exportdoc.discussion)" />'.
394: ' <input type="button" value="'.&mt('uncheck all').'"'.
395: ' onclick="javascript:uncheckAll(document.exportdoc.discussion)" />'.
396: '</fieldset>';
397: }
398: $display .= '</div>';
399: my $curRes;
400: my $depth = 0;
401: my $count = 0;
402: my $boards = 0;
403: my $startcount = 5;
404: my %parent = ();
405: my %children = ();
406: my $lastcontainer = $startcount;
407: $display .= &Apache::loncommon::start_data_table()
408: .&Apache::loncommon::start_data_table_header_row()
409: .'<th>'.&mt('Export content item?').'</th>';
410: if ($numdisc > 0) {
411: $display .= '<th>'.&mt('Export discussion posts?').'</th>';
412: }
413: $display .= &Apache::loncommon::end_data_table_header_row();
414: while ($curRes = $it->next()) {
415: if (ref($curRes)) {
416: $count ++;
417: }
418: if ($curRes == $it->BEGIN_MAP()) {
419: $depth++;
420: $parent{$depth} = $lastcontainer;
421: }
422: if ($curRes == $it->END_MAP()) {
423: $depth--;
424: $lastcontainer = $parent{$depth};
425: }
426: if (ref($curRes)) {
427: my $symb = $curRes->symb();
428: my $ressymb = $symb;
429: if ($ressymb =~ m|adm/($match_domain)/($match_username)/(\d+)/bulletinboard$|) {
430: unless ($ressymb =~ m|adm/wrapper/adm|) {
431: $ressymb = 'bulletin___'.$3.'___adm/wrapper/adm/'.$1.'/'.$2.'/'.$3.'/bulletinboard';
432: }
433: }
434: my $currelem = $count+$boards+$startcount;
435: $display .= &Apache::loncommon::start_data_table_row()
436: .'<td>'."\n"
437: .'<input type="checkbox" name="archive" value="'.$count.'" ';
438: if (($curRes->is_sequence()) || ($curRes->is_page())) {
439: $lastcontainer = $currelem;
440: $display .= 'onclick="javascript:propagateCheck('."'$currelem'".')"';
441: } elsif ($curRes->is_problem()) {
442: $numprobs ++;
443: }
444: $display .= ' />'."\n";
445: for (my $i=0; $i<$depth; $i++) {
446: $display .= ('<img src="/adm/lonIcons/whitespace1.gif" class="LC_docs_spacer" alt="" />' x2)."\n";
447: }
448: if ($curRes->is_sequence()) {
449: $display .= '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" /> '."\n";
450: } elsif ($curRes->is_page()) {
451: $display .= '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" /> '."\n";
452: }
453: $children{$parent{$depth}} .= $currelem.':';
454: $display .= ' '.$curRes->title().'</td>'."\n";
455:
456: # Existing discussion posts?
457: if ($discussiontime{$ressymb} > 0) {
458: $boards ++;
459: $display .= '<td align="right">'
460: .'<input type="checkbox" name="discussion" value="'.$count.'" />'
461: .'</td>'."\n";
462: } elsif ($numdisc > 0) {
463: $display .= '<td> </td>'."\n";
464: }
465: $display .= &Apache::loncommon::end_data_table_row();
466: }
467: }
468: $display .= &Apache::loncommon::end_data_table();
469: my $scripttag = qq|
470: <script type="text/javascript">
471: // <![CDATA[
472: function checkAll(field) {
473: if (field.length > 0) {
474: for (i = 0; i < field.length; i++) {
475: field[i].checked = true ;
476: }
477: } else {
478: field.checked = true
479: }
480: }
481:
482: function uncheckAll(field) {
483: if (field.length > 0) {
484: for (i = 0; i < field.length; i++) {
485: field[i].checked = false ;
486: }
487: } else {
488: field.checked = false ;
489: }
490: }
491:
492: function propagateCheck(item) {
493: if (document.exportdoc.elements[item].checked == true) {
494: containerCheck(item)
495: }
496: }
497:
498: function containerCheck(item) {
499: document.exportdoc.elements[item].checked = true
500: var numitems = $count + $boards + $startcount
501: var parents = new Array(numitems)
502: for (var i=$startcount; i<numitems; i++) {
503: parents[i] = new Array
504: }
505: |;
506:
507: foreach my $container (sort { $a <=> $b } (keys(%children))) {
508: my @contents = split(/:/,$children{$container});
509: for (my $i=0; $i<@contents; $i ++) {
510: $scripttag .= ' parents['.$container.']['.$i.'] = '.$contents[$i]."\n";
511: }
512: }
513:
514: $scripttag .= qq|
515: if (parents[item].length > 0) {
516: for (var j=0; j<parents[item].length; j++) {
517: containerCheck(parents[item][j])
518: }
519: }
520: }
521: // ]]>
522: </script>
523: |;
524: $r->print(&Apache::loncommon::start_page('Export '.$crstype.' to IMS Package',
525: $scripttag));
526: $r->print(&Apache::lonhtmlcommon::breadcrumbs('IMS Export'));
527: if ($numprobs > 0) {
528: $display .= '<p><span class="LC_nobreak">'.
529: &mt('Export format for LON-CAPA problems:').
530: '<label><input type="radio" name="format" value="xml" checked="checked" />'.
531: ' '.&mt('XML').'</label>'.(' ' x3).
532: '<label><input type="radio" name="format" value="html" />'.
533: ' '.&mt('HTML').'</label>'.(' ' x3).
534: '<label><input type="radio" name="format" value="plaintext" />'.
535: ' '.&mt('Text').'</label></span></p>';
536: }
537: $r->print($display.
538: '<p><input type="hidden" name="finishexport" value="1" />'.
539: '<input type="submit" name="exportcourse" value="'.
540: &mt('Export').'" /></p></form>');
541: }
542: }
543:
544: sub create_ims_store {
545: my ($now,$manifestok,$outcome,$tempexport,$format,$testbank) = @_;
546: $$tempexport = $Apache::lonnet::perlvar{'lonDaemons'}.'/tmp/ims_exports';
547: my $ims_manifest;
548: if (!-e $$tempexport) {
549: mkdir($$tempexport,0700);
550: }
551: $$tempexport .= '/'.$now;
552: if (!-e $$tempexport) {
553: mkdir($$tempexport,0700);
554: }
555: $$tempexport .= '/'.$env{'user.domain'}.'_'.$env{'user.name'};
556: if (!-e $$tempexport) {
557: mkdir($$tempexport,0700);
558: }
559: if (!-e "$$tempexport/resources") {
560: mkdir("$$tempexport/resources",0700);
561: }
562: # open manifest file
563: my $manifest = '/imsmanifest.xml';
564: my $manifestfilename = $$tempexport.$manifest;
565: if ($ims_manifest = Apache::File->new('>'.$manifestfilename)) {
566: $$manifestok=1;
567: print $ims_manifest
568: '<?xml version="1.0" encoding="UTF-8"?>'."\n".
569: '<manifest xmlns="http://www.imsglobal.org/xsd/imscp_v1p1"'.
570: ' xmlns:imsmd="http://www.imsglobal.org/xsd/imsmd_v1p2"'.
571: ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'.
572: ' identifier="MANIFEST-'.$env{'request.course.id'}.'-'.$now.'"'.
573: ' xsi:schemaLocation="http://www.imsglobal.org/xsd/imscp_v1p1imscp_v1p1.xsd'.
574: ' http://www.imsglobal.org/xsd/imsmd_v1p2 imsmd_v1p2p2.xsd">'."\n".
575: ' <metadata>
576: <schema></schema>
577: <imsmd:lom>
578: <imsmd:general>
579: <imsmd:identifier>'.$env{'request.course.id'}.'</imsmd:identifier>
580: <imsmd:title>
581: <imsmd:langstring xml:lang="en">'.$env{'course.'.$env{'request.course.id'}.'.description'}.'</imsmd:langstring>
582: </imsmd:title>
583: </imsmd:general>
584: </imsmd:lom>
585: </metadata>'."\n".
586: ' <organizations default="ORG-'.$env{'request.course.id'}.'-'.$now.'">'."\n".
587: ' <organization identifier="ORG-'.$env{'request.course.id'}.'-'.$now.'"'.
588: ' structure="hierarchical">'."\n".
589: ' <title>'.$env{'course.'.$env{'request.course.id'}.'.description'}.'</title>';
590: if ($format eq 'plaintext') {
591: my $testbankfilename = $$tempexport.'/testbank.txt';
592: $$testbank = Apache::File->new('>'.$testbankfilename);
593: }
594: } else {
595: $$outcome .= 'An error occurred opening the IMS manifest file.<br />'
596: ;
597: }
598: return $ims_manifest;
599: }
600:
601: sub build_package {
602: my ($now,$navmap,$exportitems,$discussions,$outcome,$tempexport,$copyresult,
603: $ims_manifest,$format,$testbank) = @_;
604: # first iterator to look for dependencies
605: my $it = $navmap->getIterator(undef,undef,undef,1,undef,undef);
606: my $curRes;
607: my $count = 0;
608: my $depth = 0;
609: my $lastcontainer = 0;
610: my %parent = ();
611: my @dependencies = ();
612: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
613: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
614: while ($curRes = $it->next()) {
615: if (ref($curRes)) {
616: $count ++;
617: }
618: if ($curRes == $it->BEGIN_MAP()) {
619: $depth++;
620: $parent{$depth} = $lastcontainer;
621: }
622: if ($curRes == $it->END_MAP()) {
623: $depth--;
624: $lastcontainer = $parent{$depth};
625: }
626: if (ref($curRes)) {
627: if ($curRes->is_sequence() || $curRes->is_page()) {
628: $lastcontainer = $count;
629: }
630: if (grep(/^$count$/,@$exportitems)) {
631: &get_dependencies($exportitems,\%parent,$depth,\@dependencies);
632: }
633: }
634: }
635: # second iterator to build manifest and store resources
636: $it = $navmap->getIterator(undef,undef,undef,1,undef,undef);
637: $depth = 0;
638: my $prevdepth;
639: $count = 0;
640: my $imsresources;
641: my $pkgdepth;
642: my $currdirpath = 'Top';
643: while ($curRes = $it->next()) {
644: if ($curRes == $it->BEGIN_MAP()) {
645: $prevdepth = $depth;
646: $depth++;
647: }
648: if ($curRes == $it->END_MAP()) {
649: $prevdepth = $depth;
650: $depth--;
651: }
652:
653: if (ref($curRes)) {
654: $count ++;
655: if ((grep(/^$count$/,@$exportitems)) || (grep(/^$count$/,@dependencies))) {
656: my $symb = $curRes->symb();
657: my $isvisible = 'true';
658: my $resourceref;
659: if ($curRes->randomout()) {
660: $isvisible = 'false';
661: }
662: unless ($curRes->is_sequence()) {
663: $resourceref = 'identifierref="RES-'.$env{'request.course.id'}.'-'.$count.'"';
664: }
665: my $step = $prevdepth - $depth;
666: if (($step >= 0) && ($count > 1)) {
667: while ($step >= 0) {
668: print $ims_manifest "\n".' </item>'."\n";
669: $step --;
670: }
671: }
672: $prevdepth = $depth;
673:
674: my $itementry =
675: '<item identifier="ITEM-'.$env{'request.course.id'}.'-'.$count.
676: '" isvisible="'.$isvisible.'" '.$resourceref.'>'.
677: '<title>'.$curRes->title().'</title>';
678: print $ims_manifest "\n".$itementry;
679:
680: if ($curRes->is_sequence()) {
681: $currdirpath = 'Top';
682: my $pcslist = $curRes->map_hierarchy();
683: if ($pcslist ne '') {
684: foreach my $pc (split(/,/,$pcslist)) {
685: my $res = $navmap->getByMapPc($pc);
686: if (ref($res)) {
687: my $encloser = $res->title();
688: if ($encloser) {
689: if ($currdirpath) {
690: $currdirpath .= ' -> ';
691: }
692: $currdirpath .= $encloser;
693: }
694: }
695: }
696: }
697: } else {
698: my $content_file;
699: my @hrefs = ();
700: &process_content($count,$curRes,$cdom,$cnum,$symb,\$content_file,\@hrefs,$copyresult,$tempexport,$format,$currdirpath,$testbank);
701: if ($content_file) {
702: $imsresources .= "\n".
703: ' <resource identifier="RES-'.$env{'request.course.id'}.'-'.$count.
704: '" type="webcontent" href="'.$content_file.'">'."\n".
705: ' <file href="'.$content_file.'" />'."\n";
706: foreach my $item (@hrefs) {
707: $imsresources .=
708: ' <file href="'.$item.'" />'."\n";
709: }
710: if (grep(/^$count$/,@$discussions)) {
711: my $ressymb = $symb;
712: my $mode;
713: if ($ressymb =~ m|adm/($match_domain)/($match_username)/(\d+)/bulletinboard$|) {
714: unless ($ressymb =~ m|adm/wrapper/adm|) {
715: $ressymb = 'bulletin___'.$3.'___adm/wrapper/adm/'.$1.'/'.$2.'/'.$3.'/bulletinboard';
716: }
717: $mode = 'board';
718: }
719: my %extras = (
720: caller => 'imsexport',
721: tempexport => $tempexport.'/resources',
722: count => $count
723: );
724: my $discresult = &Apache::lonfeedback::list_discussion($mode,undef,$ressymb,\%extras);
725: }
726: $imsresources .= ' </resource>'."\n";
727: }
728: }
729: $pkgdepth = $depth;
730: }
731: }
732: }
733: while ($pkgdepth > 0) {
734: print $ims_manifest " </item>\n";
735: $pkgdepth --;
736: }
737: my $resource_text = qq|
738: </organization>
739: </organizations>
740: <resources>
741: $imsresources
742: </resources>
743: </manifest>
744: |;
745: print $ims_manifest $resource_text;
746: }
747:
748: sub get_dependencies {
749: my ($exportitems,$parent,$depth,$dependencies) = @_;
750: if ($depth > 1) {
751: if ((!grep(/^$$parent{$depth}$/,@$exportitems)) && (!grep(/^$$parent{$depth}$/,@$dependencies))) {
752: push(@{$dependencies},$$parent{$depth});
753: if ($depth > 2) {
754: &get_dependencies($exportitems,$parent,$depth-1,$dependencies);
755: }
756: }
757: }
758: }
759:
760: sub process_content {
761: my ($count,$curRes,$cdom,$cnum,$symb,$content_file,$href,$copyresult,$tempexport,$format,$currdirpath,$testbank) = @_;
762: my $content_type;
763: my $message;
764: my @uploads = ();
765: if ($curRes->is_sequence()) {
766: $content_type = 'sequence';
767: } elsif ($curRes->is_page()) {
768: $content_type = 'page'; # need to handle individual items in pages.
769: } elsif ($symb =~ m-public/$cdom/$cnum/syllabus$-) {
770: $content_type = 'syllabus';
771: my $contents = &Apache::imsexport::templatedpage($content_type);
772: if ($contents) {
773: $$content_file = &store_template($contents,$tempexport,$count,$content_type);
774: }
775: } elsif ($symb =~ m-\.sequence___\d+___ext-) {
776: $content_type = 'external';
777: my $title = $curRes->title;
778: my $contents = &Apache::imsexport::external($symb,$title);
779: if ($contents) {
780: $$content_file = &store_template($contents,$tempexport,$count,$content_type);
781: }
782: } elsif ($symb =~ m-adm/navmaps$-) {
783: $content_type = 'navmap';
784: } elsif ($symb =~ m-adm/[^/]+/[^/]+/(\d+)/smppg$-) {
785: $content_type = 'simplepage';
786: my $contents = &Apache::imsexport::templatedpage($content_type,$1,$count,\@uploads);
787: if ($contents) {
788: $$content_file = &store_template($contents,$tempexport,$count,$content_type);
789: }
790: } elsif ($symb =~ m-lib/templates/simpleproblem\.problem$-) {
791: $content_type = 'simpleproblem';
792: my $contents = &Apache::imsexport::simpleproblem($symb);
793: if ($contents) {
794: $$content_file = &store_template($contents,$tempexport,$count,$content_type);
795: }
796: } elsif ($symb =~ m-lib/templates/examupload\.problem$-) {
797: $content_type = 'examupload';
798: } elsif ($symb =~ m-adm/($match_domain)/($match_username)/(\d+)/bulletinboard$-) {
799: $content_type = 'bulletinboard';
800: my $contents = &Apache::imsexport::templatedpage($content_type,$3,$count,\@uploads,$1,$2);
801: if ($contents) {
802: $$content_file = &store_template($contents,$tempexport,$count,$content_type);
803: }
804: } elsif ($symb =~ m-adm/([^/]+)/([^/]+)/aboutme$-) {
805: $content_type = 'aboutme';
806: my $contents = &Apache::imsexport::templatedpage($content_type,undef,$count,\@uploads,$1,$2);
807: if ($contents) {
808: $$content_file = &store_template($contents,$tempexport,$count,$content_type);
809: }
810: } elsif ($symb =~ m-\.(sequence|page)___\d+___uploaded/$cdom/$cnum/-) {
811: $$content_file = &replicate_content($cdom,$cnum,$tempexport,$symb,$count,\$message,$href,'uploaded');
812: } elsif ($symb =~ m-\.(sequence|page)___\d+___([^/]+)/([^/]+)-) {
813: my $canedit = 0;
814: if ($2 eq $env{'user.domain'} && $3 eq $env{'user.name'}) {
815: $canedit= 1;
816: }
817: # only include problem code where current user is author
818: if (($format eq 'html') || ($format eq 'plaintext')) {
819: my $title = $curRes->title;
820: $$content_file = &replicate_content($cdom,$cnum,$tempexport,$symb,$count,\$message,$href,$format,$currdirpath,$title,$testbank);
821: } elsif ($format eq 'xml') {
822: if ($canedit) {
823: $$content_file = &replicate_content($cdom,$cnum,$tempexport,$symb,$count,\$message,$href,'resource');
824: } else {
825: $$content_file = &replicate_content($cdom,$cnum,$tempexport,$symb,$count,\$message,$href,'noedit');
826: }
827: }
828: } elsif ($symb =~ m-uploaded/$cdom/$cnum-) {
829: $$content_file = &replicate_content($cdom,$cnum,$tempexport,$symb,$count,\$message,$href,'uploaded');
830: }
831: if (@uploads > 0) {
832: foreach my $item (@uploads) {
833: my $uploadmsg = '';
834: &replicate_content($cdom,$cnum,$tempexport,$item,$count,\$uploadmsg,$href,'templateupload');
835: if ($uploadmsg) {
836: $$copyresult .= $uploadmsg."\n";
837: }
838: }
839: }
840: if ($message) {
841: $$copyresult .= $message."\n";
842: }
843: }
844:
845: sub replicate_content {
846: my ($cdom,$cnum,$tempexport,$symb,$count,$message,$href,$caller,$currdirpath,
847: $title,$testbank) = @_;
848: my ($map,$ind,$url);
849: if ($caller eq 'templateupload') {
850: $url = $symb;
851: $url =~ s#//#/#g;
852: } else {
853: ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);
854: }
855: my $content;
856: my $filename;
857: my $repstatus;
858: my $content_name;
859: if ($url =~ m-/([^/]+)$-) {
860: $filename = $1;
861: if (!-e $tempexport.'/resources') {
862: mkdir($tempexport.'/resources',0700);
863: }
864: if (!-e $tempexport.'/resources/'.$count) {
865: mkdir($tempexport.'/resources/'.$count,0700);
866: }
867: my $destination = $tempexport.'/resources/'.$count.'/'.$filename;
868: my $copiedfile;
869: if ($copiedfile = Apache::File->new('>'.$destination)) {
870: my $content;
871: if ($caller eq 'resource') {
872: my $respath = $Apache::lonnet::perlvar{'lonDocRoot'}.'/res';
873: my $filepath = &Apache::lonnet::filelocation($respath,$url);
874: $content = &Apache::lonnet::getfile($filepath);
875: if ($content eq -1) {
876: $$message = 'Could not copy file '.$filename;
877: } else {
878: &extract_media($url,$cdom,$cnum,\$content,$count,$tempexport,$href,$message,'resource');
879: $repstatus = 'ok';
880: }
881: } elsif ($caller eq 'uploaded' || $caller eq 'templateupload') {
882: my $rtncode;
883: $repstatus = &Apache::lonnet::getuploaded('GET',$url,$cdom,$cnum,\$content,$rtncode);
884: if ($repstatus eq 'ok') {
885: if ($url =~ /\.html?$/i) {
886: &extract_media($url,$cdom,$cnum,\$content,$count,$tempexport,$href,$message,'uploaded');
887: }
888: } else {
889: $$message = 'Could not render '.$url.' server message - '.$rtncode."<br />\n";
890: }
891: } elsif (($caller eq 'noedit') || ($caller eq 'html') ||
892: ($caller eq 'plaintext')) {
893: # Need to render the resource without the LON-CAPA Internal header and the Post discussion footer, and then set $content equal to this.
894: my %form = (
895: grade_symb => $symb,
896: grade_courseid => $cdom.'_'.$cnum,
897: grade_domain => $env{'user.domain'},
898: grade_username => $env{'user.name'},
899: grade_imsexport => 1,
900: );
901: my $feedurl=&Apache::lonnet::clutter($url);
902: my ($userview,$response)=&Apache::lonnet::ssi_body($feedurl,%form);
903: if (ref($response)) {
904: if ($response->is_success) {
905: $content = $userview;
906: $content =~ s/\Qonchange="javascript:setSubmittedPart('\E[^\']+\Q');"\E//g;
907: $content =~ s/^\s*[\n\r]+$//;
908: if ($caller eq 'plaintext') {
909: my @lines = split(/[\n\r]+/,$content);
910: my @tosave;
911: my $foilcounter = 0;
912: my @alphabet = ('a'..'z');
913: my $mc_answer;
914: foreach my $line (@lines) {
915: next if ($line =~ /^\s*$/);
916: if ($line =~ m{(|\Q<\label>\E)\Q<br />Incorrect:<label>\E}) {
917: $foilcounter ++;
918: } elsif ($line =~ m{(|\Q</label>\E)\Q<br />Correct:<b><label>\E}) {
919: $foilcounter ++;
920: $mc_answer = $alphabet[$foilcounter];
921: } elsif ($line !~ m{</label><br />}) {
922: $line =~ s/^(\s+|\s+)$//g;
923: $line =~ s{^\Q<b>\E([^<]+)\Q</b>\E$}{1};
924: push(@tosave,$line);
925: }
926: $content = join("\t",@tosave);
927: if ($mc_answer) {
928: $content .= "\t".$mc_answer."\n";
929: }
930: }
931: if (@tosave) {
932: $content = $currdirpath."\t".$title."\t".join("\t",@tosave);
933: if ($mc_answer) {
934: $content .= "\t".$mc_answer."\n";
935: }
936: }
937: } else {
938: $content = '<html><body>'.$content.'</body></html>';
939: }
940: if (($caller eq 'plaintext') && ($testbank)) {
941: print $testbank $content;
942: }
943: } else {
944: $content = 'Not the owner of this resource';
945: }
946: } else {
947: $content = 'Not the owner of this resource';
948: }
949: $repstatus = 'ok';
950: }
951: if ($repstatus eq 'ok') {
952: print $copiedfile $content;
953: }
954: close($copiedfile);
955: } else {
956: $$message = 'Could not open destination file for '.$filename."<br />\n";
957: }
958: } else {
959: $$message = 'Could not determine name of file for '.$symb."<br />\n";
960: }
961: if ($repstatus eq 'ok') {
962: $content_name = 'resources/'.$count.'/'.$filename;
963: }
964: return $content_name;
965: }
966:
967: sub extract_media {
968: my ($url,$cdom,$cnum,$content,$count,$tempexport,$href,$message,$caller) = @_;
969: my ($dirpath,$container);
970: my %allfiles = ();
971: my %codebase = ();
972: if ($url =~ m-(.*/)([^/]+)$-) {
973: $dirpath = $1;
974: $container = $2;
975: } else {
976: $dirpath = $url;
977: $container = '';
978: }
979: &Apache::lonnet::extract_embedded_items(undef,\%allfiles,\%codebase,$content);
980: foreach my $embed_file (keys(%allfiles)) {
981: my $filename;
982: if ($embed_file =~ m#([^/]+)$#) {
983: $filename = $1;
984: } else {
985: $filename = $embed_file;
986: }
987: my $newname = 'res/'.$filename;
988: my ($rtncode,$embed_content,$repstatus);
989: my $embed_url;
990: if ($embed_file =~ m-^/-) {
991: $embed_url = $embed_file; # points to absolute path
992: } else {
993: if ($embed_file =~ m-https?://-) {
994: next; # points to url
995: } else {
996: $embed_url = $dirpath.$embed_file; # points to relative path
997: }
998: }
999: if ($caller eq 'resource') {
1000: my $respath = $Apache::lonnet::perlvar{'lonDocRoot'}.'/res';
1001: my $embed_path = &Apache::lonnet::filelocation($respath,$embed_url);
1002: $embed_content = &Apache::lonnet::getfile($embed_path);
1003: unless ($embed_content eq -1) {
1004: $repstatus = 'ok';
1005: }
1006: } elsif ($caller eq 'uploaded') {
1007: $repstatus = &Apache::lonnet::getuploaded('GET',$embed_url,$cdom,$cnum,\$embed_content,$rtncode);
1008: }
1009: if ($repstatus eq 'ok') {
1010: my $destination = $tempexport.'/resources/'.$count.'/res';
1011: if (!-e "$destination") {
1012: mkdir($destination,0755);
1013: }
1014: $destination .= '/'.$filename;
1015: my $copiedfile;
1016: if ($copiedfile = Apache::File->new('>'.$destination)) {
1017: print $copiedfile $embed_content;
1018: push(@{$href},'resources/'.$count.'/res/'.$filename);
1019: my $attrib_regexp = '';
1020: if (@{$allfiles{$embed_file}} > 1) {
1021: $attrib_regexp = join('|',@{$allfiles{$embed_file}});
1022: } else {
1023: $attrib_regexp = $allfiles{$embed_file}[0];
1024: }
1025: $$content =~ s#($attrib_regexp\s*=\s*['"]?)\Q$embed_file\E(['"]?)#$1$newname$2#gi;
1026: if ($caller eq 'resource' && $container =~ /\.(problem|library)$/) {
1027: $$content =~ s#\Q$embed_file\E#$newname#gi;
1028: }
1029: }
1030: } else {
1031: $$message .= 'replication of embedded file - '.$embed_file.' in '.$url.' failed, reason -'.$rtncode."<br />\n";
1032: }
1033: }
1034: return;
1035: }
1036:
1037: sub store_template {
1038: my ($contents,$tempexport,$count,$content_type) = @_;
1039: if ($contents) {
1040: if ($tempexport) {
1041: if (!-e $tempexport.'/resources') {
1042: mkdir($tempexport.'/resources',0700);
1043: }
1044: if (!-e $tempexport.'/resources/'.$count) {
1045: mkdir($tempexport.'/resources/'.$count,0700);
1046: }
1047: my $destination = $tempexport.'/resources/'.$count.'/'.$content_type.'.xml';
1048: my $storetemplate;
1049: if ($storetemplate = Apache::File->new('>'.$destination)) {
1050: print $storetemplate $contents;
1051: close($storetemplate);
1052: }
1053: if ($content_type eq 'external') {
1054: return 'resources/'.$count.'/'.$content_type.'.html';
1055: } else {
1056: return 'resources/'.$count.'/'.$content_type.'.xml';
1057: }
1058: }
1059: }
1060: }
1061:
1062:
1063: sub group_import {
1064: my ($coursenum, $coursedom, $folder, $container, $caller, @files) = @_;
1065:
1066: while (@files) {
1067: my ($name, $url, $residx) = @{ shift(@files) };
1068: if (($url =~ m{^/uploaded/\Q$coursedom\E/\Q$coursenum\E/(default_\d+\.)(page|sequence)$})
1069: && ($caller eq 'londocs')
1070: && (!&Apache::lonnet::stat_file($url))) {
1071:
1072: my $errtext = '';
1073: my $fatal = 0;
1074: my $newmapstr = '<map>'."\n".
1075: '<resource id="1" src="" type="start"></resource>'."\n".
1076: '<link from="1" to="2" index="1"></link>'."\n".
1077: '<resource id="2" src="" type="finish"></resource>'."\n".
1078: '</map>';
1079: $env{'form.output'}=$newmapstr;
1080: my $result=&Apache::lonnet::finishuserfileupload($coursenum,$coursedom,
1081: 'output',$1.$2);
1082: if ($result != m|^/uploaded/|) {
1083: $errtext.='Map not saved: A network error occurred when trying to save the new map. ';
1084: $fatal = 2;
1085: }
1086: if ($fatal) {
1087: return ($errtext,$fatal);
1088: }
1089: }
1090: if ($url) {
1091: if (!$residx
1092: || defined($LONCAPA::map::zombies[$residx])) {
1093: $residx = &LONCAPA::map::getresidx($url,$residx);
1094: push(@LONCAPA::map::order, $residx);
1095: }
1096: my $ext = 'false';
1097: if ($url=~m{^http://} || $url=~m{^https://}) { $ext = 'true'; }
1098: $url = &LONCAPA::map::qtunescape($url);
1099: $name = &LONCAPA::map::qtunescape($name);
1100: $LONCAPA::map::resources[$residx] =
1101: join(':', ($name, $url, $ext, 'normal', 'res'));
1102: }
1103: }
1104: return &storemap($coursenum, $coursedom, $folder.'.'.$container);
1105: }
1106:
1107: sub breadcrumbs {
1108: my ($allowed,$crstype)=@_;
1109: &Apache::lonhtmlcommon::clear_breadcrumbs();
1110: my (@folders);
1111: if ($env{'form.pagepath'}) {
1112: @folders = split('&',$env{'form.pagepath'});
1113: } else {
1114: @folders=split('&',$env{'form.folderpath'});
1115: }
1116: my $folderpath;
1117: my $cpinfo='';
1118: my $plain='';
1119: my $randompick=-1;
1120: my $isencrypted=0;
1121: my $ishidden=0;
1122: my $is_random_order=0;
1123: if (!$allowed) {
1124: my $description = $env{'course.'.$env{'request.course.id'}.'.description'};
1125: &Apache::lonhtmlcommon::add_breadcrumb(
1126: {'href' => '/adm/menu',
1127: 'title'=> 'Go to main menu',
1128: 'text' => $description,
1129: });
1130: $plain .= $description.' >';
1131: }
1132: while (@folders) {
1133: my $folder=shift(@folders);
1134: my $foldername=shift(@folders);
1135: if ($folderpath) {$folderpath.='&';}
1136: $folderpath.=$folder.'&'.$foldername;
1137: my $url='/adm/coursedocs?folderpath='.
1138: &escape($folderpath);
1139: my $name=&unescape($foldername);
1140: # randompick number, hidden, encrypted, random order, is appended with ":"s to the foldername
1141: $name=~s/\:(\d*)\:(\w*)\:(\w*):(\d*)$//;
1142: if ($1 ne '') {
1143: $randompick=$1;
1144: } else {
1145: $randompick=-1;
1146: }
1147: if ($2) { $ishidden=1; }
1148: if ($3) { $isencrypted=1; }
1149: if ($4 ne '') { $is_random_order = 1; }
1150: if ($folder eq 'supplemental') {
1151: $name = &mt('Supplemental '.$crstype.' Documents');
1152: }
1153: &Apache::lonhtmlcommon::add_breadcrumb(
1154: {'href'=>$url.$cpinfo,
1155: 'title'=>$name,
1156: 'text'=>$name,
1157: 'no_mt'=>1,
1158: });
1159: $plain.=$name.' > ';
1160: }
1161: $plain=~s/\>\;\s*$//;
1162: return (&Apache::lonhtmlcommon::breadcrumbs(undef,undef,0,'nohelp',
1163: undef, undef, 1 ),$randompick,$ishidden,$isencrypted,$plain,$is_random_order);
1164: }
1165:
1166: sub log_docs {
1167: return &Apache::lonnet::instructor_log('docslog',@_);
1168: }
1169:
1170: {
1171: my @oldresources=();
1172: my @oldorder=();
1173: my $parmidx;
1174: my %parmaction=();
1175: my %parmvalue=();
1176: my $changedflag;
1177:
1178: sub snapshotbefore {
1179: @oldresources=@LONCAPA::map::resources;
1180: @oldorder=@LONCAPA::map::order;
1181: $parmidx=undef;
1182: %parmaction=();
1183: %parmvalue=();
1184: $changedflag=0;
1185: }
1186:
1187: sub remember_parms {
1188: my ($idx,$parameter,$action,$value)=@_;
1189: $parmidx=$idx;
1190: $parmaction{$parameter}=$action;
1191: $parmvalue{$parameter}=$value;
1192: $changedflag=1;
1193: }
1194:
1195: sub log_differences {
1196: my ($plain)=@_;
1197: my %storehash=('folder' => $plain,
1198: 'currentfolder' => $env{'form.folder'});
1199: if ($parmidx) {
1200: $storehash{'parameter_res'}=$oldresources[$parmidx];
1201: foreach my $parm (keys(%parmaction)) {
1202: $storehash{'parameter_action_'.$parm}=$parmaction{$parm};
1203: $storehash{'parameter_value_'.$parm}=$parmvalue{$parm};
1204: }
1205: }
1206: my $maxidx=$#oldresources;
1207: if ($#LONCAPA::map::resources>$#oldresources) {
1208: $maxidx=$#LONCAPA::map::resources;
1209: }
1210: for (my $idx=0; $idx<=$maxidx; $idx++) {
1211: if ($LONCAPA::map::resources[$idx] ne $oldresources[$idx]) {
1212: $storehash{'before_resources_'.$idx}=$oldresources[$idx];
1213: $storehash{'after_resources_'.$idx}=$LONCAPA::map::resources[$idx];
1214: $changedflag=1;
1215: }
1216: if ($LONCAPA::map::order[$idx] ne $oldorder[$idx]) {
1217: $storehash{'before_order_res_'.$idx}=$oldresources[$oldorder[$idx]];
1218: $storehash{'after_order_res_'.$idx}=$LONCAPA::map::resources[$LONCAPA::map::order[$idx]];
1219: $changedflag=1;
1220: }
1221: }
1222: $storehash{'maxidx'}=$maxidx;
1223: if ($changedflag) { &log_docs(\%storehash); }
1224: }
1225: }
1226:
1227:
1228:
1229:
1230:
1231: sub docs_change_log {
1232: my ($r)=@_;
1233: my $folder=$env{'form.folder'};
1234: $r->print(&Apache::loncommon::start_page('Course Document Change Log'));
1235: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Course Document Change Log'));
1236: my %docslog=&Apache::lonnet::dump('nohist_docslog',
1237: $env{'course.'.$env{'request.course.id'}.'.domain'},
1238: $env{'course.'.$env{'request.course.id'}.'.num'});
1239:
1240: if ((keys(%docslog))[0]=~/^error\:/) { undef(%docslog); }
1241:
1242: $r->print('<form action="/adm/coursedocs" method="post" name="docslog">'.
1243: '<input type="hidden" name="docslog" value="1" />');
1244:
1245: my %saveable_parameters = ('show' => 'scalar',);
1246: &Apache::loncommon::store_course_settings('docs_log',
1247: \%saveable_parameters);
1248: &Apache::loncommon::restore_course_settings('docs_log',
1249: \%saveable_parameters);
1250: if (!$env{'form.show'}) { $env{'form.show'}=10; }
1251: # FIXME: internationalization seems wrong here
1252: my %lt=('hiddenresource' => 'Resources hidden',
1253: 'encrypturl' => 'URL hidden',
1254: 'randompick' => 'Randomly pick',
1255: 'randomorder' => 'Randomly ordered',
1256: 'set' => 'set to',
1257: 'del' => 'deleted');
1258: $r->print(&Apache::loncommon::display_filter().
1259: '<input type="hidden" name="folder" value="'.$folder.'" />'.
1260: '<input type="submit" value="'.&mt('Display').'" /></form>');
1261: $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
1262: '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Folder').'</th><th>'.&mt('Before').'</th><th>'.
1263: &mt('After').'</th>'.
1264: &Apache::loncommon::end_data_table_header_row());
1265: my $shown=0;
1266: foreach my $id (sort { $docslog{$b}{'exe_time'}<=>$docslog{$a}{'exe_time'} } (keys(%docslog))) {
1267: if ($env{'form.displayfilter'} eq 'currentfolder') {
1268: if ($docslog{$id}{'logentry'}{'currentfolder'} ne $folder) { next; }
1269: }
1270: my @changes=keys(%{$docslog{$id}{'logentry'}});
1271: if ($env{'form.displayfilter'} eq 'containing') {
1272: my $wholeentry=$docslog{$id}{'exe_uname'}.':'.$docslog{$id}{'exe_udom'}.':'.
1273: &Apache::loncommon::plainname($docslog{$id}{'exe_uname'},$docslog{$id}{'exe_udom'});
1274: foreach my $key (@changes) {
1275: $wholeentry.=':'.$docslog{$id}{'logentry'}{$key};
1276: }
1277: if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
1278: }
1279: my $count = 0;
1280: my $time =
1281: &Apache::lonlocal::locallocaltime($docslog{$id}{'exe_time'});
1282: my $plainname =
1283: &Apache::loncommon::plainname($docslog{$id}{'exe_uname'},
1284: $docslog{$id}{'exe_udom'});
1285: my $about_me_link =
1286: &Apache::loncommon::aboutmewrapper($plainname,
1287: $docslog{$id}{'exe_uname'},
1288: $docslog{$id}{'exe_udom'});
1289: my $send_msg_link='';
1290: if ((($docslog{$id}{'exe_uname'} ne $env{'user.name'})
1291: || ($docslog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
1292: $send_msg_link ='<br />'.
1293: &Apache::loncommon::messagewrapper(&mt('Send message'),
1294: $docslog{$id}{'exe_uname'},
1295: $docslog{$id}{'exe_udom'});
1296: }
1297: $r->print(&Apache::loncommon::start_data_table_row());
1298: $r->print('<td>'.$time.'</td>
1299: <td>'.$about_me_link.
1300: '<br /><tt>'.$docslog{$id}{'exe_uname'}.
1301: ':'.$docslog{$id}{'exe_udom'}.'</tt>'.
1302: $send_msg_link.'</td><td>'.
1303: $docslog{$id}{'logentry'}{'folder'}.'</td><td>');
1304: # Before
1305: for (my $idx=0;$idx<=$docslog{$id}{'logentry'}{'maxidx'};$idx++) {
1306: my $oldname=(split(/\:/,$docslog{$id}{'logentry'}{'before_resources_'.$idx}))[0];
1307: my $newname=(split(/\:/,$docslog{$id}{'logentry'}{'after_resources_'.$idx}))[0];
1308: if ($oldname ne $newname) {
1309: $r->print(&LONCAPA::map::qtescape($oldname));
1310: }
1311: }
1312: $r->print('<ul>');
1313: for (my $idx=0;$idx<=$docslog{$id}{'logentry'}{'maxidx'};$idx++) {
1314: if ($docslog{$id}{'logentry'}{'before_order_res_'.$idx}) {
1315: $r->print('<li>'.&LONCAPA::map::qtescape((split(/\:/,$docslog{$id}{'logentry'}{'before_order_res_'.$idx}))[0]).'</li>');
1316: }
1317: }
1318: $r->print('</ul>');
1319: # After
1320: $r->print('</td><td>');
1321:
1322: for (my $idx=0;$idx<=$docslog{$id}{'logentry'}{'maxidx'};$idx++) {
1323: my $oldname=(split(/\:/,$docslog{$id}{'logentry'}{'before_resources_'.$idx}))[0];
1324: my $newname=(split(/\:/,$docslog{$id}{'logentry'}{'after_resources_'.$idx}))[0];
1325: if ($oldname ne '' && $oldname ne $newname) {
1326: $r->print(&LONCAPA::map::qtescape($newname));
1327: }
1328: }
1329: $r->print('<ul>');
1330: for (my $idx=0;$idx<=$docslog{$id}{'logentry'}{'maxidx'};$idx++) {
1331: if ($docslog{$id}{'logentry'}{'after_order_res_'.$idx}) {
1332: $r->print('<li>'.&LONCAPA::map::qtescape((split(/\:/,$docslog{$id}{'logentry'}{'after_order_res_'.$idx}))[0]).'</li>');
1333: }
1334: }
1335: $r->print('</ul>');
1336: if ($docslog{$id}{'logentry'}{'parameter_res'}) {
1337: $r->print(&LONCAPA::map::qtescape((split(/\:/,$docslog{$id}{'logentry'}{'parameter_res'}))[0]).':<ul>');
1338: foreach my $parameter ('randompick','hiddenresource','encrypturl','randomorder') {
1339: if ($docslog{$id}{'logentry'}{'parameter_action_'.$parameter}) {
1340: # FIXME: internationalization seems wrong here
1341: $r->print('<li>'.
1342: &mt($lt{$parameter}.' '.$lt{$docslog{$id}{'logentry'}{'parameter_action_'.$parameter}}.' [_1]',
1343: $docslog{$id}{'logentry'}{'parameter_value_'.$parameter})
1344: .'</li>');
1345: }
1346: }
1347: $r->print('</ul>');
1348: }
1349: # End
1350: $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1351: $shown++;
1352: if (!($env{'form.show'} eq &mt('all')
1353: || $shown<=$env{'form.show'})) { last; }
1354: }
1355: $r->print(&Apache::loncommon::end_data_table());
1356: }
1357:
1358: sub update_paste_buffer {
1359: my ($coursenum,$coursedom) = @_;
1360:
1361: return if (!defined($env{'form.markcopy'}));
1362: return if (!defined($env{'form.copyfolder'}));
1363: return if ($env{'form.markcopy'} < 0);
1364:
1365: my ($errtext,$fatal) = &mapread($coursenum,$coursedom,
1366: $env{'form.copyfolder'});
1367:
1368: return if ($fatal);
1369:
1370: # Mark for copying
1371: my ($title,$url)=split(':',$LONCAPA::map::resources[$LONCAPA::map::order[$env{'form.markcopy'}]]);
1372: if (&is_supplemental_title($title)) {
1373: &Apache::lonnet::appenv({'docs.markedcopy_supplemental' => $title});
1374: ($title) = &parse_supplemental_title($title);
1375: } elsif ($env{'docs.markedcopy_supplemental'}) {
1376: &Apache::lonnet::delenv('docs.markedcopy_supplemental');
1377: }
1378: $url=~s{http(:|:)//https(:|:)//}{https$2//};
1379:
1380: &Apache::lonnet::appenv({'docs.markedcopy_title' => $title,
1381: 'docs.markedcopy_url' => $url});
1382: delete($env{'form.markcopy'});
1383: }
1384:
1385: sub print_paste_buffer {
1386: my ($r,$container) = @_;
1387: return if (!defined($env{'docs.markedcopy_url'}));
1388:
1389: $r->print('<fieldset>'
1390: .'<legend>'.&mt('Clipboard').'</legend>'
1391: .'<form name="pasteform" action="/adm/coursedocs" method="post">'
1392: .'<input type="submit" name="pastemarked" value="'.&mt('Paste').'" /> '
1393: );
1394:
1395: my $type;
1396: if ($env{'docs.markedcopy_url'} =~ m{^(?:/adm/wrapper/ext|(?:http|https)(?::|:))//} ) {
1397: $type = &mt('External Resource');
1398: $r->print($type.': '.
1399: &LONCAPA::map::qtescape($env{'docs.markedcopy_title'}).' ('.
1400: &LONCAPA::map::qtescape($env{'docs.markedcopy_url'}).')');
1401: } else {
1402: my $extension = (split(/\./,$env{'docs.markedcopy_url'}))[-1];
1403: my $icon = &Apache::loncommon::icon($extension);
1404: if ($extension eq 'sequence' &&
1405: $env{'docs.markedcopy_url'} =~ m{/default_\d+\.sequence$ }x) {
1406: $icon = &Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL'));
1407: $icon .= '/navmap.folder.closed.gif';
1408: }
1409: $icon = '<img src="'.$icon.'" alt="" class="LC_icon" />';
1410: $r->print($icon.$type.': '. &parse_supplemental_title(&LONCAPA::map::qtescape($env{'docs.markedcopy_title'})));
1411: }
1412: if ($container eq 'page') {
1413: $r->print('
1414: <input type="hidden" name="pagepath" value="'.&HTML::Entities::encode($env{'form.pagepath'},'<>&"').'" />
1415: <input type="hidden" name="pagesymb" value="'.&HTML::Entities::encode($env{'form.pagesymb'},'<>&"').'" />
1416: ');
1417: } else {
1418: $r->print('
1419: <input type="hidden" name="folderpath" value="'.&HTML::Entities::encode($env{'form.folderpath'},'<>&"').'" />
1420: ');
1421: }
1422: $r->print('</form></fieldset>');
1423: }
1424:
1425: sub do_paste_from_buffer {
1426: my ($coursenum,$coursedom,$folder) = @_;
1427:
1428: if (!$env{'form.pastemarked'}) {
1429: return;
1430: }
1431:
1432: # paste resource to end of list
1433: my $url=&LONCAPA::map::qtescape($env{'docs.markedcopy_url'});
1434: my $title=&LONCAPA::map::qtescape($env{'docs.markedcopy_title'});
1435: # Maps need to be copied first
1436: if (($url=~/\.(page|sequence)$/) && ($url=~/^\/uploaded\//)) {
1437: $title=&mt('Copy of').' '.$title;
1438: my $newid=$$.int(rand(100)).time;
1439: my ($oldid,$ext) = ($url=~/^(.+)\.(\w+)$/);
1440: if ($oldid =~ m{^(/uploaded/\Q$coursedom\E/\Q$coursenum\E/)(\D+)(\d+)$}) {
1441: my $path = $1;
1442: my $prefix = $2;
1443: my $ancestor = $3;
1444: if (length($ancestor) > 10) {
1445: $ancestor = substr($ancestor,-10,10);
1446: }
1447: $oldid = $path.$prefix.$ancestor;
1448: }
1449: my $counter = 0;
1450: my $newurl=$oldid.$newid.'.'.$ext;
1451: my $is_unique = &uniqueness_check($newurl);
1452: while (!$is_unique && $counter < 100) {
1453: $counter ++;
1454: $newid ++;
1455: $newurl = $oldid.$newid;
1456: $is_unique = &uniqueness_check($newurl);
1457: }
1458: if (!$is_unique) {
1459: if ($url=~/\.page$/) {
1460: return &mt('Paste failed: an error occurred creating a unique URL for the composite page');
1461: } else {
1462: return &mt('Paste failed: an error occurred creating a unique URL for the folder');
1463: }
1464: }
1465: my $storefn=$newurl;
1466: $storefn=~s{^/\w+/$match_domain/$match_username/}{};
1467: my $paste_map_result =
1468: &Apache::lonclonecourse::writefile($env{'request.course.id'},$storefn,
1469: &Apache::lonnet::getfile($url));
1470: if ($paste_map_result eq '/adm/notfound.html') {
1471: if ($url=~/\.page$/) {
1472: return &mt('Paste failed: an error occurred saving the composite page');
1473: } else {
1474: return &mt('Paste failed: an error occurred saving the folder');
1475: }
1476: }
1477: $url = $newurl;
1478: }
1479: # published maps can only exists once, so remove it from paste buffer when done
1480: if (($url=~/\.(page|sequence)$/) && ($url=~m {^/res/})) {
1481: &Apache::lonnet::delenv('docs.markedcopy');
1482: }
1483: if ($url=~ m{/smppg$}) {
1484: my $db_name = &Apache::lonsimplepage::get_db_name($url);
1485: if ($db_name =~ /^smppage_/) {
1486: #simple pages, need to copy the db contents to a new one.
1487: my %contents=&Apache::lonnet::dump($db_name,$coursedom,$coursenum);
1488: my $now = time();
1489: $db_name =~ s{_\d*$ }{_$now}x;
1490: my $result=&Apache::lonnet::put($db_name,\%contents,
1491: $coursedom,$coursenum);
1492: $url =~ s{/(\d*)/smppg$ }{/$now/smppg}x;
1493: $title=&mt('Copy of').' '.$title;
1494: }
1495: }
1496: $title = &LONCAPA::map::qtunescape($title);
1497: my $ext='false';
1498: if ($url=~m{^http(|s)://}) { $ext='true'; }
1499: $url = &LONCAPA::map::qtunescape($url);
1500: # Now insert the URL at the bottom
1501: my $newidx = &LONCAPA::map::getresidx($url);
1502: if ($env{'docs.markedcopy_supplemental'}) {
1503: if ($folder =~ /^supplemental/) {
1504: $title = $env{'docs.markedcopy_supplemental'};
1505: } else {
1506: (undef,undef,$title) =
1507: &parse_supplemental_title($env{'docs.markedcopy_supplemental'});
1508: }
1509: } else {
1510: if ($folder=~/^supplemental/) {
1511: $title=time.'___&&&___'.$env{'user.name'}.'___&&&___'.
1512: $env{'user.domain'}.'___&&&___'.$title;
1513: }
1514: }
1515:
1516: $LONCAPA::map::resources[$newidx]= $title.':'.$url.':'.$ext.':normal:res';
1517: push(@LONCAPA::map::order, $newidx);
1518: return 'ok';
1519: # Store the result
1520: }
1521:
1522: sub uniqueness_check {
1523: my ($newurl) = @_;
1524: my $unique = 1;
1525: foreach my $res (@LONCAPA::map::order) {
1526: my ($name,$url)=split(/\:/,$LONCAPA::map::resources[$res]);
1527: $url=&LONCAPA::map::qtescape($url);
1528: if ($newurl eq $url) {
1529: $unique = 0;
1530: last;
1531: }
1532: }
1533: return $unique;
1534: }
1535:
1536: my %parameter_type = ( 'randompick' => 'int_pos',
1537: 'hiddenresource' => 'string_yesno',
1538: 'encrypturl' => 'string_yesno',
1539: 'randomorder' => 'string_yesno',);
1540: my $valid_parameters_re = join('|',keys(%parameter_type));
1541: # set parameters
1542: sub update_parameter {
1543:
1544: return 0 if ($env{'form.changeparms'} !~ /^($valid_parameters_re)$/);
1545:
1546: my $which = $env{'form.changeparms'};
1547: my $idx = $env{'form.setparms'};
1548: if ($env{'form.'.$which.'_'.$idx}) {
1549: my $value = ($which eq 'randompick') ? $env{'form.'.$which.'_'.$idx}
1550: : 'yes';
1551: &LONCAPA::map::storeparameter($idx, 'parameter_'.$which, $value,
1552: $parameter_type{$which});
1553: &remember_parms($idx,$which,'set',$value);
1554: } else {
1555: &LONCAPA::map::delparameter($idx,'parameter_'.$which);
1556:
1557: &remember_parms($idx,$which,'del');
1558: }
1559: return 1;
1560: }
1561:
1562:
1563: sub handle_edit_cmd {
1564: my ($coursenum,$coursedom) =@_;
1565:
1566: my ($cmd,$idx)=split('_',$env{'form.cmd'});
1567:
1568: my $ratstr = $LONCAPA::map::resources[$LONCAPA::map::order[$idx]];
1569: my ($title, $url, @rrest) = split(':', $ratstr);
1570:
1571: if ($cmd eq 'del') {
1572: if (($url=~m|/+uploaded/\Q$coursedom\E/\Q$coursenum\E/|) &&
1573: ($url!~/\.(page|sequence|problem|exam|quiz|assess|survey|form|library|task)$/)) {
1574: &Apache::lonnet::removeuploadedurl($url);
1575: } else {
1576: &LONCAPA::map::makezombie($LONCAPA::map::order[$idx]);
1577: }
1578: splice(@LONCAPA::map::order, $idx, 1);
1579:
1580: } elsif ($cmd eq 'cut') {
1581: &LONCAPA::map::makezombie($LONCAPA::map::order[$idx]);
1582: splice(@LONCAPA::map::order, $idx, 1);
1583:
1584: } elsif ($cmd eq 'up'
1585: && ($idx) && (defined($LONCAPA::map::order[$idx-1]))) {
1586: @LONCAPA::map::order[$idx-1,$idx] = @LONCAPA::map::order[$idx,$idx-1];
1587:
1588: } elsif ($cmd eq 'down'
1589: && defined($LONCAPA::map::order[$idx+1])) {
1590: @LONCAPA::map::order[$idx+1,$idx] = @LONCAPA::map::order[$idx,$idx+1];
1591:
1592: } elsif ($cmd eq 'rename') {
1593:
1594: my $comment = &LONCAPA::map::qtunescape($env{'form.title'});
1595: if ($comment=~/\S/) {
1596: $LONCAPA::map::resources[$LONCAPA::map::order[$idx]]=
1597: $comment.':'.join(':', $url, @rrest);
1598: }
1599: # Devalidate title cache
1600: my $renamed_url=&LONCAPA::map::qtescape($url);
1601: &Apache::lonnet::devalidate_title_cache($renamed_url);
1602: } else {
1603: return 0;
1604: }
1605: return 1;
1606: }
1607:
1608: sub editor {
1609: my ($r,$coursenum,$coursedom,$folder,$allowed,$upload_output,$crstype)=@_;
1610: my $container= ($env{'form.pagepath'}) ? 'page'
1611: : 'sequence';
1612:
1613: my ($errtext,$fatal) = &mapread($coursenum,$coursedom,
1614: $folder.'.'.$container);
1615: return $errtext if ($fatal);
1616:
1617: if ($#LONCAPA::map::order<1) {
1618: my $idx=&LONCAPA::map::getresidx();
1619: if ($idx<=0) { $idx=1; }
1620: $LONCAPA::map::order[0]=$idx;
1621: $LONCAPA::map::resources[$idx]='';
1622: }
1623:
1624: my ($breadcrumbtrail,$randompick,$ishidden,$isencrypted,$plain,$is_random_order) =
1625: &breadcrumbs($allowed,$crstype);
1626: $r->print($breadcrumbtrail);
1627:
1628: unless ($allowed) {
1629: $randompick = -1;
1630: }
1631:
1632: # ------------------------------------------------------------ Process commands
1633:
1634: # ---------------- if they are for this folder and user allowed to make changes
1635: if (($allowed) && ($env{'form.folder'} eq $folder)) {
1636: # set parameters and change order
1637: &snapshotbefore();
1638:
1639: if (&update_parameter()) {
1640: ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container);
1641: return $errtext if ($fatal);
1642: }
1643:
1644: if ($env{'form.newpos'} && $env{'form.currentpos'}) {
1645: # change order
1646: my $res = splice(@LONCAPA::map::order,$env{'form.currentpos'}-1,1);
1647: splice(@LONCAPA::map::order,$env{'form.newpos'}-1,0,$res);
1648:
1649: ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container);
1650: return $errtext if ($fatal);
1651: }
1652:
1653: if ($env{'form.pastemarked'}) {
1654: my $paste_res =
1655: &do_paste_from_buffer($coursenum,$coursedom,$folder);
1656: if ($paste_res eq 'ok') {
1657: ($errtext,$fatal) = &storemap($coursenum,$coursedom,$folder.'.'.$container);
1658: return $errtext if ($fatal);
1659: } elsif ($paste_res ne '') {
1660: $r->print('<p><span class="LC_error">'.$paste_res.'</span></p>');
1661: }
1662: }
1663:
1664: $r->print($upload_output);
1665:
1666: if (&handle_edit_cmd()) {
1667: ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container);
1668: return $errtext if ($fatal);
1669: }
1670: # Group import/search
1671: if ($env{'form.importdetail'}) {
1672: my @imports;
1673: foreach my $item (split(/\&/,$env{'form.importdetail'})) {
1674: if (defined($item)) {
1675: my ($name,$url,$residx)=
1676: map {&unescape($_)} split(/\=/,$item);
1677: push(@imports, [$name, $url, $residx]);
1678: }
1679: }
1680: ($errtext,$fatal)=&group_import($coursenum, $coursedom, $folder,
1681: $container,'londocs',@imports);
1682: return $errtext if ($fatal);
1683: }
1684: # Loading a complete map
1685: if ($env{'form.loadmap'}) {
1686: if ($env{'form.importmap'}=~/\w/) {
1687: foreach my $res (&Apache::lonsequence::attemptread(&Apache::lonnet::filelocation('',$env{'form.importmap'}))) {
1688: my ($title,$url,$ext,$type)=split(/\:/,$res);
1689: my $idx=&LONCAPA::map::getresidx($url);
1690: $LONCAPA::map::resources[$idx]=$res;
1691: $LONCAPA::map::order[$#LONCAPA::map::order+1]=$idx;
1692: }
1693: ($errtext,$fatal)=&storemap($coursenum,$coursedom,
1694: $folder.'.'.$container);
1695: return $errtext if ($fatal);
1696: } else {
1697: $r->print('<p><span class="LC_error">'.&mt('No map selected.').'</span></p>');
1698:
1699: }
1700: }
1701: &log_differences($plain);
1702: }
1703: # ---------------------------------------------------------------- End commands
1704: # ---------------------------------------------------------------- Print screen
1705: my $idx=0;
1706: my $shown=0;
1707: if (($ishidden) || ($isencrypted) || ($randompick>=0) || ($is_random_order)) {
1708: $r->print('<div class="LC_Box">'.
1709: '<ol class="LC_docs_parameters"><li class="LC_docs_parameters_title">'.&mt('Parameters:').'</li>'.
1710: ($randompick>=0?'<li>'.&mt('randomly pick [quant,_1,resource]',$randompick).'</li>':'').
1711: ($ishidden?'<li>'.&mt('contents hidden').'</li>':'').
1712: ($isencrypted?'<li>'.&mt('URLs hidden').'</li>':'').
1713: ($is_random_order?'<li>'.&mt('random order').'</li>':'').
1714: '</ol>');
1715: if ($randompick>=0) {
1716: $r->print('<p class="LC_warning">'
1717: .&mt('Caution: this folder is set to randomly pick a subset'
1718: .' of resources. Adding or removing resources from this'
1719: .' folder will change the set of resources that the'
1720: .' students see, resulting in spurious or missing credit'
1721: .' for completed problems, not limited to ones you'
1722: .' modify. Do not modify the contents of this folder if'
1723: .' it is in active student use.')
1724: .'</p>'
1725: );
1726: }
1727: if ($is_random_order) {
1728: $r->print('<p class="LC_warning">'
1729: .&mt('Caution: this folder is set to randomly order its'
1730: .' contents. Adding or removing resources from this folder'
1731: .' will change the order of resources shown.')
1732: .'</p>'
1733: );
1734: }
1735: $r->print('</div>');
1736: }
1737:
1738: my $output;
1739:
1740: &Apache::loncommon::start_data_table_count(); #setup a row counter
1741: foreach my $res (@LONCAPA::map::order) {
1742: my ($name,$url)=split(/\:/,$LONCAPA::map::resources[$res]);
1743: $name=&LONCAPA::map::qtescape($name);
1744: $url=&LONCAPA::map::qtescape($url);
1745: unless ($name) { $name=(split(/\//,$url))[-1]; }
1746: unless ($name) { $idx++; next; }
1747: $output .= &entryline($idx,$name,$url,$folder,$allowed,$res,
1748: $coursenum,$crstype);
1749: $idx++;
1750: $shown++;
1751: }
1752: &Apache::loncommon::end_data_table_count();
1753:
1754: if ($shown) {
1755: $r->print(&Apache::loncommon::start_scrollbox('900px','880px','400px')
1756: .&Apache::loncommon::start_data_table());
1757: if ($allowed) {
1758: $r->print(&Apache::loncommon::start_data_table_header_row()
1759: .'<th colspan="2">'.&mt('Move').'</th>'
1760: .'<th>'.&mt('Actions').'</th>'
1761: .'<th colspan="2">'.&mt('Document').'</th>');
1762: if ($folder !~ /^supplemental/) {
1763: $r->print('<th colspan="4">'.&mt('Settings').'</th>');
1764: }
1765: $r->print(&Apache::loncommon::end_data_table_header_row());
1766: }
1767: $r->print($output
1768: .&Apache::loncommon::end_data_table()
1769: .&Apache::loncommon::end_scrollbox()
1770: );
1771: } else {
1772: $r->print('<p class="LC_info">'
1773: .&mt('Currently no documents.')
1774: .'</p>'
1775: );
1776: }
1777: if ($allowed) {
1778: &print_paste_buffer($r,$container);
1779: }
1780: return;
1781: }
1782:
1783: sub process_file_upload {
1784: my ($upload_output,$coursenum,$coursedom,$allfiles,$codebase,$uploadcmd) = @_;
1785: # upload a file, if present
1786: my ($parseaction,$showupload,$nextphase,$mimetype);
1787: if ($env{'form.parserflag'}) {
1788: $parseaction = 'parse';
1789: }
1790: my $folder=$env{'form.folder'};
1791: if ($folder eq '') {
1792: $folder='default';
1793: }
1794: if ( ($folder=~/^$uploadcmd/) || ($uploadcmd eq 'default') ) {
1795: my $errtext='';
1796: my $fatal=0;
1797: my $container='sequence';
1798: if ($env{'form.pagepath'}) {
1799: $container='page';
1800: }
1801: ($errtext,$fatal)=
1802: &mapread($coursenum,$coursedom,$folder.'.'.$container);
1803: if ($#LONCAPA::map::order<1) {
1804: $LONCAPA::map::order[0]=1;
1805: $LONCAPA::map::resources[1]='';
1806: }
1807: if ($fatal) {
1808: $$upload_output = '<p><span class="LC_error">'.&mt('The uploaded file has not been stored as an error occurred reading the contents of the current folder.').'</span></p>';
1809: return;
1810: }
1811: my $destination = 'docs/';
1812: if ($folder =~ /^supplemental/) {
1813: $destination = 'supplemental/';
1814: }
1815: if (($folder eq 'default') || ($folder eq 'supplemental')) {
1816: $destination .= 'default/';
1817: } elsif ($folder =~ /^(default|supplemental)_(\d+)$/) {
1818: $destination .= $2.'/';
1819: }
1820: # this is for a course, not a user, so set context to coursedoc.
1821: my $newidx=&LONCAPA::map::getresidx();
1822: $destination .= $newidx;
1823: my $url=&Apache::lonnet::userfileupload('uploaddoc','coursedoc',$destination,
1824: $parseaction,$allfiles,
1825: $codebase,undef,undef,undef,undef,
1826: undef,undef,\$mimetype);
1827: if ($url =~ m{^/uploaded/\Q$coursedom\E/\Q$coursenum\E.*/([^/]+)$}) {
1828: my $stored = $1;
1829: $showupload = '<p>'.&mt('Uploaded [_1]','<span class="LC_filename">'.
1830: $stored.'</span>').'</p>';
1831: } else {
1832: my ($filename) = ($env{'form.uploaddoc.filename'} =~ m{([^/]+)$});
1833:
1834: $$upload_output = '<p><span class="LC_error">'.&mt('Unable to save file [_1].','<span class="LC_filename">'.$filename.'</span>').'</span></p>';
1835: return;
1836: }
1837: my $ext='false';
1838: if ($url=~m{^http://}) { $ext='true'; }
1839: $url = &LONCAPA::map::qtunescape($url);
1840: my $comment=$env{'form.comment'};
1841: $comment = &LONCAPA::map::qtunescape($comment);
1842: if ($folder=~/^supplemental/) {
1843: $comment=time.'___&&&___'.$env{'user.name'}.'___&&&___'.
1844: $env{'user.domain'}.'___&&&___'.$comment;
1845: }
1846:
1847: $LONCAPA::map::resources[$newidx]=
1848: $comment.':'.$url.':'.$ext.':normal:res';
1849: $LONCAPA::map::order[$#LONCAPA::map::order+1]= $newidx;
1850: ($errtext,$fatal)=&storemap($coursenum,$coursedom,
1851: $folder.'.'.$container);
1852: if ($fatal) {
1853: $$upload_output = '<p><span class="LC_error">'.$errtext.'</span></p>';
1854: return;
1855: } else {
1856: if ($parseaction eq 'parse' && $mimetype eq 'text/html') {
1857: $$upload_output = $showupload;
1858: my $total_embedded = scalar(keys(%{$allfiles}));
1859: if ($total_embedded > 0) {
1860: my $uploadphase = 'upload_embedded';
1861: my $primaryurl = &HTML::Entities::encode($url,'<>&"');
1862: my $state = &embedded_form_elems($uploadphase,$primaryurl,$newidx);
1863: my ($embedded,$num) =
1864: &Apache::loncommon::ask_for_embedded_content(
1865: '/adm/coursedocs',$state,$allfiles,$codebase,{'docs_url' => $url});
1866: if ($embedded) {
1867: if ($num) {
1868: $$upload_output .=
1869: '<p>'.&mt('This file contains embedded multimedia objects, which need to be uploaded.').'</p>'.$embedded;
1870: $nextphase = $uploadphase;
1871: } else {
1872: $$upload_output .= $embedded;
1873: }
1874: } else {
1875: $$upload_output .= &mt('Embedded item(s) already present, so no additional upload(s) required').'<br />';
1876: }
1877: } else {
1878: $$upload_output .= &mt('No embedded items identified').'<br />';
1879: }
1880: }
1881: }
1882: }
1883: return $nextphase;
1884: }
1885:
1886: sub is_supplemental_title {
1887: my ($title) = @_;
1888: return scalar($title =~ m/^(\d+)___&&&___($match_username)___&&&___($match_domain)___&&&___(.*)$/);
1889: }
1890:
1891: sub parse_supplemental_title {
1892: my ($title) = @_;
1893:
1894: my ($foldertitle,$renametitle);
1895: if ($title =~ /&&&/) {
1896: $title = &HTML::Entites::decode($title);
1897: }
1898: if ($title =~ m/^(\d+)___&&&___($match_username)___&&&___($match_domain)___&&&___(.*)$/) {
1899: $renametitle=$4;
1900: my ($time,$uname,$udom) = ($1,$2,$3);
1901: $foldertitle=&Apache::lontexconvert::msgtexconverted($4);
1902: my $name = &Apache::loncommon::plainname($uname,$udom);
1903: $name = &HTML::Entities::encode($name,'"<>&\'');
1904: $renametitle = &HTML::Entities::encode($renametitle,'"<>&\'');
1905: $title='<i>'.&Apache::lonlocal::locallocaltime($time).'</i> '.
1906: $name.': <br />'.$foldertitle;
1907: }
1908: if (wantarray) {
1909: return ($title,$foldertitle,$renametitle);
1910: }
1911: return $title;
1912: }
1913:
1914: # --------------------------------------------------------------- An entry line
1915:
1916: sub entryline {
1917: my ($index,$title,$url,$folder,$allowed,$residx,$coursenum,$crstype)=@_;
1918: my ($foldertitle,$pagetitle,$renametitle);
1919: if (&is_supplemental_title($title)) {
1920: ($title,$foldertitle,$renametitle) = &parse_supplemental_title($title);
1921: $pagetitle = $foldertitle;
1922: } else {
1923: $title=&HTML::Entities::encode($title,'"<>&\'');
1924: $renametitle=$title;
1925: $foldertitle=$title;
1926: $pagetitle=$title;
1927: }
1928:
1929: my $orderidx=$LONCAPA::map::order[$index];
1930:
1931:
1932: $renametitle=~s/\\/\\\\/g;
1933: $renametitle=~s/\"\;/\\\"/g;
1934: $renametitle=~s/ /%20/g;
1935: my $line=&Apache::loncommon::start_data_table_row();
1936: my ($form_start,$form_end);
1937: # Edit commands
1938: my ($container, $type, $esc_path, $path, $symb);
1939: if ($env{'form.folderpath'}) {
1940: $type = 'folder';
1941: $container = 'sequence';
1942: $esc_path=&escape($env{'form.folderpath'});
1943: $path = &HTML::Entities::encode($env{'form.folderpath'},'<>&"');
1944: # $htmlfoldername=&HTML::Entities::encode($env{'form.foldername'},'<>&"');
1945: }
1946: if ($env{'form.pagepath'}) {
1947: $type = $container = 'page';
1948: $esc_path=&escape($env{'form.pagepath'});
1949: $path = &HTML::Entities::encode($env{'form.pagepath'},'<>&"');
1950: $symb=&escape($env{'form.pagesymb'});
1951: }
1952: my $cpinfo='';
1953: if ($allowed) {
1954: my $incindex=$index+1;
1955: my $selectbox='';
1956: if (($folder!~/^supplemental/) &&
1957: ($#LONCAPA::map::order>0) &&
1958: ((split(/\:/,
1959: $LONCAPA::map::resources[$LONCAPA::map::order[0]]))[1]
1960: ne '') &&
1961: ((split(/\:/,
1962: $LONCAPA::map::resources[$LONCAPA::map::order[1]]))[1]
1963: ne '')) {
1964: $selectbox=
1965: '<input type="hidden" name="currentpos" value="'.$incindex.'" />'.
1966: '<select name="newpos" onchange="this.form.submit()">';
1967: for (my $i=1;$i<=$#LONCAPA::map::order+1;$i++) {
1968: if ($i==$incindex) {
1969: $selectbox.='<option value="" selected="selected">('.$i.')</option>';
1970: } else {
1971: $selectbox.='<option value="'.$i.'">'.$i.'</option>';
1972: }
1973: }
1974: $selectbox.='</select>';
1975: }
1976: my %lt=&Apache::lonlocal::texthash(
1977: 'up' => 'Move Up',
1978: 'dw' => 'Move Down',
1979: 'rm' => 'Remove',
1980: 'ct' => 'Cut',
1981: 'rn' => 'Rename',
1982: 'cp' => 'Copy');
1983: my $nocopy=0;
1984: my $nocut=0;
1985: if ($url=~/\.(page|sequence)$/) {
1986: if ($url =~ m{/res/}) {
1987: # no copy for published maps
1988: $nocopy = 1;
1989: } else {
1990: foreach my $item (&Apache::lonsequence::attemptread(&Apache::lonnet::filelocation('',$url),1)) {
1991: my ($title,$url,$ext,$type)=split(/\:/,$item);
1992: if (($url=~/\.(page|sequence)/) && ($type ne 'zombie')) {
1993: $nocopy=1;
1994: last;
1995: }
1996: }
1997: }
1998: }
1999: if ($url=~/^\/res\/lib\/templates\//) {
2000: $nocopy=1;
2001: $nocut=1;
2002: }
2003: my $copylink=' ';
2004: my $cutlink=' ';
2005:
2006: my $skip_confirm = 0;
2007: if ( $folder =~ /^supplemental/
2008: || ($url =~ m{( /smppg$
2009: |/syllabus$
2010: |/aboutme$
2011: |/navmaps$
2012: |/bulletinboard$
2013: |\.html$
2014: |^/adm/wrapper/ext)}x)) {
2015: $skip_confirm = 1;
2016: }
2017:
2018: if (!$nocopy) {
2019: $copylink=(<<ENDCOPY);
2020: <a href='javascript:markcopy("$esc_path","$index","$renametitle","$container","$symb","$folder");' class="LC_docs_copy">$lt{'cp'}</a>
2021: ENDCOPY
2022: }
2023: if (!$nocut) {
2024: $cutlink=(<<ENDCUT);
2025: <a href='javascript:cutres("$esc_path","$index","$renametitle","$container","$symb","$folder",$skip_confirm);' class="LC_docs_cut">$lt{'ct'}</a>
2026: ENDCUT
2027: }
2028: $form_start = (<<END);
2029: <form action="/adm/coursedocs" method="post">
2030: <input type="hidden" name="${type}path" value="$path" />
2031: <input type="hidden" name="${type}symb" value="$symb" />
2032: <input type="hidden" name="setparms" value="$orderidx" />
2033: <input type="hidden" name="changeparms" value="0" />
2034: END
2035: $form_end = '</form>';
2036: $line.=(<<END);
2037: <td>
2038: <div class="LC_docs_entry_move">
2039: <a href='/adm/coursedocs?cmd=up_$index&${type}path=$esc_path&${type}symb=$symb$cpinfo'>
2040: <img src="${iconpath}move_up.gif" alt='$lt{'up'}' class="LC_icon" />
2041: </a>
2042: </div>
2043: <div class="LC_docs_entry_move">
2044: <a href='/adm/coursedocs?cmd=down_$index&${type}path=$esc_path&${type}symb=$symb$cpinfo'>
2045: <img src="${iconpath}move_down.gif" alt='$lt{'dw'}' class="LC_icon" />
2046: </a>
2047: </div>
2048: </td>
2049: <td>
2050: $form_start
2051: $selectbox
2052: $form_end
2053: </td>
2054: <td class="LC_docs_entry_commands">
2055: <a href='javascript:removeres("$esc_path","$index","$renametitle","$container","$symb",$skip_confirm);' class="LC_docs_remove">$lt{'rm'}</a>
2056: $cutlink
2057: <a href='javascript:changename("$esc_path","$index","$renametitle","$container","$symb");' class="LC_docs_rename">$lt{'rn'}</a>
2058: $copylink
2059: </td>
2060: END
2061:
2062: }
2063: # Figure out what kind of a resource this is
2064: my ($extension)=($url=~/\.(\w+)$/);
2065: my $uploaded=($url=~/^\/*uploaded\//);
2066: my $icon=&Apache::loncommon::icon($url);
2067: my $isfolder=0;
2068: my $ispage=0;
2069: my $folderarg;
2070: my $pagearg;
2071: my $pagefile;
2072: if ($uploaded) {
2073: if ($extension eq 'sequence') {
2074: $icon=$iconpath.'/navmap.folder.closed.gif';
2075: $url=~/\Q$coursenum\E\/([\/\w]+)\.sequence$/;
2076: $url='/adm/coursedocs?';
2077: $folderarg=$1;
2078: $isfolder=1;
2079: } elsif ($extension eq 'page') {
2080: $icon=$iconpath.'/page.gif';
2081: $url=~/\Q$coursenum\E\/([\/\w]+)\.page$/;
2082: $pagearg=$1;
2083: $url='/adm/coursedocs?';
2084: $ispage=1;
2085: } else {
2086: &Apache::lonnet::allowuploaded('/adm/coursedoc',$url);
2087: }
2088: }
2089:
2090: my $orig_url = $url;
2091: $orig_url=~s{http(:|:)//https(:|:)//}{https$2//};
2092: my $external = ($url=~s{^http(|s)(:|:)//}{/adm/wrapper/ext/});
2093: if ((!$isfolder) && ($residx) && ($folder!~/supplemental/) && (!$ispage)) {
2094: my $symb=&Apache::lonnet::symbclean(
2095: &Apache::lonnet::declutter('uploaded/'.
2096: $env{'course.'.$env{'request.course.id'}.'.domain'}.'/'.
2097: $env{'course.'.$env{'request.course.id'}.'.num'}.'/'.$folder.
2098: '.sequence').
2099: '___'.$residx.'___'.
2100: &Apache::lonnet::declutter($url));
2101: (undef,undef,$url)=&Apache::lonnet::decode_symb($symb);
2102: $url=&Apache::lonnet::clutter($url);
2103: if ($url=~/^\/*uploaded\//) {
2104: $url=~/\.(\w+)$/;
2105: my $embstyle=&Apache::loncommon::fileembstyle($1);
2106: if (($embstyle eq 'img') || ($embstyle eq 'emb')) {
2107: $url='/adm/wrapper'.$url;
2108: } elsif ($embstyle eq 'ssi') {
2109: #do nothing with these
2110: } elsif ($url!~/\.(sequence|page)$/) {
2111: $url='/adm/coursedocs/showdoc'.$url;
2112: }
2113: } elsif ($url=~m|^/ext/|) {
2114: $url='/adm/wrapper'.$url;
2115: $external = 1;
2116: }
2117: if (&Apache::lonnet::symbverify($symb,$url)) {
2118: $url.=(($url=~/\?/)?'&':'?').'symb='.&escape($symb);
2119: } else {
2120: $url='';
2121: }
2122: if ($container eq 'page') {
2123: my $symb=$env{'form.pagesymb'};
2124:
2125: $url=&Apache::lonnet::clutter((&Apache::lonnet::decode_symb($symb))[2]);
2126: $url.=(($url=~/\?/)?'&':'?').'symb='.&escape($symb);
2127: }
2128: }
2129: my ($parameterset,$rand_order_text) = (' ', ' ');
2130: if ($isfolder || $extension eq 'sequence') {
2131: my $foldername=&escape($foldertitle);
2132: my $folderpath=$env{'form.folderpath'};
2133: if ($folderpath) { $folderpath.='&' };
2134: # Append randompick number, hidden, and encrypted with ":" to foldername,
2135: # so it gets transferred between levels
2136: $folderpath.=$folderarg.'&'.$foldername.':'.(&LONCAPA::map::getparameter($orderidx,
2137: 'parameter_randompick'))[0]
2138: .':'.((&LONCAPA::map::getparameter($orderidx,
2139: 'parameter_hiddenresource'))[0]=~/^yes$/i)
2140: .':'.((&LONCAPA::map::getparameter($orderidx,
2141: 'parameter_encrypturl'))[0]=~/^yes$/i)
2142: .':'.((&LONCAPA::map::getparameter($orderidx,
2143: 'parameter_randomorder'))[0]=~/^yes$/i);
2144: $url.='folderpath='.&escape($folderpath).$cpinfo;
2145: $parameterset='<label>'.&mt('Randomly Pick: ').
2146: '<input type="text" size="4" onchange="this.form.changeparms.value='."'randompick'".';this.form.submit()" name="randompick_'.$orderidx.'" value="'.
2147: (&LONCAPA::map::getparameter($orderidx,
2148: 'parameter_randompick'))[0].
2149: '" />'.
2150: '<a href="javascript:void(0)">'.&mt('Save').'</a></label>';
2151: my $ro_set=
2152: ((&LONCAPA::map::getparameter($orderidx,'parameter_randomorder'))[0]=~/^yes$/i?' checked="checked"':'');
2153: $rand_order_text ='
2154: <span class="LC_nobreak"><label><input type="checkbox" name="randomorder_'.$orderidx.'" onclick="this.form.changeparms.value=\'randomorder\';this.form.submit()" '.$ro_set.' /> '.&mt('Random Order').' </label></span>';
2155: }
2156: if ($ispage) {
2157: my $pagename=&escape($pagetitle);
2158: my $pagepath;
2159: my $folderpath=$env{'form.folderpath'};
2160: if ($folderpath) { $pagepath = $folderpath.'&' };
2161: $pagepath.=$pagearg.'&'.$pagename;
2162: my $symb=$env{'form.pagesymb'};
2163: if (!$symb) {
2164: my $path='uploaded/'.
2165: $env{'course.'.$env{'request.course.id'}.'.domain'}.'/'.
2166: $env{'course.'.$env{'request.course.id'}.'.num'}.'/';
2167: $symb=&Apache::lonnet::encode_symb($path.$folder.'.sequence',
2168: $residx,
2169: $path.$pagearg.'.page');
2170: }
2171: $url.='pagepath='.&escape($pagepath).
2172: '&pagesymb='.&escape($symb).$cpinfo;
2173: }
2174: if (($external) && ($allowed)) {
2175: my $form = ($folder =~ /^default/)? 'newext' : 'supnewext';
2176: $external = ' <a class="LC_docs_ext_edit" href="javascript:edittext(\''.$form.'\',\''.$residx.'\',\''.&escape($title).'\',\''.&escape($orig_url).'\');" >'.&mt('Edit').'</a>';
2177: } else {
2178: undef($external);
2179: }
2180: my $reinit;
2181: if ($crstype eq 'Community') {
2182: $reinit = &mt('(re-initialize community to access)');
2183: } else {
2184: $reinit = &mt('(re-initialize course to access)');
2185: }
2186: $line.='
2187: <td>
2188: '.($url?'<a href="'.$url.'">':'').'<img src="'.$icon.'" alt="" class="LC_icon" />'.($url?'</a>':'').'
2189: </td>
2190: <td>
2191: '.($url?"<a href=\"$url\">":'').$title.($url?'</a>':' <span class="LC_docs_reinit_warn">'.$reinit.'</span>').$external."
2192: </td>";
2193: if (($allowed) && ($folder!~/^supplemental/)) {
2194: my %lt=&Apache::lonlocal::texthash(
2195: 'hd' => 'Hidden',
2196: 'ec' => 'URL hidden');
2197: my $enctext=
2198: ((&LONCAPA::map::getparameter($orderidx,'parameter_encrypturl'))[0]=~/^yes$/i?' checked="checked"':'');
2199: my $hidtext=
2200: ((&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i?' checked="checked"':'');
2201: $line.=(<<ENDPARMS);
2202: <td class="LC_docs_entry_parameter">
2203: $form_start
2204: <label><input type="checkbox" name="hiddenresource_$orderidx" onclick="this.form.changeparms.value='hiddenresource';this.form.submit()" $hidtext /> $lt{'hd'}</label>
2205: $form_end
2206: </td>
2207: <td class="LC_docs_entry_parameter">
2208: $form_start
2209: <label><input type="checkbox" name="encrypturl_$orderidx" onclick="this.form.changeparms.value='encrypturl';this.form.submit()" $enctext /> $lt{'ec'}</label>
2210: $form_end
2211: </td>
2212: <td class="LC_docs_entry_parameter">$form_start $rand_order_text $form_end</td>
2213: <td class="LC_docs_entry_parameter">$form_start $parameterset $form_end</td>
2214: ENDPARMS
2215: }
2216: $line.=&Apache::loncommon::end_data_table_row();
2217: return $line;
2218: }
2219:
2220: =pod
2221:
2222: =item tiehash()
2223:
2224: tie the hash
2225:
2226: =cut
2227:
2228: sub tiehash {
2229: my ($mode)=@_;
2230: $hashtied=0;
2231: if ($env{'request.course.fn'}) {
2232: if ($mode eq 'write') {
2233: if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.".db",
2234: &GDBM_WRCREAT(),0640)) {
2235: $hashtied=2;
2236: }
2237: } else {
2238: if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.".db",
2239: &GDBM_READER(),0640)) {
2240: $hashtied=1;
2241: }
2242: }
2243: }
2244: }
2245:
2246: sub untiehash {
2247: if ($hashtied) { untie %hash; }
2248: $hashtied=0;
2249: return OK;
2250: }
2251:
2252:
2253:
2254:
2255: sub checkonthis {
2256: my ($r,$url,$level,$title)=@_;
2257: $url=&unescape($url);
2258: $alreadyseen{$url}=1;
2259: $r->rflush();
2260: if (($url) && ($url!~/^\/uploaded\//) && ($url!~/\*$/)) {
2261: $r->print("\n<br />");
2262: if ($level==0) {
2263: $r->print("<br />");
2264: }
2265: for (my $i=0;$i<=$level*5;$i++) {
2266: $r->print(' ');
2267: }
2268: $r->print('<a href="'.$url.'" target="cat">'.
2269: ($title?$title:$url).'</a> ');
2270: if ($url=~/^\/res\//) {
2271: my $result=&Apache::lonnet::repcopy(
2272: &Apache::lonnet::filelocation('',$url));
2273: if ($result eq 'ok') {
2274: $r->print('<span class="LC_success">'.&mt('ok').'</span>');
2275: $r->rflush();
2276: &Apache::lonnet::countacc($url);
2277: $url=~/\.(\w+)$/;
2278: if (&Apache::loncommon::fileembstyle($1) eq 'ssi') {
2279: $r->print('<br />');
2280: $r->rflush();
2281: for (my $i=0;$i<=$level*5;$i++) {
2282: $r->print(' ');
2283: }
2284: $r->print('- '.&mt('Rendering:').' ');
2285: my ($errorcount,$warningcount)=split(/:/,
2286: &Apache::lonnet::ssi_body($url,
2287: ('grade_target'=>'web',
2288: 'return_only_error_and_warning_counts' => 1)));
2289: if (($errorcount) ||
2290: ($warningcount)) {
2291: if ($errorcount) {
2292: $r->print('<img src="/adm/lonMisc/bomb.gif" alt="'.&mt('bomb').'" /><span class="LC_error">'.
2293: &mt('[quant,_1,error]',$errorcount).'</span>');
2294: }
2295: if ($warningcount) {
2296: $r->print('<span class="LC_warning">'.
2297: &mt('[quant,_1,warning]',$warningcount).'</span>');
2298: }
2299: } else {
2300: $r->print('<span class="LC_success">'.&mt('ok').'</span>');
2301: }
2302: $r->rflush();
2303: }
2304: my $dependencies=
2305: &Apache::lonnet::metadata($url,'dependencies');
2306: foreach my $dep (split(/\,/,$dependencies)) {
2307: if (($dep=~/^\/res\//) && (!$alreadyseen{$dep})) {
2308: &checkonthis($r,$dep,$level+1);
2309: }
2310: }
2311: } elsif ($result eq 'unavailable') {
2312: $r->print('<span class="LC_error">'.&mt('connection down').'</span>');
2313: } elsif ($result eq 'not_found') {
2314: unless ($url=~/\$/) {
2315: $r->print('<span class="LC_error">'.&mt('not found').'</b></span>');
2316: } else {
2317: $r->print('<span class="LC_error">'.&mt('unable to verify variable URL').'</span>');
2318: }
2319: } else {
2320: $r->print('<span class="LC_error">'.&mt('access denied').'</span>');
2321: }
2322: }
2323: }
2324: }
2325:
2326:
2327:
2328: =pod
2329:
2330: =item list_symbs()
2331:
2332: List Symbs
2333:
2334: =cut
2335:
2336: sub list_symbs {
2337: my ($r) = @_;
2338:
2339: my $crstype = &Apache::loncommon::course_type();
2340: $r->print(&Apache::loncommon::start_page('Symb List'));
2341: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Symb List'));
2342: &startContentScreen($r,'tools');
2343: my $navmap = Apache::lonnavmaps::navmap->new();
2344: if (!defined($navmap)) {
2345: $r->print('<h2>'.&mt('Retrieval of List Failed').'</h2>'.
2346: '<div class="LC_error">'.
2347: &mt('Unable to retrieve information about course contents').
2348: '</div>');
2349: &Apache::lonnet::logthis('Symb list failed - could not create navmap object in '.lc($crstype).':'.$env{'request.course.id'});
2350: } else {
2351: $r->print("<pre>\n");
2352: foreach my $res ($navmap->retrieveResources()) {
2353: $r->print($res->compTitle()."\t".$res->symb()."\n");
2354: }
2355: $r->print("\n</pre>\n");
2356: }
2357: }
2358:
2359:
2360: sub verifycontent {
2361: my ($r) = @_;
2362: my $crstype = &Apache::loncommon::course_type();
2363: $r->print(&Apache::loncommon::start_page('Verify '.$crstype.' Documents'));
2364: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Verify '.$crstype.' Documents'));
2365: &startContentScreen($r,'tools');
2366: $hashtied=0;
2367: undef %alreadyseen;
2368: %alreadyseen=();
2369: &tiehash();
2370: foreach my $key (keys(%hash)) {
2371: if ($hash{$key}=~/\.(page|sequence)$/) {
2372: if (($key=~/^src_/) && ($alreadyseen{&unescape($hash{$key})})) {
2373: $r->print('<hr /><span class="LC_error">'.
2374: &mt('The following sequence or page is included more than once in your '.$crstype.':').' '.
2375: &unescape($hash{$key}).'</span><br />'.
2376: &mt('Note that grading records for problems included in this sequence or folder will overlap.').'<hr />');
2377: }
2378: }
2379: if (($key=~/^src\_(.+)$/) && (!$alreadyseen{&unescape($hash{$key})})) {
2380: &checkonthis($r,$hash{$key},0,$hash{'title_'.$1});
2381: }
2382: }
2383: &untiehash();
2384: $r->print('<p class="LC_success">'.&mt('Done').'</p>');
2385: }
2386:
2387:
2388: sub devalidateversioncache {
2389: my $src=shift;
2390: &Apache::lonnet::devalidate_cache_new('courseresversion',$env{'request.course.id'}.'_'.
2391: &Apache::lonnet::clutter($src));
2392: }
2393:
2394: sub checkversions {
2395: my ($r) = @_;
2396: my $crstype = &Apache::loncommon::course_type();
2397: $r->print(&Apache::loncommon::start_page("Check $crstype Document Versions"));
2398: $r->print(&Apache::lonhtmlcommon::breadcrumbs("Check $crstype Document Versions"));
2399: &startContentScreen($r,'tools');
2400:
2401: my $header='';
2402: my $startsel='';
2403: my $monthsel='';
2404: my $weeksel='';
2405: my $daysel='';
2406: my $allsel='';
2407: my %changes=();
2408: my $starttime=0;
2409: my $haschanged=0;
2410: my %setversions=&Apache::lonnet::dump('resourceversions',
2411: $env{'course.'.$env{'request.course.id'}.'.domain'},
2412: $env{'course.'.$env{'request.course.id'}.'.num'});
2413:
2414: $hashtied=0;
2415: &tiehash();
2416: my %newsetversions=();
2417: if ($env{'form.setmostrecent'}) {
2418: $haschanged=1;
2419: foreach my $key (keys(%hash)) {
2420: if ($key=~/^ids\_(\/res\/.+)$/) {
2421: $newsetversions{$1}='mostrecent';
2422: &devalidateversioncache($1);
2423: }
2424: }
2425: } elsif ($env{'form.setcurrent'}) {
2426: $haschanged=1;
2427: foreach my $key (keys(%hash)) {
2428: if ($key=~/^ids\_(\/res\/.+)$/) {
2429: my $getvers=&Apache::lonnet::getversion($1);
2430: if ($getvers>0) {
2431: $newsetversions{$1}=$getvers;
2432: &devalidateversioncache($1);
2433: }
2434: }
2435: }
2436: } elsif ($env{'form.setversions'}) {
2437: $haschanged=1;
2438: foreach my $key (keys(%env)) {
2439: if ($key=~/^form\.set_version_(.+)$/) {
2440: my $src=$1;
2441: if (($env{$key}) && ($env{$key} ne $setversions{$src})) {
2442: $newsetversions{$src}=$env{$key};
2443: &devalidateversioncache($src);
2444: }
2445: }
2446: }
2447: }
2448: if ($haschanged) {
2449: if (&Apache::lonnet::put('resourceversions',\%newsetversions,
2450: $env{'course.'.$env{'request.course.id'}.'.domain'},
2451: $env{'course.'.$env{'request.course.id'}.'.num'}) eq 'ok') {
2452: $r->print('<h1>'.&mt('Your Version Settings have been Saved').'</h1>');
2453: } else {
2454: $r->print('<h1><span class="LC_error">'.&mt('An Error Occured while Attempting to Save your Version Settings').'</span></h1>');
2455: }
2456: &mark_hash_old();
2457: }
2458: &changewarning($r,'');
2459: if ($env{'form.timerange'} eq 'all') {
2460: # show all documents
2461: $header=&mt('All Documents in '.$crstype);
2462: $allsel=1;
2463: foreach my $key (keys(%hash)) {
2464: if ($key=~/^ids\_(\/res\/.+)$/) {
2465: my $src=$1;
2466: $changes{$src}=1;
2467: }
2468: }
2469: } else {
2470: # show documents which changed
2471: %changes=&Apache::lonnet::dump
2472: ('versionupdate',$env{'course.'.$env{'request.course.id'}.'.domain'},
2473: $env{'course.'.$env{'request.course.id'}.'.num'});
2474: my $firstkey=(keys(%changes))[0];
2475: unless ($firstkey=~/^error\:/) {
2476: unless ($env{'form.timerange'}) {
2477: $env{'form.timerange'}=604800;
2478: }
2479: my $seltext=&mt('during the last').' '.$env{'form.timerange'}.' '
2480: .&mt('seconds');
2481: if ($env{'form.timerange'}==-1) {
2482: $seltext='since start of course';
2483: $startsel='selected';
2484: $env{'form.timerange'}=time;
2485: }
2486: $starttime=time-$env{'form.timerange'};
2487: if ($env{'form.timerange'}==2592000) {
2488: $seltext=&mt('during the last month').' ('.&Apache::lonlocal::locallocaltime($starttime).')';
2489: $monthsel='selected';
2490: } elsif ($env{'form.timerange'}==604800) {
2491: $seltext=&mt('during the last week').' ('.&Apache::lonlocal::locallocaltime($starttime).')';
2492: $weeksel='selected';
2493: } elsif ($env{'form.timerange'}==86400) {
2494: $seltext=&mt('since yesterday').' ('.&Apache::lonlocal::locallocaltime($starttime).')';
2495: $daysel='selected';
2496: }
2497: $header=&mt('Content changed').' '.$seltext;
2498: } else {
2499: $header=&mt('No content modifications yet.');
2500: }
2501: }
2502: %setversions=&Apache::lonnet::dump('resourceversions',
2503: $env{'course.'.$env{'request.course.id'}.'.domain'},
2504: $env{'course.'.$env{'request.course.id'}.'.num'});
2505: my %lt=&Apache::lonlocal::texthash
2506: ('st' => 'Version changes since start of '.$crstype,
2507: 'lm' => 'Version changes since last Month',
2508: 'lw' => 'Version changes since last Week',
2509: 'sy' => 'Version changes since Yesterday',
2510: 'al' => 'All Resources (possibly large output)',
2511: 'sd' => 'Display',
2512: 'fi' => 'File',
2513: 'md' => 'Modification Date',
2514: 'mr' => 'Most recently published Version',
2515: 've' => 'Version used in '.$crstype,
2516: 'vu' => 'Set Version to be used in '.$crstype,
2517: 'sv' => 'Set Versions to be used in '.$crstype.' according to Selections below',
2518: 'sm' => 'Keep all Resources up-to-date with most recent Versions (default)',
2519: 'sc' => 'Set all Resource Versions to current Version (Fix Versions)',
2520: 'di' => 'Differences');
2521: $r->print(<<ENDHEADERS);
2522: <form action="/adm/coursedocs" method="post">
2523: <input type="hidden" name="versions" value="1" />
2524: <input type="submit" name="setmostrecent" value="$lt{'sm'}" />
2525: <input type="submit" name="setcurrent" value="$lt{'sc'}" /><hr />
2526: <select name="timerange">
2527: <option value='all' $allsel>$lt{'al'}</option>
2528: <option value="-1" $startsel>$lt{'st'}</option>
2529: <option value="2592000" $monthsel>$lt{'lm'}</option>
2530: <option value="604800" $weeksel>$lt{'lw'}</option>
2531: <option value="86400" $daysel>$lt{'sy'}</option>
2532: </select>
2533: <input type="submit" name="display" value="$lt{'sd'}" />
2534: <h3>$header</h3>
2535: <input type="submit" name="setversions" value="$lt{'sv'}" />
2536: <table border="0">
2537: ENDHEADERS
2538: foreach my $key (sort(keys(%changes))) {
2539: if ($changes{$key}>$starttime) {
2540: my ($root,$extension)=($key=~/^(.*)\.(\w+)$/);
2541: my $currentversion=&Apache::lonnet::getversion($key);
2542: if ($currentversion<0) {
2543: $currentversion=&mt('Could not be determined.');
2544: }
2545: my $linkurl=&Apache::lonnet::clutter($key);
2546: $r->print(
2547: '<tr><td colspan="5"><br /><br /><font size="+1"><b>'.
2548: &Apache::lonnet::gettitle($linkurl).
2549: '</b></font></td></tr>'.
2550: '<tr><td> </td>'.
2551: '<td colspan="4">'.
2552: '<a href="'.$linkurl.'" target="cat">'.$linkurl.
2553: '</a></td></tr>'.
2554: '<tr><td></td>'.
2555: '<td title="'.$lt{'md'}.'">'.
2556: &Apache::lonlocal::locallocaltime(
2557: &Apache::lonnet::metadata($root.'.'.$extension,
2558: 'lastrevisiondate')
2559: ).
2560: '</td>'.
2561: '<td title="'.$lt{'mr'}.'"><span class="LC_nobreak">Most Recent: '.
2562: '<font size="+1">'.$currentversion.'</font>'.
2563: '</span></td>'.
2564: '<td title="'.$lt{'ve'}.'"><span class="LC_nobreak">In '.$crstype.': '.
2565: '<font size="+1">');
2566: # Used in course
2567: my $usedversion=$hash{'version_'.$linkurl};
2568: if (($usedversion) && ($usedversion ne 'mostrecent')) {
2569: $r->print($usedversion);
2570: } else {
2571: $r->print($currentversion);
2572: }
2573: $r->print('</font></span></td><td title="'.$lt{'vu'}.'">'.
2574: '<span class="LC_nobreak">Use: ');
2575: # Set version
2576: $r->print(&Apache::loncommon::select_form($setversions{$linkurl},
2577: 'set_version_'.$linkurl,
2578: {'select_form_order' =>
2579: ['',1..$currentversion,'mostrecent'],
2580: '' => '',
2581: 'mostrecent' => &mt('most recent'),
2582: map {$_,$_} (1..$currentversion)}));
2583: $r->print('</span></td></tr><tr><td></td>');
2584: my $lastold=1;
2585: for (my $prevvers=1;$prevvers<$currentversion;$prevvers++) {
2586: my $url=$root.'.'.$prevvers.'.'.$extension;
2587: if (&Apache::lonnet::metadata($url,'lastrevisiondate')<
2588: $starttime) {
2589: $lastold=$prevvers;
2590: }
2591: }
2592: #
2593: # Code to figure out how many version entries should go in
2594: # each of the four columns
2595: my $entries_per_col = 0;
2596: my $num_entries = ($currentversion-$lastold);
2597: if ($num_entries % 4 == 0) {
2598: $entries_per_col = $num_entries/4;
2599: } else {
2600: $entries_per_col = $num_entries/4 + 1;
2601: }
2602: my $entries_count = 0;
2603: $r->print('<td valign="top"><font size="-2">');
2604: my $cols_output = 1;
2605: for (my $prevvers=$lastold;$prevvers<$currentversion;$prevvers++) {
2606: my $url=$root.'.'.$prevvers.'.'.$extension;
2607: $r->print('<span class="LC_nobreak"><a href="'.&Apache::lonnet::clutter($url).
2608: '">'.&mt('Version').' '.$prevvers.'</a> ('.
2609: &Apache::lonlocal::locallocaltime(
2610: &Apache::lonnet::metadata($url,
2611: 'lastrevisiondate')
2612: ).
2613: ')');
2614: if (&Apache::loncommon::fileembstyle($extension) eq 'ssi') {
2615: $r->print(' <a href="/adm/diff?filename='.
2616: &Apache::lonnet::clutter($root.'.'.$extension).
2617: '&versionone='.$prevvers.
2618: '">'.&mt('Diffs').'</a>');
2619: }
2620: $r->print('</span><br />');
2621: if (++$entries_count % $entries_per_col == 0) {
2622: $r->print('</font></td>');
2623: if ($cols_output != 4) {
2624: $r->print('<td valign="top"><font size="-2">');
2625: $cols_output++;
2626: }
2627: }
2628: }
2629: while($cols_output++ < 4) {
2630: $r->print('</font></td><td><font>')
2631: }
2632: $r->print('</font></td></tr>'."\n");
2633: }
2634: }
2635: $r->print('</table></form>');
2636: $r->print('<p class="LC_success">'.&mt('Done').'</p>');
2637:
2638: &untiehash();
2639: }
2640:
2641: sub mark_hash_old {
2642: my $retie_hash=0;
2643: if ($hashtied) {
2644: $retie_hash=1;
2645: &untiehash();
2646: }
2647: &tiehash('write');
2648: $hash{'old'}=1;
2649: &untiehash();
2650: if ($retie_hash) { &tiehash(); }
2651: }
2652:
2653: sub is_hash_old {
2654: my $untie_hash=0;
2655: if (!$hashtied) {
2656: $untie_hash=1;
2657: &tiehash();
2658: }
2659: my $return=$hash{'old'};
2660: if ($untie_hash) { &untiehash(); }
2661: return $return;
2662: }
2663:
2664: sub changewarning {
2665: my ($r,$postexec,$message,$url)=@_;
2666: if (!&is_hash_old()) { return; }
2667: my $pathvar='folderpath';
2668: my $path=&escape($env{'form.folderpath'});
2669: if (!defined($url)) {
2670: if (defined($env{'form.pagepath'})) {
2671: $pathvar='pagepath';
2672: $path=&escape($env{'form.pagepath'});
2673: $path.='&pagesymb='.&escape($env{'form.pagesymb'});
2674: }
2675: $url='/adm/coursedocs?'.$pathvar.'='.$path;
2676: }
2677: my $course_type = &Apache::loncommon::course_type();
2678: if (!defined($message)) {
2679: $message='Changes will become active for your current session after [_1], or the next time you log in.';
2680: }
2681: $r->print("\n\n".
2682: '<script type="text/javascript">'."\n".
2683: '// <![CDATA['."\n".
2684: 'function reinit(tf) { tf.submit();'.$postexec.' }'."\n".
2685: '// ]]>'."\n".
2686: '</script>'."\n".
2687: '<form name="reinitform" method="post" action="/adm/roles" target="loncapaclient">'.
2688: '<input type="hidden" name="orgurl" value="'.$url.
2689: '" /><input type="hidden" name="selectrole" value="1" /><p class="LC_warning">'.
2690: &mt($message,' <input type="hidden" name="'.
2691: $env{'request.role'}.'" value="1" /><input type="button" value="'.
2692: &mt('re-initializing '.$course_type).'" onclick="reinit(this.form)" />').
2693: $help{'Caching'}.'</p></form>'."\n\n");
2694: }
2695:
2696:
2697: sub init_breadcrumbs {
2698: my ($form,$text)=@_;
2699: &Apache::lonhtmlcommon::clear_breadcrumbs();
2700: &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/coursedocs",
2701: text=>&Apache::loncommon::course_type().' Editor',
2702: faq=>273,
2703: bug=>'Instructor Interface',
2704: help => 'Docs_Adding_Course_Doc'});
2705: &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/coursedocs?".$form.'=1',
2706: text=>$text,
2707: faq=>273,
2708: bug=>'Instructor Interface'});
2709: }
2710:
2711: # subroutine to list form elements
2712: sub create_list_elements {
2713: my @formarr = @_;
2714: my $list = '';
2715: for my $button (@formarr){
2716: for my $picture(keys %$button) {
2717: $list .= &Apache::lonhtmlcommon::htmltag('li', $picture.' '.$button->{$picture}, {class => 'LC_menubuttons_inline_text'});
2718: }
2719: }
2720: return $list;
2721: }
2722:
2723: # subroutine to create ul from list elements
2724: sub create_form_ul {
2725: my $list = shift;
2726: my $ul = &Apache::lonhtmlcommon::htmltag('ul',$list, {class => 'LC_ListStyleNormal'});
2727: return $ul;
2728: }
2729:
2730: #
2731: # Start tabs
2732: #
2733:
2734: sub startContentScreen {
2735: my ($r,$mode)=@_;
2736: $r->print('<ul class="LC_TabContentBigger" id="mainnav">');
2737: $r->print('<li'.(($mode eq 'navmaps')?' class="active"':'').'><a href="/adm/navmaps"><b> '.&mt('Content Overview').' </b></a></li>');
2738:
2739: my $active = '';
2740: # does this user have privileges to modify docs?
2741: my $allowed=&Apache::lonnet::allowed('mdc',$env{'request.course.id'});
2742:
2743: my $onclick;
2744: my $href;
2745:
2746: if ($allowed) {
2747: $r->print('<li '.(($mode eq 'docs')?' class="active"':'').
2748: '><a href="/adm/coursedocs?forcestandard=1"><b> '.&mt('Content Editor').' </b></a></li>');
2749: }
2750: $r->print('<li'.(($mode eq 'coursesearch')?' class="active"':'').'><a href="/adm/searchcourse"><b> '.&mt('Content Search').' </b></a></li>');
2751: $r->print('<li'.(($mode eq 'courseindex')?' class="active"':'').'><a href="/adm/indexcourse"><b> '.&mt('Content Index').' </b></a></li>');
2752: $r->print('<li '.(($mode eq 'supdocs')?' class="active"':'').
2753: '><a href="/adm/coursedocs?forcesupplement=1"><b>'.&mt('Supplemental Documents').'</b></a></li>');
2754: $r->print('</ul>');
2755: $r->print('<div class="LC_Box" style="clear:both;margin:0;">'
2756: .'<div id="maincoursedoc" style="margin:0 0;padding:0 0;">');
2757: $r->print('<div class="LC_ContentBox" id="mainCourseDocuments" style="display: block;">');
2758: }
2759:
2760: #
2761: # End tabs
2762: #
2763:
2764: sub endContentScreen {
2765: my ($r)=@_;
2766: $r->print('</div></div></div>');
2767: }
2768:
2769: sub supplemental_base {
2770: return 'supplemental&'.&escape(&mt('Supplemental '.&Apache::loncommon::course_type().' Documents'));
2771: }
2772:
2773: sub handler {
2774: my $r = shift;
2775: &Apache::loncommon::content_type($r,'text/html');
2776: $r->send_http_header;
2777: return OK if $r->header_only;
2778: my $crstype = &Apache::loncommon::course_type();
2779:
2780: #
2781: # --------------------------------------------- Initialize help topics for this
2782: foreach my $topic ('Adding_Course_Doc','Main_Course_Documents',
2783: 'Adding_External_Resource','Navigate_Content',
2784: 'Adding_Folders','Docs_Overview', 'Load_Map',
2785: 'Supplemental','Score_Upload_Form','Adding_Pages',
2786: 'Importing_LON-CAPA_Resource','Uploading_From_Harddrive',
2787: 'Check_Resource_Versions','Verify_Content') {
2788: $help{$topic}=&Apache::loncommon::help_open_topic('Docs_'.$topic);
2789: }
2790: # Composite help files
2791: $help{'Syllabus'} = &Apache::loncommon::help_open_topic(
2792: 'Docs_About_Syllabus,Docs_Editing_Templated_Pages');
2793: $help{'Simple Page'} = &Apache::loncommon::help_open_topic(
2794: 'Docs_About_Simple_Page,Docs_Editing_Templated_Pages');
2795: $help{'Simple Problem'} = &Apache::loncommon::help_open_topic(
2796: 'Option_Response_Simple');
2797: $help{'Bulletin Board'} = &Apache::loncommon::help_open_topic(
2798: 'Docs_About_Bulletin_Board,Docs_Editing_Templated_Pages');
2799: $help{'My Personal Information Page'} = &Apache::loncommon::help_open_topic(
2800: 'Docs_About_My_Personal_Info,Docs_Editing_Templated_Pages');
2801: $help{'Group Portfolio'} = &Apache::loncommon::help_open_topic('Docs_About_Group_Files');
2802: $help{'Caching'} = &Apache::loncommon::help_open_topic('Caching');
2803:
2804: # does this user have privileges to modify docs
2805: my $allowed=&Apache::lonnet::allowed('mdc',$env{'request.course.id'});
2806: if ($allowed && $env{'form.verify'}) {
2807: &init_breadcrumbs('verify','Verify Content');
2808: &verifycontent($r);
2809: } elsif ($allowed && $env{'form.listsymbs'}) {
2810: &init_breadcrumbs('listsymbs','List Symbs');
2811: &list_symbs($r);
2812: } elsif ($allowed && $env{'form.docslog'}) {
2813: &init_breadcrumbs('docslog','Show Log');
2814: &docs_change_log($r);
2815: } elsif ($allowed && $env{'form.versions'}) {
2816: &init_breadcrumbs('versions','Check/Set Resource Versions');
2817: &checkversions($r);
2818: } elsif ($allowed && $env{'form.dumpcourse'}) {
2819: &init_breadcrumbs('dumpcourse','Dump '.&Apache::loncommon::course_type().' Documents to Construction Space');
2820: &dumpcourse($r);
2821: } elsif ($allowed && $env{'form.exportcourse'}) {
2822: &init_breadcrumbs('exportcourse','IMS Export');
2823: &exportcourse($r);
2824: } else {
2825: #
2826: # Done catching special calls
2827: # The whole rest is for course and supplemental documents
2828: # Get the parameters that may be needed
2829: #
2830: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
2831: ['folderpath','pagepath',
2832: 'pagesymb','forcesupplement','forcestandard']);
2833:
2834: # standard=1: this is a "new-style" course with an uploaded map as top level
2835: # standard=2: this is a "old-style" course, and there is nothing we can do
2836:
2837: my $standard=($env{'request.course.uri'}=~/^\/uploaded\//);
2838:
2839: # Decide whether this should display supplemental or main content
2840: # supplementalflag=1: show supplemental documents
2841: # supplementalflag=0: show standard documents
2842:
2843:
2844: my $supplementalflag=($env{'form.folderpath'}=~/^supplemental/);
2845: if (($env{'form.folderpath'}=~/^default/) || $env{'form.folderpath'} eq "" || ($env{'form.pagepath'})) {
2846: $supplementalflag=0;
2847: }
2848: if ($env{'form.forcesupplement'}) { $supplementalflag=1; }
2849: if ($env{'form.forcestandard'}) { $supplementalflag=0; }
2850: unless ($allowed) { $supplementalflag=1; }
2851: unless ($standard) { $supplementalflag=1; }
2852:
2853: my $script='';
2854: my $showdoc=0;
2855: my $containertag;
2856: my $uploadtag;
2857:
2858: # Where do we store these for when we come back?
2859: my $stored_folderpath='docs_folderpath';
2860: if ($supplementalflag) {
2861: $stored_folderpath='docs_sup_folderpath';
2862: }
2863:
2864: # No folderpath, no pagepath, see if we have something stored
2865: if ((!$env{'form.folderpath'}) && (!$env{'form.pagepath'})) {
2866: &Apache::loncommon::restore_course_settings($stored_folderpath,
2867: {'folderpath' => 'scalar'});
2868: }
2869:
2870: # If we are not allowed to make changes, all we can see are supplemental docs
2871: if (!$allowed) {
2872: $env{'form.pagepath'}='';
2873: unless ($env{'form.folderpath'} =~ /^supplemental/) {
2874: $env{'form.folderpath'} = &supplemental_base();
2875: }
2876: }
2877: # If we still not have a folderpath, see if we can resurrect at pagepath
2878: if (!$env{'form.folderpath'} && $allowed) {
2879: &Apache::loncommon::restore_course_settings($stored_folderpath,
2880: {'pagepath' => 'scalar'});
2881: }
2882: # Make the zeroth entry in supplemental docs page paths, so we can get to top level
2883: if ($env{'form.folderpath'} =~ /^supplemental_\d+/) {
2884: $env{'form.folderpath'} = &supplemental_base()
2885: .'&'.
2886: $env{'form.folderpath'};
2887: }
2888: # If after all of this, we still don't have any paths, make them
2889: unless (($env{'form.pagepath'}) || ($env{'form.folderpath'})) {
2890: if ($supplementalflag) {
2891: $env{'form.folderpath'}=&supplemental_base();
2892: } else {
2893: $env{'form.folderpath'}='default';
2894: }
2895: }
2896:
2897: # Store this
2898: &Apache::loncommon::store_course_settings($stored_folderpath,
2899: {'pagepath' => 'scalar',
2900: 'folderpath' => 'scalar'});
2901:
2902: if ($env{'form.folderpath'}) {
2903: my (@folderpath)=split('&',$env{'form.folderpath'});
2904: $env{'form.foldername'}=&unescape(pop(@folderpath));
2905: $env{'form.folder'}=pop(@folderpath);
2906: }
2907: if ($env{'form.pagepath'}) {
2908: my (@pagepath)=split('&',$env{'form.pagepath'});
2909: $env{'form.pagename'}=&unescape(pop(@pagepath));
2910: $env{'form.folder'}=pop(@pagepath);
2911: $containertag = '<input type="hidden" name="pagepath" value="" />'.
2912: '<input type="hidden" name="pagesymb" value="" />';
2913: $uploadtag =
2914: '<input type="hidden" name="pagepath" value="'.&HTML::Entities::encode($env{'form.pagepath'},'<>&"').'" />'.
2915: '<input type="hidden" name="pagesymb" value="'.&HTML::Entities::encode($env{'form.pagesymb'},'<>&"').'" />'.
2916: '<input type="hidden" name="folderpath" value="" />';
2917: } else {
2918: my $folderpath=$env{'form.folderpath'};
2919: if (!$folderpath) {
2920: if ($env{'form.folder'} eq '' ||
2921: $env{'form.folder'} eq 'supplemental') {
2922: $folderpath='default&'.
2923: &escape(&mt('Main '.$crstype.' Documents'));
2924: }
2925: }
2926: $containertag = '<input type="hidden" name="folderpath" value="" />';
2927: $uploadtag = '<input type="hidden" name="folderpath" value="'.&HTML::Entities::encode($folderpath,'<>&"').'" />';
2928: }
2929: if ($r->uri=~/^\/adm\/coursedocs\/showdoc\/(.*)$/) {
2930: $showdoc='/'.$1;
2931: }
2932: if ($showdoc) { # got called in sequence from course
2933: $allowed=0;
2934: } else {
2935: if ($allowed) {
2936: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['cmd']);
2937: $script=&Apache::lonratedt::editscript('simple');
2938: }
2939: }
2940:
2941: # get course data
2942: my $coursenum=$env{'course.'.$env{'request.course.id'}.'.num'};
2943: my $coursedom=$env{'course.'.$env{'request.course.id'}.'.domain'};
2944:
2945: # get personal data
2946: my $uname=$env{'user.name'};
2947: my $udom=$env{'user.domain'};
2948: my $plainname=&escape(&Apache::loncommon::plainname($uname,$udom));
2949:
2950: # graphics settings
2951:
2952: $iconpath = &Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL') . "/");
2953:
2954: if ($allowed) {
2955: $script .= &editing_js($udom,$uname);
2956: }
2957: # -------------------------------------------------------------------- Body tag
2958: $script = '<script type="text/javascript">'."\n"
2959: .'// <![CDATA['."\n"
2960: .$script."\n"
2961: .'// ]]>'."\n"
2962: .'</script>'."\n";
2963:
2964: # Breadcrumbs
2965: &Apache::lonhtmlcommon::clear_breadcrumbs();
2966: unless ($showdoc) {
2967: &Apache::lonhtmlcommon::add_breadcrumb({
2968: href=>"/adm/coursedocs",text=>"$crstype Contents"});
2969:
2970: $r->print(&Apache::loncommon::start_page("$crstype Contents", $script,
2971: {'force_register' => $showdoc,})
2972: .&Apache::loncommon::help_open_menu('','',273,'RAT')
2973: .&Apache::lonhtmlcommon::breadcrumbs(
2974: 'Editing the Table of Contents for your '.$crstype,
2975: 'Docs_Adding_Course_Doc')
2976: );
2977: } else {
2978: $r->print(&Apache::loncommon::start_page("$crstype documents",undef,
2979: {'force_register' => $showdoc,}));
2980: }
2981:
2982: my %allfiles = ();
2983: my %codebase = ();
2984: my ($upload_result,$upload_output,$uploadphase);
2985: if ($allowed) {
2986: if (($env{'form.uploaddoc.filename'}) &&
2987: ($env{'form.cmd'}=~/^upload_(\w+)/)) {
2988: my $context = $1;
2989: # Process file upload - phase one - upload and parse primary file.
2990: undef($hadchanges);
2991: $uploadphase = &process_file_upload(\$upload_output,$coursenum,$coursedom,
2992: \%allfiles,\%codebase,$context);
2993: if ($hadchanges) {
2994: &mark_hash_old();
2995: }
2996: $r->print($upload_output);
2997: } elsif ($env{'form.phase'} eq 'upload_embedded') {
2998: # Process file upload - phase two - upload embedded objects
2999: $uploadphase = 'check_embedded';
3000: my $primaryurl = &HTML::Entities::encode($env{'form.primaryurl'},'<>&"');
3001: my $state = &embedded_form_elems($uploadphase,$primaryurl,
3002: $env{'form.newidx'});
3003: my $docuname=$env{'course.'.$env{'request.course.id'}.'.num'};
3004: my $docudom=$env{'course.'.$env{'request.course.id'}.'.domain'};
3005: my ($destination,$dir_root) = &embedded_destination();
3006: my $url_root = '/uploaded/'.$docudom.'/'.$docuname;
3007: my $actionurl = '/adm/coursedocs';
3008: my ($result,$flag) =
3009: &Apache::loncommon::upload_embedded('coursedoc',$destination,
3010: $docuname,$docudom,$dir_root,$url_root,undef,undef,undef,$state,
3011: $actionurl);
3012: $r->print($result.&return_to_editor());
3013: } elsif ($env{'form.phase'} eq 'check_embedded') {
3014: # Process file upload - phase three - modify references in HTML file
3015: $uploadphase = 'modified_orightml';
3016: my $docuname=$env{'course.'.$env{'request.course.id'}.'.num'};
3017: my $docudom=$env{'course.'.$env{'request.course.id'}.'.domain'};
3018: my ($destination,$dir_root) = &embedded_destination();
3019: $r->print(&Apache::loncommon::modify_html_refs('coursedoc',$destination,
3020: $docuname,$docudom,undef,
3021: $dir_root).
3022: &return_to_editor());
3023: }
3024: }
3025:
3026: unless ($showdoc || $uploadphase) {
3027: # -----------------------------------------------------------------------------
3028: my %lt=&Apache::lonlocal::texthash(
3029: 'uplm' => 'Upload a new main '.lc($crstype).' document',
3030: 'upls' => 'Upload a new supplemental '.lc($crstype).' document',
3031: 'impp' => 'Import a document',
3032: 'copm' => 'All documents out of a published map into this folder',
3033: 'upld' => 'Import Document',
3034: 'srch' => 'Search',
3035: 'impo' => 'Import',
3036: 'wish' => 'Import from Wishlist',
3037: 'selm' => 'Select Map',
3038: 'load' => 'Load Map',
3039: 'reco' => 'Recover Deleted Documents',
3040: 'newf' => 'New Folder',
3041: 'newp' => 'New Composite Page',
3042: 'extr' => 'External Resource',
3043: 'syll' => 'Syllabus',
3044: 'navc' => 'Table of Contents',
3045: 'sipa' => 'Simple Course Page',
3046: 'sipr' => 'Simple Problem',
3047: 'drbx' => 'Drop Box',
3048: 'scuf' => 'External Scores (handgrade, upload, clicker)',
3049: 'bull' => 'Discussion Board',
3050: 'mypi' => 'My Personal Information Page',
3051: 'grpo' => 'Group Portfolio',
3052: 'rost' => 'Course Roster',
3053: 'abou' => 'Personal Information Page for a User',
3054: 'imsf' => 'IMS Import',
3055: 'imsl' => 'Import IMS package',
3056: 'file' => 'File',
3057: 'title' => 'Title',
3058: 'comment' => 'Comment',
3059: 'parse' => 'Upload embedded images/multimedia files if HTML file',
3060: 'nd' => 'Upload Document',
3061: 'pm' => 'Published Map',
3062: 'sd' => 'Special Document',
3063: 'mo' => 'More Options',
3064: );
3065: # -----------------------------------------------------------------------------
3066: my $fileupload=(<<FIUP);
3067: $lt{'file'}:<br />
3068: <input type="file" name="uploaddoc" size="40" />
3069: FIUP
3070:
3071: my $checkbox=(<<CHBO);
3072: <!-- <label>$lt{'parse'}?
3073: <input type="checkbox" name="parserflag" />
3074: </label> -->
3075: <label>
3076: <input type="checkbox" name="parserflag" checked="checked" /> $lt{'parse'}
3077: </label>
3078: CHBO
3079:
3080: my $fileuploada = "<input type='submit' value='".$lt{'upld'}."' /> $help{'Uploading_From_Harddrive'}";
3081: my $fileuploadform=(<<FUFORM);
3082: <form name="uploaddocument" action="/adm/coursedocs" method="post" enctype="multipart/form-data">
3083: <input type="hidden" name="active" value="aa" />
3084: $fileupload
3085: <br />
3086: $lt{'title'}:<br />
3087: <input type="text" size="80" name="comment" />
3088: $uploadtag
3089: <input type="hidden" name="cmd" value="upload_default" />
3090: <br />
3091: <span class="LC_nobreak">
3092: $checkbox
3093: </span>
3094: FUFORM
3095: $fileuploadform .= &create_form_ul(&Apache::lonhtmlcommon::htmltag('li',$fileuploada,{class => 'LC_menubuttons_inline_text'})).'</form>';
3096:
3097: my $simpleeditdefaultform=(<<SEDFFORM);
3098: <form action="/adm/coursedocs" method="post" name="simpleeditdefault">
3099: <input type="hidden" name="active" value="bb" />
3100: SEDFFORM
3101: my @simpleeditdefaultforma = (
3102: { '<img class="LC_noBorder LC_middle" src="/res/adm/pages/src.png" alt="'.$lt{srch}.'" onclick="javascript:groupsearch()" />' => "$uploadtag<a class='LC_menubuttons_link' href='javascript:groupsearch()'>$lt{'srch'}</a>" },
3103: { '<img class="LC_noBorder LC_middle" src="/res/adm/pages/res.png" alt="'.$lt{impo}.'" onclick="javascript:groupimport();"/>' => "<a class='LC_menubuttons_link' href='javascript:groupimport();'>$lt{'impo'}</a>$help{'Importing_LON-CAPA_Resource'}" },
3104: { '<img class="LC_noBorder LC_middle" src="/res/adm/pages/wishlist.png" alt="'.$lt{wish}.'" onclick="javascript:open_Wishlist_Import();" />' => "<a class='LC_menubuttons_link' href='javascript:open_Wishlist_Import();'>$lt{'wish'}</a>" },
3105: );
3106: $simpleeditdefaultform .= &create_form_ul(&create_list_elements(@simpleeditdefaultforma));
3107: $simpleeditdefaultform .=(<<SEDFFORM);
3108: <hr />
3109: <p>
3110: $lt{'copm'}<br />
3111: <input type="text" size="40" name="importmap" /><br />
3112: <span class="LC_nobreak"><input type="button"
3113: onclick="javascript:openbrowser('simpleeditdefault','importmap','sequence,page','')"
3114: value="$lt{'selm'}" /> <input type="submit" name="loadmap" value="$lt{'load'}" />
3115: $help{'Load_Map'}</span>
3116: </p>
3117: </form>
3118: SEDFFORM
3119:
3120: my $extresourcesform=(<<ERFORM);
3121: <form action="/adm/coursedocs" method="post" name="newext">
3122: $uploadtag
3123: <input type="hidden" name="importdetail" value="" />
3124: <a class="LC_menubuttons_link" href="javascript:makenewext('newext');">$lt{'extr'}</a>$help{'Adding_External_Resource'}
3125: </form>
3126: ERFORM
3127:
3128:
3129: if ($allowed) {
3130: &update_paste_buffer($coursenum,$coursedom);
3131: my %lt=&Apache::lonlocal::texthash(
3132: 'vc' => 'Verify Content',
3133: 'cv' => 'Check/Set Resource Versions',
3134: 'ls' => 'List Symbs',
3135: 'sl' => 'Show Log'
3136: );
3137:
3138: $r->print(<<HIDDENFORM);
3139: <form name="renameform" method="post" action="/adm/coursedocs">
3140: <input type="hidden" name="title" />
3141: <input type="hidden" name="cmd" />
3142: <input type="hidden" name="markcopy" />
3143: <input type="hidden" name="copyfolder" />
3144: $containertag
3145: </form>
3146: <form name="simpleedit" method="post" action="/adm/coursedocs">
3147: <input type="hidden" name="importdetail" value="" />
3148: $uploadtag
3149: </form>
3150: HIDDENFORM
3151: }
3152:
3153: # Generate the tabs
3154: &startContentScreen($r,($supplementalflag?'supdocs':'docs'));
3155:
3156:
3157: #
3158:
3159: my $savefolderpath;
3160:
3161: if ($allowed) {
3162: my $folder=$env{'form.folder'};
3163: if ($folder eq '' || $supplementalflag) {
3164: $folder='default';
3165: $savefolderpath = $env{'form.folderpath'};
3166: $env{'form.folderpath'}='default&'.&escape(&mt('Content'));
3167: $uploadtag = '<input type="hidden" name="folderpath" value="'.
3168: &HTML::Entities::encode($env{'form.folderpath'},'<>&"').'" />';
3169: }
3170: my $postexec='';
3171: if ($folder eq 'default') {
3172: $r->print('<script type="text/javascript">'."\n"
3173: .'// <![CDATA['."\n"
3174: .'this.window.name="loncapaclient";'."\n"
3175: .'// ]]>'."\n"
3176: .'</script>'."\n"
3177: );
3178: } else {
3179: #$postexec='self.close();';
3180: }
3181: my $folderseq='/uploaded/'.$coursedom.'/'.$coursenum.'/default_'.time.
3182: '.sequence';
3183: my $pageseq = '/uploaded/'.$coursedom.'/'.$coursenum.'/default_'.time.
3184: '.page';
3185: my $container='sequence';
3186: if ($env{'form.pagepath'}) {
3187: $container='page';
3188: }
3189: my $readfile='/uploaded/'.$coursedom.'/'.$coursenum.'/'.$folder.'.'.$container;
3190:
3191:
3192:
3193: my $recoverform=(<<RFORM);
3194: <form action="/adm/groupsort" method="post" name="recover">
3195: <a class="LC_menubuttons_link" href="javascript:groupopen('$readfile',1)">$lt{'reco'}</a>
3196: </form>
3197: RFORM
3198:
3199: my $imspform=(<<IMSPFORM);
3200: <form action="/adm/imsimportdocs" method="post" name="ims">
3201: <input type="hidden" name="folder" value="$folder" />
3202: <a class="LC_menubuttons_link" href="javascript:makeims();">$lt{'imsf'}</a>
3203: </form>
3204: IMSPFORM
3205:
3206: my $newnavform=(<<NNFORM);
3207: <form action="/adm/coursedocs" method="post" name="newnav">
3208: <input type="hidden" name="active" value="cc" />
3209: $uploadtag
3210: <input type="hidden" name="importdetail"
3211: value="$lt{'navc'}=/adm/navmaps" />
3212: <a class="LC_menubuttons_link" href="javascript:document.newnav.submit()">$lt{'navc'}</a>
3213: $help{'Navigate_Content'}
3214: </form>
3215: NNFORM
3216: my $newsmppageform=(<<NSPFORM);
3217: <form action="/adm/coursedocs" method="post" name="newsmppg">
3218: <input type="hidden" name="active" value="cc" />
3219: $uploadtag
3220: <input type="hidden" name="importdetail" value="" />
3221: <a class="LC_menubuttons_link" href="javascript:makesmppage();"> $lt{'sipa'}</a>
3222: $help{'Simple Page'}
3223: </form>
3224: NSPFORM
3225:
3226: my $newsmpproblemform=(<<NSPROBFORM);
3227: <form action="/adm/coursedocs" method="post" name="newsmpproblem">
3228: <input type="hidden" name="active" value="cc" />
3229: $uploadtag
3230: <input type="hidden" name="importdetail" value="" />
3231: <a class="LC_menubuttons_link" href="javascript:makesmpproblem();">$lt{'sipr'}</a>
3232: $help{'Simple Problem'}
3233: </form>
3234:
3235: NSPROBFORM
3236:
3237: my $newdropboxform=(<<NDBFORM);
3238: <form action="/adm/coursedocs" method="post" name="newdropbox">
3239: <input type="hidden" name="active" value="cc" />
3240: $uploadtag
3241: <input type="hidden" name="importdetail" value="" />
3242: <a class="LC_menubuttons_link" href="javascript:makedropbox();">$lt{'drbx'}</a>
3243: </form>
3244: NDBFORM
3245:
3246: my $newexuploadform=(<<NEXUFORM);
3247: <form action="/adm/coursedocs" method="post" name="newexamupload">
3248: <input type="hidden" name="active" value="cc" />
3249: $uploadtag
3250: <input type="hidden" name="importdetail" value="" />
3251: <a class="LC_menubuttons_link" href="javascript:makeexamupload();">$lt{'scuf'}</a>
3252: $help{'Score_Upload_Form'}
3253: </form>
3254: NEXUFORM
3255:
3256: my $newbulform=(<<NBFORM);
3257: <form action="/adm/coursedocs" method="post" name="newbul">
3258: <input type="hidden" name="active" value="cc" />
3259: $uploadtag
3260: <input type="hidden" name="importdetail" value="" />
3261: <a class="LC_menubuttons_link" href="javascript:makebulboard();" >$lt{'bull'}</a>
3262: $help{'Bulletin Board'}
3263: </form>
3264: NBFORM
3265:
3266: my $newaboutmeform=(<<NAMFORM);
3267: <form action="/adm/coursedocs" method="post" name="newaboutme">
3268: <input type="hidden" name="active" value="cc" />
3269: $uploadtag
3270: <input type="hidden" name="importdetail"
3271: value="$plainname=/adm/$udom/$uname/aboutme" />
3272: <a class="LC_menubuttons_link" href="javascript:document.newaboutme.submit()">$lt{'mypi'}</a>
3273: $help{'My Personal Information Page'}
3274: </form>
3275: NAMFORM
3276:
3277: my $newaboutsomeoneform=(<<NASOFORM);
3278: <form action="/adm/coursedocs" method="post" name="newaboutsomeone">
3279: <input type="hidden" name="active" value="cc" />
3280: $uploadtag
3281: <input type="hidden" name="importdetail" value="" />
3282: <a class="LC_menubuttons_link" href="javascript:makeabout();">$lt{'abou'}</a>
3283: </form>
3284: NASOFORM
3285:
3286:
3287: my $newrosterform=(<<NROSTFORM);
3288: <form action="/adm/coursedocs" method="post" name="newroster">
3289: <input type="hidden" name="active" value="cc" />
3290: $uploadtag
3291: <input type="hidden" name="importdetail"
3292: value="$lt{'rost'}=/adm/viewclasslist" />
3293: <a class="LC_menubuttons_link" href="javascript:document.newroster.submit()">$lt{'rost'}</a>
3294: $help{'Course Roster'}
3295: </form>
3296: NROSTFORM
3297:
3298: my $specialdocumentsform;
3299: my @specialdocumentsforma;
3300: my $gradingform;
3301: my @gradingforma;
3302: my $communityform;
3303: my @communityforma;
3304: my $newfolderform;
3305: my $newfolderb;
3306:
3307: my $path = &HTML::Entities::encode($env{'form.folderpath'},'<>&"');
3308:
3309: my $newpageform=(<<NPFORM);
3310: <form action="/adm/coursedocs" method="post" name="newpage">
3311: <input type="hidden" name="folderpath" value="$path" />
3312: <input type="hidden" name="importdetail" value="" />
3313: <input type="hidden" name="active" value="cc" />
3314: <a class="LC_menubuttons_link" href="javascript:makenewpage(document.newpage,'$pageseq');">$lt{'newp'}</a>
3315: $help{'Adding_Pages'}
3316: </form>
3317: NPFORM
3318:
3319:
3320: $newfolderform=(<<NFFORM);
3321: <form action="/adm/coursedocs" method="post" name="newfolder">
3322: <input type="hidden" name="folderpath" value="$path" />
3323: <input type="hidden" name="importdetail" value="" />
3324: <input type="hidden" name="active" value="aa" />
3325: <a href="javascript:makenewfolder(document.newfolder,'$folderseq');">$lt{'newf'}</a>$help{'Adding_Folders'}
3326: </form>
3327: NFFORM
3328:
3329: my $newsylform=(<<NSYLFORM);
3330: <form action="/adm/coursedocs" method="post" name="newsyl">
3331: <input type="hidden" name="active" value="cc" />
3332: $uploadtag
3333: <input type="hidden" name="importdetail"
3334: value="$lt{'syll'}=/public/$coursedom/$coursenum/syllabus" />
3335: <a class="LC_menubuttons_link" href="javascript:document.newsyl.submit()">$lt{'syll'}</a>
3336: $help{'Syllabus'}
3337:
3338: </form>
3339: NSYLFORM
3340:
3341: my $newgroupfileform=(<<NGFFORM);
3342: <form action="/adm/coursedocs" method="post" name="newgroupfiles">
3343: <input type="hidden" name="active" value="cc" />
3344: $uploadtag
3345: <input type="hidden" name="importdetail"
3346: value="$lt{'grpo'}=/adm/$coursedom/$coursenum/aboutme" />
3347: <a class="LC_menubuttons_link" href="javascript:document.newgroupfiles.submit()">$lt{'grpo'}</a>
3348: $help{'Group Portfolio'}
3349: </form>
3350: NGFFORM
3351: @specialdocumentsforma=(
3352: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/page.png" alt="'.$lt{newp}.'" onclick="javascript:makenewpage(document.newpage,\''.$pageseq.'\');" />'=>$newpageform},
3353: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/syllabus.png" alt="'.$lt{syll}.'" onclick="document.newsyl.submit()" />'=>$newsylform},
3354: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/navigation.png" alt="'.$lt{navc}.'" onclick="document.newnav.submit()" />'=>$newnavform},
3355: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/simple.png" alt="'.$lt{sipa}.'" onclick="javascript:makesmppage();" />'=>$newsmppageform},
3356: );
3357: $specialdocumentsform = &create_form_ul(&create_list_elements(@specialdocumentsforma));
3358:
3359:
3360: my @importdoc = (
3361: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/extres.png" alt="'.$lt{extr}.'" onclick="javascript:makenewext(\'newext\');" />'=>$extresourcesform},
3362: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/ims.png" alt="'.$lt{imsf}.'" onclick="javascript:makeims();" />'=>$imspform},);
3363: $fileuploadform = &create_form_ul(&create_list_elements(@importdoc)) . '<hr/>' . $fileuploadform;
3364:
3365: @gradingforma=(
3366: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/simpprob.png" alt="'.$lt{sipr}.'" onclick="javascript:makesmpproblem();" />'=>$newsmpproblemform},
3367: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/dropbox.png" alt="'.$lt{drbx}.'" onclick="javascript:makedropbox();" />'=>$newdropboxform},
3368: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/scoreupfrm.png" alt="'.$lt{scuf}.'" onclick="javascript:makeexamupload();" />'=>$newexuploadform},
3369:
3370: );
3371: $gradingform = &create_form_ul(&create_list_elements(@gradingforma));
3372:
3373: @communityforma=(
3374: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/bchat.png" alt="'.$lt{bull}.'" onclick="javascript:makebulboard();" />'=>$newbulform},
3375: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/myaboutme.png" alt="'.$lt{mypi}.'" onclick="javascript:makebulboard();" />'=>$newaboutmeform},
3376: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/aboutme.png" alt="'.$lt{abou}.'" onclick="javascript:makeabout();" />'=>$newaboutsomeoneform},
3377: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/clst.png" alt="'.$lt{rost}.'" onclick="document.newroster.submit()" />'=>$newrosterform},
3378: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/groupportfolio.png" alt="'.$lt{grpo}.'" onclick="document.newgroupfiles.submit()" />'=>$newgroupfileform},
3379: );
3380: $communityform = &create_form_ul(&create_list_elements(@communityforma));
3381:
3382:
3383:
3384: my @tools = (
3385: # {'<img class="LC_noBorder LC_middle" align="left" src="/res/adm/pages/extres.png" alt="'.$lt{extr}.'" />'=>$extresourcesform},
3386: # {'<img class="LC_noBorder LC_middle" align="left" src="/res/adm/pages/ims.png" alt="'.$lt{imsf}.'" />'=>$imspform},
3387: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/recover.png" alt="'.$lt{reco}.'" onclick="javascript:groupopen(\''.$readfile.'\',1)" />'=>$recoverform},
3388: );
3389:
3390: my %orderhash = (
3391: 'aa' => ['Import Documents',$fileuploadform],
3392: 'bb' => ['Published Resources',$simpleeditdefaultform],
3393: 'cc' => ['Grading Resources',$gradingform],
3394: 'ff' => ['Tools', &create_form_ul(&create_list_elements(@tools)).&generate_admin_options(\%help,\%env)],
3395: );
3396: unless ($env{'form.pagepath'}) {
3397: $orderhash{'00'} = ['Newfolder',$newfolderform];
3398: $orderhash{'dd'} = ['Community Resources',$communityform];
3399: $orderhash{'ee'} = ['Special Documents',$specialdocumentsform];
3400: }
3401:
3402: $hadchanges=0;
3403: unless ($supplementalflag) {
3404: my $error = &editor($r,$coursenum,$coursedom,$folder,$allowed,'',$crstype);
3405: if ($error) {
3406: $r->print('<p><span class="LC_error">'.$error.'</span></p>');
3407: }
3408: if ($hadchanges) {
3409: &mark_hash_old();
3410: }
3411:
3412: &changewarning($r,'');
3413: $r->print(&generate_edit_table('1',\%orderhash));
3414: }
3415:
3416: }
3417:
3418: # Supplemental documents start here
3419:
3420: my $folder=$env{'form.folder'};
3421: unless ($supplementalflag) {
3422: $folder='supplemental';
3423: }
3424: if ($folder =~ /^supplemental$/ &&
3425: (($env{'form.folderpath'} =~ /^default\&/) || ($env{'form.folderpath'} eq ''))) {
3426: $env{'form.folderpath'} = &supplemental_base();
3427: } elsif ($allowed) {
3428: $env{'form.folderpath'} = $savefolderpath;
3429: }
3430: $env{'form.pagepath'} = '';
3431: if ($allowed) {
3432: my $folderseq=
3433: '/uploaded/'.$coursedom.'/'.$coursenum.'/supplemental_'.time.
3434: '.sequence';
3435:
3436: my $path = &HTML::Entities::encode($env{'form.folderpath'},'<>&"');
3437:
3438: my $supupdocformbtn = "<input type='submit' value='".$lt{'upld'}."' />$help{'Uploading_From_Harddrive'}";
3439: my $supupdocform=(<<SUPDOCFORM);
3440: <form action="/adm/coursedocs" method="post" name="supuploaddocument" enctype="multipart/form-data">
3441: <input type="hidden" name="active" value="ee" />
3442: $fileupload
3443: <br />
3444: <br />
3445: <span class="LC_nobreak">
3446: $checkbox
3447: </span>
3448: <br /><br />
3449: $lt{'comment'}:<br />
3450: <textarea cols="50" rows="4" name="comment"></textarea>
3451: <br />
3452: <input type="hidden" name="folderpath" value="$path" />
3453: <input type="hidden" name="cmd" value="upload_supplemental" />
3454: SUPDOCFORM
3455: $supupdocform .= &create_form_ul(&Apache::lonhtmlcommon::htmltag('li',$supupdocformbtn,{class => 'LC_menubuttons_inline_text'}))."</form>";
3456:
3457: my $supnewfolderform=(<<SNFFORM);
3458: <form action="/adm/coursedocs" method="post" name="supnewfolder">
3459: <input type="hidden" name="active" value="ee" />
3460: <input type="hidden" name="folderpath" value="$path" />
3461: <input type="hidden" name="importdetail" value="" />
3462: <a class="LC_menubuttons_link" href="javascript:makenewfolder(document.supnewfolder,'$folderseq');">$lt{'newf'}</a>
3463: $help{'Adding_Folders'}
3464: </form>
3465: SNFFORM
3466:
3467:
3468: my $supnewextform=(<<SNEFORM);
3469: <form action="/adm/coursedocs" method="post" name="supnewext">
3470: <input type="hidden" name="active" value="ff" />
3471: <input type="hidden" name="folderpath" value="$path" />
3472: <input type="hidden" name="importdetail" value="" />
3473: <a class="LC_menubuttons_link" href="javascript:makenewext('supnewext');">$lt{'extr'}</a> $help{'Adding_External_Resource'}
3474: </form>
3475: SNEFORM
3476:
3477: my $supnewsylform=(<<SNSFORM);
3478: <form action="/adm/coursedocs" method="post" name="supnewsyl">
3479: <input type="hidden" name="active" value="ff" />
3480: <input type="hidden" name="folderpath" value="$path" />
3481: <input type="hidden" name="importdetail"
3482: value="Syllabus=/public/$coursedom/$coursenum/syllabus" />
3483: <a class="LC_menubuttons_link" href="javascript:document.supnewsyl.submit()">$lt{'syll'}</a>
3484: $help{'Syllabus'}
3485: </form>
3486: SNSFORM
3487:
3488: my $supnewaboutmeform=(<<SNAMFORM);
3489: <form action="/adm/coursedocs" method="post" name="supnewaboutme">
3490: <input type="hidden" name="active" value="ff" />
3491: <input type="hidden" name="folderpath" value="$path" />
3492: <input type="hidden" name="importdetail"
3493: value="$plainname=/adm/$udom/$uname/aboutme" />
3494: <a class="LC_menubuttons_link" href="javascript:document.supnewaboutme.submit()">$lt{'mypi'}</a>
3495: $help{'My Personal Information Page'}
3496: </form>
3497: SNAMFORM
3498:
3499:
3500: my @specialdocs = (
3501: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/syllabus.png" alt="'.$lt{syll}.'" onclick="document.supnewsyl.submit()" />'
3502: =>$supnewsylform},
3503: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/myaboutme.png" alt="'.$lt{mypi}.'" onclick="document.supnewaboutme.submit()" />'
3504: =>$supnewaboutmeform},
3505: );
3506: my @supimportdoc = (
3507: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/extres.png" alt="'.$lt{extr}.'" onclick="javascript:makenewext(\'supnewext\');" />'
3508: =>$supnewextform},
3509: );
3510: $supupdocform = &create_form_ul(&create_list_elements(@supimportdoc)) . '<hr/>' . $supupdocform;
3511: my %suporderhash = (
3512: '00' => ['Supnewfolder', $supnewfolderform],
3513: 'ee' => ['Import Documents',$supupdocform],
3514: 'ff' => ['Special Documents',&create_form_ul(&create_list_elements(@specialdocs))]
3515: );
3516: if ($supplementalflag) {
3517: my $error = &editor($r,$coursenum,$coursedom,$folder,$allowed,'',$crstype);
3518: if ($error) {
3519: $r->print('<p><span class="LC_error">'.$error.'</span></p>');
3520: }
3521: $r->print(&generate_edit_table('2',\%suporderhash));
3522: }
3523: } elsif ($supplementalflag) {
3524: my $error = &editor($r,$coursenum,$coursedom,$folder,$allowed,'',$crstype);
3525: if ($error) {
3526: $r->print('<p><span class="LC_error">'.$error.'</span></p>');
3527: }
3528: }
3529:
3530: &endContentScreen($r);
3531:
3532: if ($allowed) {
3533: $r->print('
3534: <form method="post" name="extimport" action="/adm/coursedocs">
3535: <input type="hidden" name="title" />
3536: <input type="hidden" name="url" />
3537: <input type="hidden" name="useform" />
3538: <input type="hidden" name="residx" />
3539: </form>');
3540: }
3541: } else {
3542: unless ($uploadphase) {
3543: # -------------------------------------------------------- This is showdoc mode
3544: $r->print("<h1>".&mt('Uploaded Document').' - '.
3545: &Apache::lonnet::gettitle($r->uri).'</h1><p>'.
3546: &mt('It is recommended that you use an up-to-date virus scanner before handling this file.')."</p><table>".
3547: &entryline(0,&mt("Click to download or use your browser's Save Link function"),$showdoc).'</table>');
3548: }
3549: }
3550: }
3551: $r->print(&Apache::loncommon::end_page());
3552: return OK;
3553: }
3554:
3555: sub embedded_form_elems {
3556: my ($phase,$primaryurl,$newidx) = @_;
3557: my $folderpath = &HTML::Entities::encode($env{'form.folderpath'},'<>&"');
3558: return <<STATE;
3559: <input type="hidden" name="folderpath" value="$folderpath" />
3560: <input type="hidden" name="cmd" value="upload_embedded" />
3561: <input type="hidden" name="newidx" value="$newidx" />
3562: <input type="hidden" name="phase" value="$phase" />
3563: <input type="hidden" name="primaryurl" value="$primaryurl" />
3564: STATE
3565: }
3566:
3567: sub embedded_destination {
3568: my $folder=$env{'form.folder'};
3569: my $destination = 'docs/';
3570: if ($folder =~ /^supplemental/) {
3571: $destination = 'supplemental/';
3572: }
3573: if (($folder eq 'default') || ($folder eq 'supplemental')) {
3574: $destination .= 'default/';
3575: } elsif ($folder =~ /^(default|supplemental)_(\d+)$/) {
3576: $destination .= $2.'/';
3577: }
3578: $destination .= $env{'form.newidx'};
3579: my $dir_root = '/userfiles';
3580: return ($destination,$dir_root);
3581: }
3582:
3583: sub return_to_editor {
3584: my $actionurl = '/adm/coursedocs';
3585: return '<p><form name="backtoeditor" method="post" action="'.$actionurl.'" />'."\n".
3586: '<input type="hidden" name="folderpath" value="'.&HTML::Entities::encode($env{'form.folderpath'},'<>&"').'" /></form>'."\n".
3587: '<a href="javascript:document.backtoeditor.submit();">'.&mt('Return to Editor').
3588: '</a></p>';
3589: }
3590:
3591: sub generate_admin_options {
3592: my ($help_ref,$env_ref) = @_;
3593: my %lt=&Apache::lonlocal::texthash(
3594: 'vc' => 'Verify Content',
3595: 'cv' => 'Check/Set Resource Versions',
3596: 'ls' => 'List Symbs',
3597: 'sl' => 'Show Log',
3598: 'imse' => 'IMS Export',
3599: 'dcd' => 'Dump Course Documents to Construction Space: available on other servers'
3600: );
3601: my %help = %{$help_ref};
3602: my %env = %{$env_ref};
3603: my $dumpbut=&dumpbutton();
3604: my $exportbut=&exportbutton();
3605: my @list = (
3606: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/verify.png" alt="'.$lt{vc}.'" onclick=\'javascript:injectData(document.courseverify, "dummy", "verify", "'.$lt{'vc'}.'")\' />'
3607: => "<a class='LC_menubuttons_link' href='javascript:injectData(document.courseverify, \"dummy\", \"verify\", \"$lt{'vc'}\")'>$lt{'vc'}</a>$help{'Verify_Content'}"},
3608: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/resversion.png" alt="'.$lt{cv}.'" onclick=\'javascript:injectData(document.courseverify, "dummy", "versions", "'.$lt{'cv'}.'")\' />'
3609: =>"<a class='LC_menubuttons_link' href='javascript:injectData(document.courseverify, \"dummy\", \"versions\", \"$lt{'cv'}\")'>$lt{'cv'}</a>$help{'Check_Resource_Versions'}"},
3610: );
3611: if($dumpbut ne ''){
3612: push @list, {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/dump.png" alt="'.$lt{dcd}.'" />'=>$dumpbut};
3613: }
3614: push @list, ({'<img class="LC_noBorder LC_middle" src="/res/adm/pages/imsexport.png" alt="'.$lt{imse}.'" onclick="javascript:injectData(document.courseverify, \'dummy\', \'exportcourse\', \''.&mt('IMS Export').'\');" />'
3615: =>$exportbut},
3616: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/symbs.png" alt="'.$lt{ls}.'" onclick=\'javascript:injectData(document.courseverify, "dummy", "listsymbs", "'.$lt{'ls'}.'")\' />'
3617: =>"<a class='LC_menubuttons_link' href='javascript:injectData(document.courseverify, \"dummy\", \"listsymbs\", \"$lt{'ls'}\")'>$lt{'ls'}</a><input type='hidden' name='folder' value='$env{'form.folder'}' />"},
3618: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/document-properties.png" alt="'.$lt{sl}.'" onclick=\'javascript:injectData(document.courseverify, "dummy", "docslog", "'.$lt{'sl'}.'")\' />'
3619: =>"<a class='LC_menubuttons_link' href='javascript:injectData(document.courseverify, \"dummy\", \"docslog\", \"$lt{'sl'}\")'>$lt{'sl'}</a>"},
3620: );
3621: return '<form action="/adm/coursedocs" method="post" name="courseverify"><input type="hidden" id="dummy" />'.&create_form_ul(&create_list_elements(@list)).'</form>';
3622:
3623: }
3624:
3625:
3626: sub generate_edit_table {
3627: my ($tid,$orderhash_ref) = @_;
3628: return unless(ref($orderhash_ref) eq 'HASH');
3629: my %orderhash = %{$orderhash_ref};
3630: my $form;
3631: my $activetab;
3632: my $active;
3633: if($env{'form.active'} ne ''){
3634: $activetab = $env{'form.active'};
3635: }
3636: $form = '<div class="LC_Box" style="margin-right:0">';
3637: $form .= '<ul id="navigation'.$tid.'" class="LC_TabContent">';
3638: foreach my $name (sort(keys(%orderhash))){
3639: if($name ne '00'){
3640: if($activetab eq '' || $activetab ne $name){
3641: $active = '';
3642: }elsif($activetab eq $name){
3643: $active = 'class="active"';
3644: }
3645: $form .= '<li '.$active
3646: .' onmouseover="javascript:showPage(this, \''.$name.$tid.'\', \'navigation'.$tid.'\',\'content'.$tid.'\');"'
3647: .' onclick="javascript:showPage(this, \''.$name.$tid.'\', \'navigation'.$tid.'\',\'content'.$tid.'\');"><a href="javascript:;"><b>'.&mt(${$orderhash{$name}}[0]).'</b></a></li>';
3648: } else {
3649: $form .= '<li '.$active.'>'.${$orderhash{$name}}[1].'</li>';
3650:
3651: }
3652: }
3653: $form .= '</ul>';
3654: $form .= '<div id="content'.$tid.'" style="padding: 0 0; margin: 0 0; clear: both;">';
3655: foreach my $field (keys(%orderhash)){
3656: if($field ne '00'){
3657: if($activetab eq '' || $activetab ne $field){
3658: $active = 'style="display: none;"';
3659: }elsif($activetab eq $field){
3660: $active = 'style="display:block;"';
3661: }
3662: $form .= '<div id="'.$field.$tid.'"'
3663: .' class="LC_ContentBox" '.$active.'>'.${$orderhash{$field}}[1]
3664: .'</div>';
3665: }
3666: }
3667: $form .= '</div></div>';
3668:
3669: return $form;
3670: }
3671:
3672: sub editing_js {
3673: my ($udom,$uname) = @_;
3674: my $now = time();
3675: my %lt = &Apache::lonlocal::texthash(
3676: p_mnf => 'Name of New Folder',
3677: t_mnf => 'New Folder',
3678: p_mnp => 'Name of New Page',
3679: t_mnp => 'New Page',
3680: p_mxu => 'Title for the External Score',
3681: p_msp => 'Name of Simple Course Page',
3682: p_msb => 'Title for the Problem',
3683: p_mdb => 'Title for the Drop Box',
3684: p_mbb => 'Title for the Discussion Board',
3685: p_mab => "Enter user:domain for User's Personal Information Page",
3686: p_mab2 => 'Personal Information Page of ',
3687: p_mab_alrt1 => 'Not a valid user:domain',
3688: p_mab_alrt2 => 'Please enter both user and domain in the format user:domain',
3689: p_chn => 'New Title',
3690: p_rmr1 => 'WARNING: Removing a resource makes associated grades and scores inaccessible!',
3691: p_rmr2a => 'Remove[_99]',
3692: p_rmr2b => '?[_99]',
3693: p_ctr1a => 'WARNING: Cutting a resource makes associated grades and scores inaccessible!',
3694: p_ctr1b => 'Grades remain inaccessible if resource is pasted into another folder.',
3695: p_ctr2a => 'Cut[_98]',
3696: p_ctr2b => '?[_98]'
3697: );
3698:
3699: my $crstype = &Apache::loncommon::course_type();
3700: my $docs_folderpath = &HTML::Entities::encode($env{'environment.internal.'.$env{'request.course.id'}.'.docs_folderpath.folderpath'},'<>&"');
3701: my $docs_pagepath = &HTML::Entities::encode($env{'environment.internal.'.$env{'request.course.id'}.'.docs_folderpath.pagepath'},'<>&"');
3702: my $main_container_page;
3703: if ($docs_folderpath eq '') {
3704: if ($docs_pagepath ne '') {
3705: $main_container_page = 1;
3706: }
3707: }
3708: my $toplevelmain = 'default&Main%20'.$crstype.'%20Documents';
3709: my $toplevelsupp = &supplemental_base();
3710:
3711: return <<ENDNEWSCRIPT;
3712: function makenewfolder(targetform,folderseq) {
3713: var foldername=prompt('$lt{"p_mnf"}','$lt{"t_mnf"}');
3714: if (foldername) {
3715: targetform.importdetail.value=escape(foldername)+"="+folderseq;
3716: targetform.submit();
3717: }
3718: }
3719:
3720: function makenewpage(targetform,folderseq) {
3721: var pagename=prompt('$lt{"p_mnp"}','$lt{"t_mnp"}');
3722: if (pagename) {
3723: targetform.importdetail.value=escape(pagename)+"="+folderseq;
3724: targetform.submit();
3725: }
3726: }
3727:
3728: function makenewext(targetname) {
3729: this.document.forms.extimport.useform.value=targetname;
3730: this.document.forms.extimport.title.value='';
3731: this.document.forms.extimport.url.value='';
3732: this.document.forms.extimport.residx.value='';
3733: window.open('/adm/rat/extpickframe.html');
3734: }
3735:
3736: function edittext(targetname,residx,title,url) {
3737: this.document.forms.extimport.useform.value=targetname;
3738: this.document.forms.extimport.residx.value=residx;
3739: this.document.forms.extimport.url.value=url;
3740: this.document.forms.extimport.title.value=title;
3741: window.open('/adm/rat/extpickframe.html');
3742: }
3743:
3744: function makeexamupload() {
3745: var title=prompt('$lt{"p_mxu"}');
3746: if (title) {
3747: this.document.forms.newexamupload.importdetail.value=
3748: escape(title)+'=/res/lib/templates/examupload.problem';
3749: this.document.forms.newexamupload.submit();
3750: }
3751: }
3752:
3753: function makesmppage() {
3754: var title=prompt('$lt{"p_msp"}');
3755: if (title) {
3756: this.document.forms.newsmppg.importdetail.value=
3757: escape(title)+'=/adm/$udom/$uname/$now/smppg';
3758: this.document.forms.newsmppg.submit();
3759: }
3760: }
3761:
3762: function makesmpproblem() {
3763: var title=prompt('$lt{"p_msb"}');
3764: if (title) {
3765: this.document.forms.newsmpproblem.importdetail.value=
3766: escape(title)+'=/res/lib/templates/simpleproblem.problem';
3767: this.document.forms.newsmpproblem.submit();
3768: }
3769: }
3770:
3771: function makedropbox() {
3772: var title=prompt('$lt{"p_mdb"}');
3773: if (title) {
3774: this.document.forms.newdropbox.importdetail.value=
3775: escape(title)+'=/res/lib/templates/DropBox.problem';
3776: this.document.forms.newdropbox.submit();
3777: }
3778: }
3779:
3780: function makebulboard() {
3781: var title=prompt('$lt{"p_mbb"}');
3782: if (title) {
3783: this.document.forms.newbul.importdetail.value=
3784: escape(title)+'=/adm/$udom/$uname/$now/bulletinboard';
3785: this.document.forms.newbul.submit();
3786: }
3787: }
3788:
3789: function makeabout() {
3790: var user=prompt("$lt{'p_mab'}");
3791: if (user) {
3792: var comp=new Array();
3793: comp=user.split(':');
3794: if ((typeof(comp[0])!=undefined) && (typeof(comp[1])!=undefined)) {
3795: if ((comp[0]) && (comp[1])) {
3796: this.document.forms.newaboutsomeone.importdetail.value=
3797: '$lt{"p_mab2"}'+escape(user)+'=/adm/'+comp[1]+'/'+comp[0]+'/aboutme';
3798: this.document.forms.newaboutsomeone.submit();
3799: } else {
3800: alert("$lt{'p_mab_alrt1'}");
3801: }
3802: } else {
3803: alert("$lt{'p_mab_alrt2'}");
3804: }
3805: }
3806: }
3807:
3808: function makeims() {
3809: var caller = document.forms.ims.folder.value;
3810: var newlocation = "/adm/imsimportdocs?folder="+caller+"&phase=one";
3811: newWindow = window.open("","IMSimport","HEIGHT=700,WIDTH=750,scrollbars=yes");
3812: newWindow.location.href = newlocation;
3813: }
3814:
3815:
3816: function finishpick() {
3817: var title=this.document.forms.extimport.title.value;
3818: var url=this.document.forms.extimport.url.value;
3819: var form=this.document.forms.extimport.useform.value;
3820: var residx=this.document.forms.extimport.residx.value;
3821: eval('this.document.forms.'+form+'.importdetail.value="'+title+'='+url+'='+residx+'";this.document.forms.'+form+'.submit();');
3822: }
3823:
3824: function changename(folderpath,index,oldtitle,container,pagesymb) {
3825: var title=prompt('$lt{"p_chn"}',oldtitle);
3826: if (title) {
3827: this.document.forms.renameform.markcopy.value=-1;
3828: this.document.forms.renameform.title.value=title;
3829: this.document.forms.renameform.cmd.value='rename_'+index;
3830: if (container == 'sequence') {
3831: this.document.forms.renameform.folderpath.value=folderpath;
3832: }
3833: if (container == 'page') {
3834: this.document.forms.renameform.pagepath.value=folderpath;
3835: this.document.forms.renameform.pagesymb.value=pagesymb;
3836: }
3837: this.document.forms.renameform.submit();
3838: }
3839: }
3840:
3841: function removeres(folderpath,index,oldtitle,container,pagesymb,skip_confirm) {
3842: if (skip_confirm || confirm('$lt{"p_rmr1"}\\n\\n$lt{"p_rmr2a"} "'+oldtitle+'" $lt{"p_rmr2b"}')) {
3843: this.document.forms.renameform.markcopy.value=-1;
3844: this.document.forms.renameform.cmd.value='del_'+index;
3845: if (container == 'sequence') {
3846: this.document.forms.renameform.folderpath.value=folderpath;
3847: }
3848: if (container == 'page') {
3849: this.document.forms.renameform.pagepath.value=folderpath;
3850: this.document.forms.renameform.pagesymb.value=pagesymb;
3851: }
3852: this.document.forms.renameform.submit();
3853: }
3854: }
3855:
3856: function cutres(folderpath,index,oldtitle,container,pagesymb,folder,skip_confirm) {
3857: if (skip_confirm || confirm('$lt{"p_ctr1a"}\\n$lt{"p_ctr1b"}\\n\\n$lt{"p_ctr2a"} "'+oldtitle+'" $lt{"p_ctr2b"}')) {
3858: this.document.forms.renameform.cmd.value='cut_'+index;
3859: this.document.forms.renameform.markcopy.value=index;
3860: this.document.forms.renameform.copyfolder.value=folder+'.'+container;
3861: if (container == 'sequence') {
3862: this.document.forms.renameform.folderpath.value=folderpath;
3863: }
3864: if (container == 'page') {
3865: this.document.forms.renameform.pagepath.value=folderpath;
3866: this.document.forms.renameform.pagesymb.value=pagesymb;
3867: }
3868: this.document.forms.renameform.submit();
3869: }
3870: }
3871:
3872: function markcopy(folderpath,index,oldtitle,container,pagesymb,folder) {
3873: this.document.forms.renameform.markcopy.value=index;
3874: this.document.forms.renameform.copyfolder.value=folder+'.'+container;
3875: if (container == 'sequence') {
3876: this.document.forms.renameform.folderpath.value=folderpath;
3877: }
3878: if (container == 'page') {
3879: this.document.forms.renameform.pagepath.value=folderpath;
3880: this.document.forms.renameform.pagesymb.value=pagesymb;
3881: }
3882: this.document.forms.renameform.submit();
3883: }
3884:
3885: function unselectInactive(nav) {
3886: currentNav = document.getElementById(nav);
3887: currentLis = currentNav.getElementsByTagName('LI');
3888: for (i = 0; i < currentLis.length; i++) {
3889: if(currentLis[i].className == 'right active' || currentLis[i].className == 'right'){
3890: currentLis[i].className = 'right';
3891: }else{
3892: currentLis[i].className = 'i';
3893: }
3894: }
3895: }
3896:
3897: function hideAll(current, nav, data) {
3898: unselectInactive(nav);
3899: if(current.className == 'right'){
3900: current.className = 'right active'
3901: }else{
3902: current.className = 'active';
3903: }
3904: currentData = document.getElementById(data);
3905: currentDivs = currentData.getElementsByTagName('DIV');
3906: for (i = 0; i < currentDivs.length; i++) {
3907: if(currentDivs[i].className == 'LC_ContentBox'){
3908: currentDivs[i].style.display = 'none';
3909: }
3910: }
3911: }
3912:
3913: function openTabs(pageId) {
3914: tabnav = document.getElementById(pageId).getElementsByTagName('UL');
3915: if(tabnav.length > 2 ){
3916: currentNav = document.getElementById(tabnav[1].id);
3917: currentLis = currentNav.getElementsByTagName('LI');
3918: for(i = 0; i< currentLis.length; i++){
3919: if(currentLis[i].className == 'active') {
3920: funcString = currentLis[i].onclick.toString();
3921: tab = funcString.split('"');
3922: if(tab.length < 2) {
3923: tab = funcString.split("'");
3924: }
3925: currentData = document.getElementById(tab[1]);
3926: currentData.style.display = 'block';
3927: }
3928: }
3929: }
3930: }
3931:
3932: function showPage(current, pageId, nav, data) {
3933: hideAll(current, nav, data);
3934: openTabs(pageId);
3935: unselectInactive(nav);
3936: current.className = 'active';
3937: currentData = document.getElementById(pageId);
3938: currentData.style.display = 'block';
3939: if (nav == 'mainnav') {
3940: var storedpath = "$docs_folderpath";
3941: if (storedpath == '') {
3942: storedpath = "$docs_pagepath";
3943: }
3944: var storedpage = "$main_container_page";
3945: var reg = new RegExp("^supplemental");
3946: if (pageId == 'mainCourseDocuments') {
3947: if (storedpage == 1) {
3948: document.simpleedit.folderpath.value = '';
3949: document.uploaddocument.folderpath.value = '';
3950: } else {
3951: if (reg.test(storedpath)) {
3952: document.simpleedit.folderpath.value = '$toplevelmain';
3953: document.uploaddocument.folderpath.value = '$toplevelmain';
3954: document.newext.folderpath.value = '$toplevelmain';
3955: } else {
3956: document.simpleedit.folderpath.value = storedpath;
3957: document.uploaddocument.folderpath.value = storedpath;
3958: document.newext.folderpath.value = storedpath;
3959: }
3960: }
3961: } else {
3962: if (reg.test(storedpath)) {
3963: document.simpleedit.folderpath.value = storedpath;
3964: document.supuploaddocument.folderpath.value = storedpath;
3965: document.supnewext.folderpath.value = storedpath;
3966: } else {
3967: document.simpleedit.folderpath.value = '$toplevelsupp';
3968: document.supuploaddocument.folderpath.value = '$toplevelsupp';
3969: document.supnewext.folderpath.value = '$toplevelsupp';
3970: }
3971: }
3972: }
3973: return false;
3974: }
3975:
3976: function injectData(current, hiddenField, name, value) {
3977: currentElement = document.getElementById(hiddenField);
3978: currentElement.name = name;
3979: currentElement.value = value;
3980: current.submit();
3981: }
3982:
3983: ENDNEWSCRIPT
3984: }
3985: 1;
3986: __END__
3987:
3988:
3989: =head1 NAME
3990:
3991: Apache::londocs.pm
3992:
3993: =head1 SYNOPSIS
3994:
3995: This is part of the LearningOnline Network with CAPA project
3996: described at http://www.lon-capa.org.
3997:
3998: =head1 SUBROUTINES
3999:
4000: =over
4001:
4002: =item %help=()
4003:
4004: Available help topics
4005:
4006: =item mapread()
4007:
4008: Mapread read maps into LONCAPA::map:: global arrays
4009: @order and @resources, determines status
4010: sets @order - pointer to resources in right order
4011: sets @resources - array with the resources with correct idx
4012:
4013: =item authorhosts()
4014:
4015: Return hash with valid author names
4016:
4017: =item dumpbutton()
4018:
4019: Generate "dump" button
4020:
4021: =item clean()
4022:
4023: =item dumpcourse()
4024:
4025: Actually dump course
4026:
4027:
4028: =item exportbutton()
4029:
4030: Generate "export" button
4031:
4032: =item exportcourse()
4033:
4034: =item create_ims_store()
4035:
4036: =item build_package()
4037:
4038: =item get_dependencies()
4039:
4040: =item process_content()
4041:
4042: =item replicate_content()
4043:
4044: =item extract_media()
4045:
4046: =item store_template()
4047:
4048: =item group_import()
4049:
4050: Imports the given (name, url) resources into the course
4051: coursenum, coursedom, and folder must precede the list
4052:
4053: =item breadcrumbs()
4054:
4055: =item log_docs()
4056:
4057: =item docs_change_log()
4058:
4059: =item update_paste_buffer()
4060:
4061: =item print_paste_buffer()
4062:
4063: =item do_paste_from_buffer()
4064:
4065: =item update_parameter()
4066:
4067: =item handle_edit_cmd()
4068:
4069: =item editor()
4070:
4071: =item process_file_upload()
4072:
4073: =item process_secondary_uploads()
4074:
4075: =item is_supplemental_title()
4076:
4077: =item parse_supplemental_title()
4078:
4079: =item entryline()
4080:
4081: =item tiehash()
4082:
4083: =item untiehash()
4084:
4085: =item checkonthis()
4086:
4087: check on this
4088:
4089: =item verifycontent()
4090:
4091: Verify Content
4092:
4093: =item devalidateversioncache() & checkversions()
4094:
4095: Check Versions
4096:
4097: =item mark_hash_old()
4098:
4099: =item is_hash_old()
4100:
4101: =item changewarning()
4102:
4103: =item init_breadcrumbs()
4104:
4105: Breadcrumbs for special functions
4106:
4107: =back
4108:
4109: =cut
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>