Annotation of loncom/interface/lonsyllabus.pm, revision 1.124
1.1 www 1: # The LearningOnline Network
2: # Syllabus
3: #
1.124 ! raeburn 4: # $Id: lonsyllabus.pm,v 1.123 2013/05/14 14:30:15 raeburn Exp $
1.1 www 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: package Apache::lonsyllabus;
30:
31: use strict;
1.70 amueller 32: use Apache::lontemplate;
1.1 www 33: use Apache::Constants qw(:common);
34: use Apache::loncommon;
35: use Apache::lonnet;
1.5 www 36: use Apache::lontexconvert;
1.11 www 37: use Apache::lonfeedback;
1.19 www 38: use Apache::lonannounce;
1.23 www 39: use Apache::lonlocal;
1.32 www 40: use Apache::lonhtmlcommon;
1.38 www 41: use Apache::lonspeller();
1.54 albertel 42: use HTML::Entities();
1.1 www 43:
44: sub handler {
45: my $r = shift;
1.46 www 46: &Apache::loncommon::content_type($r,'text/html');
47: $r->send_http_header;
48: return OK if $r->header_only;
1.45 www 49:
1.46 www 50: my $target=$env{'form.grade_target'};
1.45 www 51: # --------------------------------------------------- Get course info from URL
52: my (undef,undef,$cdom,$cnum)=split(/\//,$r->uri);
1.46 www 53: # ------------------------------------------------------------ Get query string
54: &Apache::loncommon::get_unprocessed_cgi
1.116 raeburn 55: ($ENV{'QUERY_STRING'},['register','forceedit','todocs',
1.115 raeburn 56: 'folderpath','title']);
1.45 www 57: # ----------------------------------------------------- Is this even a course?
58: my $homeserver=&Apache::lonnet::homeserver($cnum,$cdom);
59: if ($homeserver eq 'no_host') {
60: &Apache::loncommon::content_type($r,'text/html');
61: $r->send_http_header;
1.106 faziophi 62: &Apache::loncommon::simple_error_page($r,'No syllabus available',
1.91 amueller 63: 'No syllabus available');
1.45 www 64: return OK;
1.113 raeburn 65: } elsif (!&Apache::lonnet::is_course($cdom,$cnum)) {
66: &Apache::loncommon::content_type($r,'text/html');
67: $r->send_http_header;
68: &Apache::loncommon::simple_error_page($r,'No syllabus available',
69: 'The course/community for which the syllabus was requested does not exist.');
70: return OK;
1.45 www 71: }
72: # ------------------------------------- There is such a course, get environment
73: my %courseenv=&Apache::lonnet::dump('environment',$cdom,$cnum);
1.46 www 74:
1.1 www 75: # ------------------------------------------------------------ Print the screen
1.49 albertel 76:
77: if ($target eq 'tex') {
1.91 amueller 78: $r->print(&Apache::lonprintout::print_latex_header($env{'form.latex_type'}));
1.86 bisitz 79: }
1.117 raeburn 80:
81: # --------------------------------------------------------------- Force Student
82: my ($forceedit,$forcestudent);
83: if ($env{'form.forceedit'}) { $forceedit=1; }
84: if (!$forceedit) {
85: $forcestudent=1;
86: }
87:
88: # --------------------------------------------------------------- Check Privileges
89: my $allowed = 0;
90: if ($env{'user.environment'}) {
91: # does this user have privileges to post, etc?
92: if ($env{'request.course.id'}
93: && $cdom eq $env{'course.'.$env{'request.course.id'}.'.domain'}
94: && $cnum eq $env{'course.'.$env{'request.course.id'}.'.num'}) {
95: $allowed=&Apache::lonnet::allowed('mdc',$env{'request.course.id'});
96: if ($forcestudent or $target eq 'tex') { $allowed=0; }
97: }
98: }
99:
1.46 www 100: # -------------------------------------------------- Let's see who handles this
1.117 raeburn 101: my $external=$courseenv{'externalsyllabus'};
102: my $uploaded=$courseenv{'uploadedsyllabus'};
1.122 raeburn 103: my $minimal=$courseenv{'minimalsyllabus'};
1.49 albertel 104:
1.122 raeburn 105: if (($minimal =~/\w/) || ($uploaded =~/\w/)) {
106: my $item;
107: if ($minimal =~/\w/) {
108: if ($external =~ m{\Q$minimal\E$}) {
109: undef($external);
110: }
111: $item = $minimal;
112: } elsif ($uploaded =~/\w/) {
113: if ($external =~ m{\Q$uploaded\E$}) {
114: undef($external);
115: }
116: $item = $uploaded;
1.117 raeburn 117: }
118: unless ($allowed && $forceedit) {
1.122 raeburn 119: my $file=&Apache::lonnet::filelocation("",$item);
1.117 raeburn 120: if ($file =~ /\.(sty|css|js|txt|tex|html?)$/) {
121: my $filetype;
122: if ($file =~ /\.(sty|css|js|txt|tex)$/) {
123: $filetype=$1;
124: } else {
125: $filetype='html';
126: }
127: my $result = '';
128: my $filecontents=&Apache::lonnet::getfile($file);
129: if ($filecontents eq -1) {
130: $r->print(&mt('Syllabus file unavailable'));
131: } elsif ($filetype eq 'html') {
132: my %mystyle;
133: &Apache::structuretags::reset_problem_globals();
134: my $oldfile = $env{'request.filename'};
1.122 raeburn 135: $env{'request.filename'} = $item;
1.117 raeburn 136: $result = &Apache::lonxml::xmlparse($r,'web',$filecontents,
137: '',%mystyle);
138: &Apache::structuretags::reset_problem_globals();
139: &Apache::lonhomework::finished_parsing();
140: $env{'request.filename'} = $oldfile;
141: &Apache::lonxml::add_messages(\$result);
142: $r->print($result);
143: }
144: } else {
1.122 raeburn 145: $r->print(&Apache::lonwrapper::wrapper($item));
1.117 raeburn 146: }
147: return OK;
148: }
149: } elsif ($external=~/\w/) {
150: unless ($allowed && $forceedit) {
151: $r->print(&Apache::lonwrapper::wrapper($external));
152: return OK;
153: }
1.90 amueller 154: }
1.42 www 155:
1.120 raeburn 156: my $crstype = &Apache::loncommon::course_type();
157:
1.46 www 158: # ------------------------------ The buck stops here: internal syllabus display
1.5 www 159: # --------------------------------------------------------- The syllabus fields
1.23 www 160: my %syllabusfields=&Apache::lonlocal::texthash(
1.5 www 161: 'aaa_instructorinfo' => 'Instructor Information',
162: 'bbb_description' => 'Course Description',
163: 'ccc_prereq' => 'Prerequisites',
1.7 www 164: 'cdc_classhours' => 'Class Hours',
1.5 www 165: 'ddd_officehours' => 'Office Hours',
166: 'eee_helproom' => 'Helproom Hours',
1.7 www 167: 'efe_projectinfo' => 'Project Information',
1.5 www 168: 'fff_examinfo' => 'Exam Information',
1.7 www 169: 'fgf_deadlines' => 'Deadlines',
1.5 www 170: 'ggg_grading' => 'Grading Information',
1.7 www 171: 'hhh_readings' => 'Readings',
172: 'iii_coursepack' => 'Coursepack',
173: 'jjj_weblinks' => 'Web Links',
1.9 www 174: 'kkk_textbook' => 'Textbook',
175: 'lll_includeurl' => 'URLs To Include in Syllabus');
1.121 raeburn 176: # ---------------------------------------------------------- Load syllabus info
177: my %syllabus=&Apache::lonnet::dump('syllabus',$cdom,$cnum);
178: my ($output,%displayfields,%noshow);
1.65 raeburn 179:
1.121 raeburn 180: # This handler might be called anonymously ...
181: # ----------------------------------------------------- Only if not public call
182: if ($allowed) {
1.122 raeburn 183: if (($env{'form.choice'} =~ /^(template|minimal|url|file)$/) ||
1.121 raeburn 184: ($env{'form.phase'} =~ /^(upload|check)_embedded$/)) {
185: my $earlyout;
1.122 raeburn 186: ($earlyout,$uploaded,$external,$minimal,$output) =
187: &save_changes($cnum,$cdom,$uploaded,$external,$minimal,
188: \%syllabus,\%syllabusfields,\%courseenv);
189: if (($env{'form.choice'} eq 'minimal') &&
190: ($minimal eq "/uploaded/$cdom/$cnum/portfolio/syllabus/loncapa.html")) {
191: delete($env{'form.symb'});
192: delete($env{'request.symb'});
193: $r->internal_redirect("$minimal?editmode=1&forceedit=1");
194: return OK;
195: }
1.121 raeburn 196: if ($earlyout) {
197: if ($target ne 'tex') {
198: &print_header($r,$cnum,$cdom,$crstype,$allowed,$forceedit,
199: \%syllabus,\%syllabusfields);
1.122 raeburn 200: $r->print($output.
201: &Apache::loncommon::end_page());
1.121 raeburn 202: }
203: return OK;
1.90 amueller 204: }
1.65 raeburn 205: }
206: }
1.121 raeburn 207: if ($target ne 'tex') {
208: &print_header($r,$cnum,$cdom,$crstype,$allowed,$forceedit,\%syllabus,
209: \%syllabusfields);
210: $r->print($output);
1.117 raeburn 211: }
212:
1.121 raeburn 213: # -------------------------------------------- Determine which fields are shown
1.117 raeburn 214:
1.121 raeburn 215: if ($syllabus{'uploaded.fields'}) {
216: if ($syllabus{'uploaded.fields'} eq 'none') {
217: foreach my $field (keys(%syllabusfields)) {
218: $displayfields{$field} = ' style="display:none;"';
219: $noshow{$field} = 1;
1.117 raeburn 220: }
221: } else {
1.121 raeburn 222: my %included;
223: map { $included{$_} = 1; } split(/,/,$syllabus{'uploaded.fields'});
224: foreach my $field (keys(%syllabusfields)) {
225: my ($prefix) = split(/_/,$field);
226: if ($included{$prefix}) {
227: $displayfields{$field} = ' style="display:block;"';
1.117 raeburn 228: } else {
1.121 raeburn 229: $displayfields{$field} = ' style="display:none;"';
230: $noshow{$field} = 1;
1.117 raeburn 231: }
232: }
233: }
1.121 raeburn 234: } else {
1.117 raeburn 235: foreach my $field (keys(%syllabusfields)) {
236: if ($syllabus{$field} ne '') {
237: $displayfields{$field} = ' style="display:block;"';
238: } else {
239: $displayfields{$field} = ' style="display:none;"';
240: }
1.90 amueller 241: }
1.4 www 242: }
1.85 bisitz 243:
1.113 raeburn 244: if ($allowed) {
245: #---------------------------------- Print External URL Syllabus Info if editing
246: if ($target ne 'tex') {
247: my $protocol = $Apache::lonnet::protocol{$homeserver};
248: $protocol = 'http' if ($protocol ne 'https');
1.119 raeburn 249: my $link = $protocol.'://'.&Apache::lonnet::hostname($homeserver).$r->uri;
250: $r->print('<div class="LC_left_float">'
251: .'<span class="LC_help_open_topic LC_info">'
252: .'<span class="LC_info">'
253: .&mt('Public link (no log-in): [_1]','<tt>'.$link.'</tt>')
254: .' </span>'.&Apache::loncommon::help_open_topic('Syllabus_ExtLink')
255: .'</span>'
1.121 raeburn 256: .'</div><div style="padding:0;clear:both;margin:0;border:0"></div>'."\n");
1.117 raeburn 257: my $lonhost = $r->dir_config('lonHostID');
1.122 raeburn 258: $r->print(&chooser($external,$uploaded,$minimal,$cdom,$cnum,$lonhost,
259: \%syllabusfields,\%syllabus));
1.93 bisitz 260: }
1.109 bisitz 261: } else {
1.113 raeburn 262: #--------------------------------------------- Print last update unless editing
263: my $lastmod=$syllabus{'uploaded.lastmodified'};
264: $lastmod=($lastmod?&Apache::lonlocal::locallocaltime($lastmod):&mt('never'));
265: my $who;
266: if ($syllabus{'uploaded.lastmodified'}) {
267: if (($env{'user.name'} ne 'public') && ($env{'user.domain'} ne 'public')) {
268: $who = &Apache::loncommon::aboutmewrapper(
269: &Apache::loncommon::plainname($syllabus{'uploaded.name'},
270: $syllabus{'uploaded.domain'}),$syllabus{'uploaded.name'},
271: $syllabus{'uploaded.domain'});
272: } else {
273: # Public user?
274: # Only display name of user, but no link to personal information page
275: $who = &Apache::loncommon::plainname(
276: $syllabus{'uploaded.name'},
277: $syllabus{'uploaded.domain'});
278: }
279: }
280: if ($target ne 'tex') {
281: $r->print('<div class="LC_info">'.&mt('Last updated').': '.
282: $lastmod . ' '.
283: ($who ? &mt('by').' '.$who
284: : '' ) .
285: '</div>' );
286: } else {
287: $r->print('\\\\ '.&mt('Last updated').': '.$lastmod.' '.
288: ($who? &mt('by').'\\\\ '.
289: &Apache::loncommon::plainname($syllabus{'uploaded.name'},$syllabus{'uploaded.domain'})
290: :'')
291: .'\\\\');
292: }
1.109 bisitz 293: }
294:
1.113 raeburn 295: #-------------------------------------------------------------- Print Headtitle
1.90 amueller 296: if ($target ne 'tex') {
1.117 raeburn 297: my $display = 'block';
1.122 raeburn 298: if ($external || $uploaded || $minimal) {
1.117 raeburn 299: $display = 'none';
300: }
301: $r->print('<div class="LC_Box" id="template" style="display: '.$display.'">'.
1.113 raeburn 302: '<h2 class="LC_hcell">'.$courseenv{'description'}.'</h2>');
303: if ($allowed) {
1.121 raeburn 304: $r->print('<div style="margin: 0; float:left;">'.
305: '<h3>'.&Apache::lonnet::domain($cdom,'description').'</h3>'.
306: '</div>');
1.113 raeburn 307: # Print Help Text if editing at right side of screen
1.121 raeburn 308: $r->print('<div style="margin: 0; float:right;">'.
309: &Apache::loncommon::help_open_topic('Uploaded_Templates_TextBoxes',&mt('Help with filling in text boxes')).
310: '</div><br clear="all" />');
1.113 raeburn 311: } else {
312: $r->print('<h3>'.&Apache::lonnet::domain($cdom,'description').'</h3>');
313: }
1.90 amueller 314: } else {
1.91 amueller 315: $r->print('\noindent{\large\textbf{'.$courseenv{'description'}.'}}\\\\\\\\\textbf{'.
316: &Apache::lonnet::domain($cdom,'description').'}\\\\');
1.90 amueller 317: }
1.80 neumanie 318: # -------------------------------------------------------- Get course personnel
1.121 raeburn 319: my $hidepersonnel;
320: if (($syllabus{'uploaded.fields'}) &&
321: (($syllabus{'uploaded.fields'} eq 'none') ||
322: ($syllabus{'uploaded.fields'} !~ /000/))) {
323: $hidepersonnel = 1;
324: }
1.80 neumanie 325: if ($target ne 'tex') {
1.121 raeburn 326: if ($allowed) {
327: my $display = ' style="display:block;"';
328: if ($hidepersonnel) {
329: $display = ' style="display:none;"';
330: }
331: &Apache::lontemplate::print_start_template($r,&mt('Personnel'),'LC_Box',
332: 'box_000_showpeople',$display);
333: $r->print(&get_personnel($r,$target,$cdom,$cnum,$allowed));
334: &Apache::lontemplate::print_end_template($r);
1.91 amueller 335: } else {
1.121 raeburn 336: unless ($hidepersonnel) {
337: &Apache::lontemplate::print_start_template($r,&mt('Personnel'),'LC_Box');
338: $r->print(&get_personnel($r,$target,$cdom,$cnum,$allowed));
339: &Apache::lontemplate::print_end_template($r);
1.91 amueller 340: }
341: }
1.121 raeburn 342: } else {
343: unless ($hidepersonnel) {
344: $r->print(&get_personnel($r,$target,$cdom,$cnum,$allowed));
1.91 amueller 345: }
1.80 neumanie 346: }
1.79 neumanie 347: # -------------------------------------------------------------- Announcements?
348: my $day = &Apache::lonannounce::showday(time,2,
1.91 amueller 349: &Apache::lonannounce::readcalendar($cdom.'_'.$cnum));
1.121 raeburn 350: my $hidefeeds;
351: if (($syllabus{'uploaded.fields'}) &&
352: (($syllabus{'uploaded.fields'} eq 'none') ||
353: ($syllabus{'uploaded.fields'} !~ /111/))) {
354: $hidefeeds = 1;
355: }
1.80 neumanie 356: if ($target ne 'tex') {
1.91 amueller 357: if ($allowed) {
1.117 raeburn 358: my $display = ' style="display:block;"';
1.121 raeburn 359: if ($hidefeeds) {
1.117 raeburn 360: $display = ' style="display:none;"';
361: }
362: &Apache::lontemplate::print_start_template($r,&mt('RSS Feeds and Blogs'),'LC_Box',
1.121 raeburn 363: 'box_111_showrssfeeds',$display);
1.120 raeburn 364: my ($numfeeds,$hiddenfeeds,$rsslinktext);
1.121 raeburn 365: my $feeds=&Apache::lonrss::advertisefeeds($cnum,$cdom,$forceedit,\$numfeeds,
366: \$hiddenfeeds);
1.120 raeburn 367: if ($numfeeds) {
368: $r->print($feeds);
369: $rsslinktext = &mt('New RSS Feed or Blog');
370: } else {
371: my $msg = '<br />'.
372: &mt("RSS Feeds and Blogs item is not included in a student's view of the syllabus.");
373: if ($hiddenfeeds) {
374: $r->print('<p class="LC_info">'.
375: &mt('All feeds currently hidden').
376: $msg.
377: '</p>');
378: } else {
379: $r->print('<p class="LC_info">'.
380: &mt('No current feeds').
381: $msg.
382: '</p>');
383: }
384: $rsslinktext = &mt('Manage Course RSS Feeds/Blogs');
385: if ($crstype eq 'Community') {
386: $rsslinktext = &mt('Manage Communiity RSS Feeds/Blogs');
387: }
388: }
1.91 amueller 389: my $editurl= &Apache::lonnet::absolute_url().'/adm/'.$cdom.'/'.$cnum.'/_rss.html';
1.120 raeburn 390: $r->print( '<a href="'.$editurl.'">'.$rsslinktext.'</a>');
1.91 amueller 391: &Apache::lontemplate::print_end_template($r);
1.117 raeburn 392: } else {
1.121 raeburn 393: unless ($hidefeeds) {
1.120 raeburn 394: my $feeds = &Apache::lonrss::advertisefeeds($cnum,$cdom,$forceedit);
395: if ($feeds ne '') {
1.117 raeburn 396: &Apache::lontemplate::print_start_template($r,&mt('RSS Feeds and Blogs'),'LC_Box');
1.120 raeburn 397: $r->print($feeds);
1.117 raeburn 398: &Apache::lontemplate::print_end_template($r);
399: }
400: }
1.91 amueller 401: }
1.79 neumanie 402: } else {
1.91 amueller 403: $r->print(&Apache::lonxml::xmlparse($r,'tex',$day));
1.86 bisitz 404: }
1.79 neumanie 405: # ---------------------------------------------------------------- Get syllabus
1.86 bisitz 406: if (($syllabus{'uploaded.lastmodified'}) || ($allowed)) {
1.90 amueller 407: if ($allowed) {
1.121 raeburn 408: $r->print('<form method="post" action="">');
1.90 amueller 409: }
1.117 raeburn 410:
1.106 faziophi 411: my $url_include_handler = sub {
1.117 raeburn 412: my ($r, $field, $message, $group, $data_ref, $fields_ref, $target, $allowed, $display) = @_;
1.106 faziophi 413: my %data = %{$data_ref};
414: my %fields = %{$fields_ref};
415: my $urls=$message;
416: $message='';
417: foreach my $filelink (split(/\n/,$urls)) {
418: my $output='';
419: # embed style?
420: my ($curfext)=($filelink=~/\.([^\.]+)$/);
421: my $embstyle=&Apache::loncommon::fileembstyle($curfext);
422: if (($embstyle eq 'ssi') || ($curfext=~/\/$/)) {# make ssi call and remove everything but the body contents
423: $output=&Apache::lonnet::ssi_body($filelink);
424: } elsif ($embstyle eq 'img') {# embed as an image
425: $output='<img src="'.$filelink.'" />';
426: }
427: if ($output ne '') {
428: if ($target ne 'tex') {
429: $message.='<p>'.$output.'</p>';
430: } else {
431: $message.=' '.&Apache::lonxml::xmlparse($r,'tex','<p>'.$output.'</p>').' ';
432: }
433: }
434: }
435: if ($allowed) {
436: &Apache::lonfeedback::newline_to_br(\$urls);
437: &Apache::lontemplate::print_start_template($r,$fields{$field}.
1.117 raeburn 438: &Apache::loncommon::help_open_topic('Syllabus_URLs'),'LC_Box',
439: 'box_'.$field,$display);
1.106 faziophi 440: $r->print($urls);
441: $r->print("<br /><div>");
442: &Apache::lontemplate::print_textarea_template($r, $data{$field},
443: $field, Apache::lontemplate->RICH_TEXT_ALWAYS_OFF);
444: &Apache::lontemplate::print_saveall_template($r);
445: $r->print("</div>");
446: &Apache::lontemplate::print_end_template($r);
1.86 bisitz 447:
1.106 faziophi 448: } else {
449: $r->print($message);
450: }
451: };
452: my %custom_hash = ( 'lll_includeurl' => $url_include_handler );
1.110 raeburn 453: &Apache::lontemplate::print_template_fields($r, \%syllabus, \%syllabusfields,
1.117 raeburn 454: $target, $allowed, Apache::lontemplate->RICH_TEXT_DETECT_HTML, \%custom_hash,
1.121 raeburn 455: undef,\%displayfields,\%noshow);
1.90 amueller 456: if ($allowed) {
1.91 amueller 457: $r->print('</form>'.
1.110 raeburn 458: &Apache::lonhtmlcommon::htmlareaselectactive());
1.90 amueller 459: }
1.4 www 460: } else {
1.112 bisitz 461: if ($target ne 'tex') {$r->print('<p class="LC_info">');} else {$r->print('\par ');}
1.91 amueller 462: $r->print(&mt('No syllabus information provided.'));
463: if ($target ne 'tex') {$r->print('</p>');}
1.1 www 464: }
1.86 bisitz 465: if ($target ne 'tex') {
1.65 raeburn 466: if ($env{'form.backto'} eq 'coursecatalog') {
467: $r->print('<form name="backtocat" method="post" action="/adm/coursecatalog">'.
1.66 raeburn 468: &Apache::lonhtmlcommon::echo_form_input(['backto','courseid']).
1.65 raeburn 469: '</form>');
470: }
1.91 amueller 471: $r->print(&Apache::loncommon::end_page());
1.48 albertel 472: } else {
1.91 amueller 473: $r->print('\end{document}');
1.48 albertel 474: }
1.1 www 475: return OK;
1.86 bisitz 476: }
1.1 www 477:
1.121 raeburn 478: sub print_header {
479: my ($r,$cnum,$cdom,$crstype,$allowed,$forceedit,$syllabus,$syllabusfields) = @_;
480: return unless ((ref($syllabus) eq 'HASH') || (ref($syllabusfields) eq 'HASH'));
481: # ----------------------------------------------------------------- Make header
482: my $rss_link = &Apache::lonrss::rss_link($cnum,$cdom);
483: my $js;
484: if ($env{'form.backto'} eq 'coursecatalog') {
485: $js .= <<"ENDSCRIPT";
486:
487: <script type="text/javascript">
488: // <![CDATA[
489:
490: function ToCatalog(caller) {
491: numidx = getIndexByName('coursenum');
492: if (numidx > -1) {
493: if (caller != 'details') {
494: document.backtocat.elements[numidx].value = '';
495: }
496: }
497: document.backtocat.submit();
498: }
499:
500: function getIndexByName(item) {
501: for (var i=0;i<document.backtocat.elements.length;i++) {
502: if (document.backtocat.elements[i].name == item) {
503: return i;
504: }
505: }
506: return -1;
507: }
508:
509: // ]]>
510: </script>
511:
512: ENDSCRIPT
513: }
514: if ($allowed && $forceedit) {
515: my $check_uncheck = &Apache::loncommon::check_uncheck_jscript();
516: my @fieldnames = sort(keys(%{$syllabusfields}));
517: unshift(@fieldnames,'000_showpeople','111_showrssfeeds');
518: my (@checked,@unchecked);
519: if ($syllabus->{'uploaded.fields'} eq 'none') {
520: my $lastidx = scalar(@fieldnames)-1;
521: @unchecked = (0..$lastidx);
522: } elsif ($syllabus->{'uploaded.fields'}) {
523: my %included;
524: map { $included{$_} = 1; } split(/,/,$syllabus->{'uploaded.fields'});
525: for (my $i=0; $i<@fieldnames; $i++) {
526: my ($prefix) = split(/_/,$fieldnames[$i]);
527: if ($included{$prefix}) {
528: push(@checked,$i);
529: } else {
530: push(@unchecked,$i);
531: }
532: }
533: } else {
534: @checked = (0,1);
535: for (my $i=2; $i<@fieldnames; $i++) {
536: if ($syllabus->{$fieldnames[$i]}) {
537: push(@checked,$i);
538: } else {
539: push(@unchecked,$i);
540: }
541: }
542: }
543: my $fieldstr = "var fields = new Array('".join("','",@fieldnames)."');";
544: my $checkedstr = "var include = new Array('".join("','",@checked)."');";
545: my $uncheckedstr = "var exclude = new Array('".join("','",@unchecked)."');";
546: my $invurl = &mt('Invalid URL');
547: my $urlregexp = <<'ENDREGEXP';
548: /^([a-z]([a-z]|\d|\+|-|\.)*):(\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?((\[(|(v[\da-f]{1,}\.(([a-z]|\d|-|\.|_|~)|[!\$&'\(\)\*\+,;=]|:)+))\])|((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=])*)(:\d*)?)(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*|(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)){0})(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i
549: ENDREGEXP
550:
551: $js .= <<"ENDSCRIPT";
552:
553: <script type="text/javascript">
554: // <![CDATA[
555:
556: function toggleEditor(pick) {
1.122 raeburn 557: var choices = new Array('template','minimal','url','file','templatebox');
1.121 raeburn 558: for (var i=0; i<choices.length; i++) {
559: if (((choices[i] == 'templatebox') && (pick == 'template')) ||
560: (choices[i] == pick)) {
561: document.getElementById(choices[i]).style.display='block';
562: } else {
563: document.getElementById(choices[i]).style.display='none';
564: }
565: }
566: return;
567: }
568:
569: var regexp = $urlregexp;
570:
571: function extUrlPreview(caller) {
572: if (document.getElementById(caller)) {
573: var url = document.getElementById(caller).value;
574: if (regexp.test(url)) {
575: openMyModal(url,500,400,'yes');
576: } else {
577: alert("$invurl");
578: }
579: }
580: }
581:
582: function toggleBox(name,caller) {
583: if (name == 'all') {
584: if (document.syllabus.showfield.length > 0) {
585: for (var i=0; i<document.syllabus.showfield.length; i++) {
586: if (document.syllabus.showfield[i].checked) {
587: if (document.getElementById('box_'+document.syllabus.showfield[i].value)) {
588: document.getElementById('box_'+document.syllabus.showfield[i].value).style.display='block';
589: }
590: } else {
591: if (document.getElementById('box_'+document.syllabus.showfield[i].value)) {
592: document.getElementById('box_'+document.syllabus.showfield[i].value).style.display='none';
593: }
594: }
595: }
596: }
597: } else {
598: if (caller.checked) {
599: if (document.getElementById('box_'+caller.value)) {
600: document.getElementById('box_'+caller.value).style.display='block';
601: }
602: } else {
603: if (document.getElementById('box_'+caller.value)) {
604: document.getElementById('box_'+caller.value).style.display='none';
605: }
606: }
607: }
608: return;
609: }
610:
611: function setTemplateBoxes() {
612: $fieldstr
613: $checkedstr
614: $uncheckedstr
615: if (include.length > 0) {
616: for (var i=0; i<include.length; i++) {
617: if (document.getElementById('showfield_'+include[i])) {
618: document.getElementById('showfield_'+include[i]).checked = true;
619: if (document.getElementById('box_'+fields[include[i]])) {
620: document.getElementById('box_'+fields[include[i]]).style.display='block';
621: }
622: }
623: }
624: }
625: if (exclude.length > 0) {
626: for (var i=0; i<exclude.length; i++) {
627: if (document.getElementById('showfield_'+exclude[i])) {
628: document.getElementById('showfield_'+exclude[i]).checked = false;
629: if (document.getElementById('box_'+fields[exclude[i]])) {
630: document.getElementById('box_'+fields[exclude[i]]).style.display='none';
631: }
632: }
633: }
634: }
635: return;
636: }
637:
638: $check_uncheck
639:
640: // ]]>
641: </script>
642:
643: ENDSCRIPT
644: }
645: my $args = {'function' => undef,
646: 'domain' => $cdom};
647: my $forcereg;
648: if ($env{'form.register'}) {
649: $forcereg = 1;
650: $args->{'force_register'} = $forcereg;
651: }
652: if ($env{'form.backto'} eq 'coursecatalog') {
653: &Apache::lonhtmlcommon::clear_breadcrumbs();
654: my $brcrum = [{href=>"javascript:ToCatalog();",
655: text=>&mt('Course/Community Catalog'),
656: no_mt=>1}
657: ];
658: if ($env{'form.coursenum'} ne '') {
659: push(@{$brcrum},
660: {href=>"javascript:ToCatalog('details')",
661: text=>"Course details"});
662: }
663: push(@{$brcrum},
664: {href=>$r->uri,
665: text=>"Course syllabus"});
666: $args->{'bread_crumbs'} = $brcrum;
667: } elsif ($env{'form.folderpath'} =~ /^supplemental/) {
668: my $title = $env{'form.title'};
669: if ($title eq '') {
670: $title = &mt('Syllabus');
671: }
672: my $brcrum =
673: &Apache::lonhtmlcommon::docs_breadcrumbs(undef,$crstype,undef,$title,1);
674: if (ref($brcrum) eq 'ARRAY') {
675: $args->{'bread_crumbs'} = $brcrum;
676: }
677: } else {
678: if ((&Apache::lonnet::is_on_map("public/$cdom/$cnum/syllabus"))
679: && (($env{'form.symb'}) || ($env{'form.register'}))) {
680: &Apache::lonhtmlcommon::clear_breadcrumbs();
681: } else {
682: $args->{'bread_crumbs'} = [
683: {'href' => "/public/$cdom/$cnum/syllabus",
684: 'text' => 'Syllabus'},
685: ];
686: }
687: }
688: if ($allowed) {
689: my %loaditem = (
690: onload => 'setTemplateBoxes();',
691: );
692: $args->{'add_entries'} = \%loaditem;
693: }
694: my $start_page =
695: &Apache::loncommon::start_page("Syllabus", $rss_link.$js,$args);
1.122 raeburn 696: if ($start_page) {
697: $r->print($start_page);
698: }
1.121 raeburn 699: }
700:
1.117 raeburn 701: sub chooser {
1.122 raeburn 702: my ($external,$uploaded,$minimal,$cdom,$cnum,$lonhost,$fields,$values) = @_;
1.117 raeburn 703: my %lt = &Apache::lonlocal::texthash(
704: 'type' => 'Syllabus Type',
705: 'url' => 'External URL',
1.122 raeburn 706: 'file' => 'Uploaded file',
707: 'minimal' => 'Minimal template',
708: 'template' => 'Standard template',
1.117 raeburn 709: 'templateboxes' => 'Choose template items ... ',
710: 'curr' => 'Current:',
711: 'rep' => 'Replace:',
712: 'upl' => 'Upload:',
713: 'pr' => 'Preview',
714: 'save' => 'Save',
1.122 raeburn 715: 'sved' => 'Save and Edit',
716: 'chourl' => 'External URL',
1.117 raeburn 717: 'chofile' => 'Uploaded syllabus file',
718: 'parse' => 'Upload embedded images/multimedia files if HTML file',
719: );
720: my %checked = (
721: file => '',
1.122 raeburn 722: minimal => '',
1.117 raeburn 723: url => '',
724: template => '',
725: );
726: my %display = (
727: file => 'none',
1.122 raeburn 728: minimal => 'none',
1.117 raeburn 729: url => 'none',
730: templatebox => 'none',
731: );
732: my $check = ' checked="checked" ';
733: if ($uploaded) {
734: $checked{'file'} = $check;
735: $display{'file'} = 'block';
736: } elsif ($external) {
737: $checked{'url'} = $check;
738: $display{'url'} = 'block';
1.122 raeburn 739: } elsif ($minimal) {
740: $checked{'minimal'} = $check;
741: $display{'minimal'} = 'block';
1.117 raeburn 742: } else {
743: $checked{'template'} = $check;
744: $checked{'templatebox'} = $check;
745: $display{'templatebox'} = 'block';
746: }
747:
748: my $output =
749: '<form name="syllabus" method="post" enctype="multipart/form-data" action="">'."\n".
750: '<input type="hidden" name="forceedit" value="1" />'."\n".
751: '<div class="LC_left_float"><fieldset><legend>'.$lt{'type'}.'</legend>';
1.122 raeburn 752: foreach my $item ('minimal','template','url','file') {
1.117 raeburn 753: $output .= '<label><input type="radio" name="choice" value="'.$item.'" '.$checked{$item}.' onclick="toggleEditor('."'$item'".')" />'.
754: $lt{$item}.'</label><br />';
755: }
756: $output .= '</fieldset></div>'."\n".
757: '<div id="url" class="LC_left_float" style="display: '.$display{'url'}.'">'."\n".
758: '<fieldset><legend>'.$lt{'chourl'}.'</legend><span class="LC_nobreak">'."\n".
759: '<a href="javascript:extUrlPreview('."'syllabusurl'".');">'.$lt{'pr'}.'</a></span> '."\n".
760: '<input type="text" id="syllabusurl" name="externalsyllabus" value="'.$external.'" size="55" />'."\n".
761: ' <input type="submit" name="storeurl" value="'.$lt{'save'}.'" />'."\n".
762: '</fieldset></div>'."\n".
1.122 raeburn 763: '<div id="minimal" class="LC_left_float" style="display: '.$display{'minimal'}.'">'."\n".
764: '<fieldset><legend>'.$lt{'minimal'}.'</legend>';
765: if ($minimal) {
766: my ($absurl,$filename,$depbutton) = &syllabus_file_info($minimal,$cnum,$cdom,$lonhost,'minimal');
767: $output .= '<a href="javascript:extUrlPreview('."'currminimal'".');">'.$lt{'pr'}.'</a>'.
768: '<input type="hidden" name="minimalfile" value="'.&HTML::Entities::encode($absurl).'?inhibitmenu=yes" id="currminimal" />'.
769: $depbutton;
770: } else {
771: $output .= &mt('Title of Syllabus Page:').' '.
772: '<input type="text" id="minimaltitle" name="syllabustitle" value="'.&mt('Syllabus').'" size="30" />'."\n".
773: ' <input type="submit" name="storeminimal" value="'.$lt{'sved'}.'" />'."\n";
774: }
775: $output .= '</fieldset></div>'."\n".
776: '<div id="file" class="LC_left_float" style="display: '.$display{'file'}.'">'."\n".
777: '<fieldset><legend>'.$lt{'file'}.'</legend>';
1.117 raeburn 778: if ($uploaded) {
1.122 raeburn 779: my ($absurl,$filename,$depbutton) = &syllabus_file_info($uploaded,$cnum,$cdom,$lonhost,'file');
1.117 raeburn 780: $output .= '<span class="LC_nobreak">'.$lt{'curr'}.' '.
781: '<input type="hidden" name="uploadedfile" value="'.&HTML::Entities::encode($absurl).'?inhibitmenu=yes" id="currfile" />'.
1.118 raeburn 782: '<a href="javascript:extUrlPreview('."'currfile'".');">'.$filename.'</a></span>'.$depbutton.
783: '<br /><br />'.$lt{'rep'};
1.117 raeburn 784: } else {
785: $output .= $lt{'upl'};
786: }
787: $output .= '<br />'."\n".
788: '<span class="LC_nobreak">'.
789: '<input type="file" name="syllabusfile" size="55" />'."\n".
790: ' <input type="submit" name="storefile" value="'.$lt{'save'}.'" />'.
791: '</span><br />'.
792: '<label>'.
793: '<input type="checkbox" name="parserflag" checked="checked" />'.
794: $lt{'parse'}.
795: '</label>'.
796: '</fieldset></div>'.
797: '<div id="templatebox" class="LC_left_float" style="display: '.
798: $display{'templatebox'}.';"><fieldset><legend>'.$lt{'templateboxes'}.
799: ' <input type="button" value="'.&mt('check all').'" '.
800: 'onclick="javascript:checkAll('."document.syllabus.showfield".');javascript:toggleBox('."'all'".');" />'.
801: (' 'x2).
802: '<input type="button" value="'.&mt('uncheck all').'" '.
803: 'onclick="javascript:uncheckAll('."document.syllabus.showfield".');javascript:toggleBox('."'all'".');" />'.
804: '</legend>'.
805: &fields_check_uncheck($fields,$values).
1.121 raeburn 806: '</fieldset><br />'.
807: '<input type="submit" name="storesyl" value="'.&mt('Save All').'" />'.
1.117 raeburn 808: '</div>';
1.121 raeburn 809: $output .= '<div style="padding:0;clear:both;margin:0;border:0"></div>';
1.117 raeburn 810: return $output;
811: }
812:
1.122 raeburn 813: sub syllabus_file_info {
814: my ($item,$cnum,$cdom,$lonhost,$context) = @_;
815: my $protocol = $Apache::lonnet::protocol{$lonhost};
816: $protocol = 'http' if ($protocol ne 'https');
817: my $absurl = $protocol.'://'.&Apache::lonnet::hostname($lonhost).$item;
818: my ($filename) = ($item =~ m{([^/]+)$});
819: my $file=&Apache::lonnet::filelocation("",$item);
820: my $depbutton;
821: if ($file =~ /\.html?$/) {
822: my $filecontents=&Apache::lonnet::getfile($file);
823: unless ($filecontents eq -1) {
824: my $mm = new File::MMagic;
825: my $mimetype = $mm->checktype_contents($filecontents);
826: if ($mimetype eq 'text/html') {
827: my (%codebase,%allfiles);
828: my $parse_result = &Apache::lonnet::extract_embedded_items($item,\%allfiles,
829: \%codebase,\$filecontents);
830: my $actionurl = "/public/$cdom/$cnum/syllabus";
831: my ($ignore,$num,$numpathchanges,$existing,$mapping) =
832: &Apache::loncommon::ask_for_embedded_content($actionurl,undef,\%allfiles,
833: \%codebase,
834: {'context' => 'rewrites',
835: 'ignore_remote_references' => 1,});
836: $depbutton = (' ' x 3).
837: &editfile_button($item,$context).
838: &editbutton_js();
839: }
840: }
841: }
842: return ($absurl,$filename,$depbutton);
843: }
844:
1.117 raeburn 845: sub fields_check_uncheck {
846: my ($fields,$values) = @_;
847: return unless ((ref($fields) eq 'HASH') && (ref($values) eq 'HASH'));
848: my $numinrow = 4;
849: my $table;
850: my @fieldnames = sort(keys(%{$fields}));
1.121 raeburn 851: unshift(@fieldnames,'000_showpeople','111_showrssfeeds');
1.117 raeburn 852: my $numfields = scalar(@fieldnames);
1.121 raeburn 853: my %included;
854: if (($values->{'uploaded.fields'}) && ($values->{'uploaded.fields'} ne 'none')) {
855: map { $included{$_} = 1; } split(/,/,$values->{'uploaded.fields'});
856: }
1.117 raeburn 857: for (my $i=0; $i<$numfields; $i++) {
1.121 raeburn 858: my ($name,$checked);
859: if ($fieldnames[$i] eq '000_showpeople') {
860: $name = &mt('Personnel');
861: } elsif ($fieldnames[$i] eq '111_showrssfeeds') {
1.117 raeburn 862: $name = &mt('RSS Feeds and Blogs');
1.121 raeburn 863: } else {
864: $name = $fields->{$fieldnames[$i]};
865: }
866: if ($values->{'uploaded.fields'}) {
867: unless ($values->{'uploaded.fields'} eq 'none') {
868: my ($prefix) = split(/_/,$fieldnames[$i]);
869: if ($included{$prefix}) {
870: $checked = ' checked="checked"';
871: }
872: }
873: } else {
874: if ($fieldnames[$i] eq '000_showpeople') {
875: $checked = ' checked="checked"';
876: } elsif ($fieldnames[$i] eq '111_showrssfeeds') {
1.117 raeburn 877: $checked = ' checked="checked"';
1.121 raeburn 878: } else {
879: if ($values->{$fieldnames[$i]} ne '') {
880: $checked = ' checked="checked"';
881: }
1.117 raeburn 882: }
883: }
884: my $rem = $i%($numinrow);
885: if ($rem == 0) {
1.121 raeburn 886: if (($i > 0) && ($i < $numfields)) {
1.117 raeburn 887: $table .= '</tr>';
888: }
1.121 raeburn 889: if ($i < $numfields) {
1.117 raeburn 890: $table .= '<tr>';
891: }
892: }
1.121 raeburn 893: if ($i == $numfields-1) {
894: my $rem = $numfields%($numinrow);
895: my $colsleft = $numinrow - $rem;
896: if ($colsleft > 1) {
897: $table .= '<td colspan="'.$colsleft.'">';
898: } else {
899: $table .= '</td>';
900: }
901: } else {
902: $table .= '<td>';
903: }
1.117 raeburn 904: $table .=
1.121 raeburn 905: '<label><input type="checkbox" name="showfield" value="'.$fieldnames[$i].'" '.
1.117 raeburn 906: $checked.' id="showfield_'.$i.'" onclick="javascript:toggleBox('."'$fieldnames[$i]',this".');" />'.
907: $name.'</label></td>'."\n";
908: }
909: if ($table ne '') {
910: my $rem = $numfields%($numinrow);
911: my $colsleft = $numinrow - $rem;
912: if ($colsleft > 1 ) {
913: $table .= '<td colspan="'.$colsleft.'"> </td>';
914: } elsif ($colsleft == 1) {
915: $table .= '<td> </td>';
916: }
917: $table = '<table>'.$table.'</tr></table>';
918: }
919: return $table;
920: }
921:
1.121 raeburn 922: sub get_personnel {
923: my ($r,$target,$cdom,$cnum,$allowed) = @_;
924: my $output;
925: my %coursepersonnel=&Apache::lonnet::get_course_adv_roles($cdom.'/'.$cnum);
926: if ($target ne 'tex') {
927: $r->print(&Apache::lonhtmlcommon::start_pick_box());
928: } else {
929: $r->print('\begin{tabular}{|p{0.45\textwidth}|p{0.45\textwidth}|}\hline');
930: }
931: my @personnel=sort(keys(%coursepersonnel));
932: my $lastpers=$personnel[$#personnel];
933: foreach my $element (@personnel) {
934: if ($target ne 'tex') {
935: $r->print(&Apache::lonhtmlcommon::row_title($element));
936: } else {
937: $r->print(' '.&Apache::lonxml::xmlparse($r,'tex',$element).' & ');
938: }
939: my @coursepersonlist;
940: foreach my $user (split(/\,/,$coursepersonnel{$element})) {
941: my ($puname,$pudom)=split(/\:/,$user);
942: if ($target ne 'tex') {
943: my $courseperson = &Apache::loncommon::plainname($puname,$pudom);
944: if (($env{'user.name'} eq '') || ($env{'user.name'} eq 'public') ||
945: ($env{'user.domain'} eq '') || ($env{'user.domain'} eq 'public')) {
946: push(@coursepersonlist,$courseperson);
947: } else {
948: push(@coursepersonlist,&Apache::loncommon::aboutmewrapper($courseperson,
949: $puname,$pudom));
950: }
951: } else {
952: push(@coursepersonlist,&Apache::loncommon::plainname($puname,
953: $pudom).' ');
954: }
955: }
956: $r->print(join(", ",@coursepersonlist));
957: if ($target ne 'tex') {
958: my $lastclose=$element eq $lastpers?1:0;
959: $r->print(&Apache::lonhtmlcommon::row_closure($lastclose));
960: } else {
961: $r->print('\\\\ \hline');
962: }
963: }
964: if ($target ne 'tex') {
965: $r->print(&Apache::lonhtmlcommon::end_pick_box());
966: } else {
967: $r->print('\end{tabular}\\\\');
968: }
969: return;
970: }
971:
972: sub save_changes {
1.122 raeburn 973: my ($cnum,$cdom,$uploaded,$external,$minimal,$syllabus,$syllabusfields,$courseenv) = @_;
1.121 raeburn 974: my ($earlyout,$output);
975: unless ((ref($syllabus) eq 'HASH') && (ref($syllabusfields) eq 'HASH')) {
1.122 raeburn 976: return ($earlyout,$uploaded,$external,$minimal,$output);
1.121 raeburn 977: }
1.122 raeburn 978: if ($env{'form.deleteuploaded'}) {
979: my %storehash;
980: if (($env{'form.choice'} eq 'file') &&
981: ($env{'form.deleteuploaded'} eq 'file') && ($uploaded =~ /\w/)) {
982: &Apache::lonnet::delenv('course.'.$env{'request.course.id'}.'.uploadedsyllabus');
983: &Apache::lonnet::delenv('course.'.$env{'request.course.id'}.'.externalsyllabus');
984: $storehash{'uploadedsyllabus'} = '';
985: $storehash{'externalsyllabus'} = '';
986: my $putres = &Apache::lonnet::put('environment',\%storehash,$cdom,$cnum);
987: undef($uploaded);
988: undef($external);
989: } elsif (($env{'form.choice'} eq 'minimal') &&
990: ($env{'form.deleteuploaded'} eq 'minimal') && ($minimal =~ /\w/)) {
991: &Apache::lonnet::delenv('course.'.$env{'request.course.id'}.'.externalsyllabus');
992: &Apache::lonnet::delenv('course.'.$env{'request.course.id'}.'.minimalsyllabus');
993: $storehash{'externalsyllabus'} = '';
994: $storehash{'minimalsyllabus'} = '';
995: my $putres = &Apache::lonnet::put('environment',\%storehash,$cdom,$cnum);
996: undef($external);
997: undef($minimal);
998: }
999: } elsif ($env{'form.choice'} eq 'template') {
1.121 raeburn 1000: #store what the user typed in to the template
1001: my @shown = &Apache::loncommon::get_env_multiple('form.showfield');
1002: $syllabus->{'uploaded.fields'} = '';
1003: if (@shown == 0) {
1004: $syllabus->{'uploaded.fields'} = 'none';
1005: } else {
1006: foreach my $field (sort(@shown)) {
1007: if (($field eq '000_showpeople') ||
1008: ($field eq '111_showrssfeeds') ||
1009: ($syllabusfields->{$field})) {
1010: my ($prefix) = split(/_/,$field);
1011: $syllabus->{'uploaded.fields'} .= $prefix.',';
1012: }
1013: }
1014: $syllabus->{'uploaded.fields'} =~ s/,$//;
1015: }
1016: foreach my $syl_field (keys(%{$syllabusfields})) {
1017: my $field=$env{'form.'.$syl_field};
1018: chomp($field);
1019: $field=~s/\s+$//s;
1020: $field=~s/^\s+//s;
1021: $field=~s/\<br\s*\/*\>$//s;
1022: $field=&Apache::lonfeedback::clear_out_html($field,1);
1023: #here it will be stored
1024: $syllabus->{$syl_field}=$field;
1025: if ($syl_field eq 'lll_includeurl') { # clean up included URLs
1026: my $field='';
1027: foreach my $value (split(/\n/,$syllabus->{$syl_field})) {
1028: my $url=$value;
1029: # get rid of leading and trailing spaces
1030: $url=~s/^\s+//;
1031: $url=~s/\s+$//;
1032: if ($url=~m|^https?\://([^/]+)/(.+)$|) {
1033: my $host = $1;
1034: my $remainder=$2;
1035: # remove the hostname from internal URLs
1036: my $hostname = &Apache::lonnet::hostname($host);
1037: my %all_hostnames = &Apache::lonnet::all_hostnames();
1038: foreach my $possible_host (keys(%all_hostnames)) {
1039: if ($possible_host =~ /\Q$hostname\E/i) {
1040: $url=$remainder;
1041: }
1042: }
1043: }
1044: # norm internal URLs
1045: unless ($url=~/^https?\:/) {
1046: $url=&Apache::lonnet::clutter($url);
1047: }
1048: # re-assemble field
1049: if ($url) {
1050: $field.=$url."\n";
1051: }
1052: }
1053: $syllabus->{$syl_field}=$field;
1054: }
1055: }
1056: my $now = time;
1057: $syllabus->{'uploaded.domain'}=$env{'user.domain'};
1058: $syllabus->{'uploaded.name'}=$env{'user.name'};
1059: $syllabus->{'uploaded.lastmodified'} = $now;
1060: my $putres = &Apache::lonnet::put('syllabus',$syllabus,$cdom,$cnum);
1061: if ($putres eq 'ok') {
1.123 raeburn 1062: ($uploaded,$minimal,$external) =
1063: &update_syllabus_env($cdom,$cnum,$courseenv,$env{'form.choice'},$uploaded,
1064: $minimal,$external);
1.121 raeburn 1065: $output = '<div>'.
1066: &Apache::lonhtmlcommon::confirm_success(&mt('Template saved.')).
1067: '</div>';
1068: } else {
1069: $output = '<div class="LC_error">'.
1070: &mt('An error occurred storing the template: [_1]',$putres).
1071: '</div>';
1072: }
1073: } elsif ($env{'form.choice'} eq 'url') {
1074: if ($env{'form.externalsyllabus'} =~ m{^https?://}) {
1075: if ($env{'form.externalsyllabus'} eq $external) {
1076: $output = '<div class="LC_info">'.
1077: &mt('External URL unchanged.').
1078: '</div>';
1.123 raeburn 1079: ($uploaded,$minimal,$external) =
1080: &update_syllabus_env($cdom,$cnum,$courseenv,$env{'form.choice'},$uploaded,
1081: $minimal,$external);
1.121 raeburn 1082: } else {
1083: $external=$env{'form.externalsyllabus'};
1084: $external =~ s/(`)//g;
1085: my $putres =
1086: &Apache::lonnet::put('environment',{externalsyllabus=>$external},
1087: $cdom,$cnum);
1088: if ($putres eq 'ok') {
1089: &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.externalsyllabus' => $external});
1090: $output = '<div>'.
1091: &Apache::lonhtmlcommon::confirm_success(&mt('External URL saved.')).
1092: '</div>';
1.123 raeburn 1093: ($uploaded,$minimal,$external) =
1094: &update_syllabus_env($cdom,$cnum,$courseenv,$env{'form.choice'},$uploaded,
1095: $minimal,$external);
1.121 raeburn 1096: } else {
1097: $output = '<div class="LC_error">'.
1098: &mt('An error occurred storing the external URL: [_1]',$putres).
1099: '</div>';
1100: }
1101: }
1102: } else {
1103: $output = '<div class="LC_error">'.
1104: &mt('External URL not saved -- invalid URL.').
1105: '</div>';
1106: }
1.122 raeburn 1107: } elsif (($env{'form.choice'} eq 'file') || ($env{'form.choice'} eq 'minimal')) {
1.121 raeburn 1108: # Process file upload - phase one - upload and parse primary file.
1.122 raeburn 1109: my ($upload_result,$uploadphase,$url,$needlink,$error,$errormsg);
1110: if ($env{'form.choice'} eq 'file') {
1111: if ($env{'form.syllabusfile.filename'}) {
1112: my %allfiles = ();
1113: my %codebase = ();
1114: ($url,$needlink) = &process_upload(\$output,$cnum,$cdom,
1115: \%allfiles,\%codebase);
1116: } else {
1117: $output = '<div class="LC_info">';
1118: &mt('No file uploaded').
1119: '</div>';
1120: }
1121: } elsif ($env{'form.choice'} eq 'minimal') {
1122: my $title = $env{'form.syllabustitle'};
1123: $title =~ s{`}{}g;
1124: $title=~s/^\s+//;
1125: $title=~s/\s+$//;
1126: if ($title eq '') {
1127: $title = &mt('Syllabus');
1128: }
1129: my $initialtext = &mt('Replace with your own content.');
1130: my $newhtml = <<END;
1131: <html>
1132: <head>
1133: <title>$title</title>
1134: </head>
1135: <body bgcolor="#ffffff">
1136: <h2>$title</h2>
1137: $initialtext
1138: </body>
1139: </html>
1140: END
1141: $env{'form.output'}=$newhtml;
1142: $url =
1143: &Apache::lonnet::finishuserfileupload($cnum,$cdom,'output',
1144: 'portfolio/syllabus/loncapa.html');
1145: }
1146: if ($url =~ m{^/uploaded/\Q$cdom\E/\Q$cnum\E.*/[^/]+$}) {
1.123 raeburn 1147: my $exturl = &home_http_host($cdom,$cnum);
1148: if ($exturl) {
1149: $exturl .= $url;
1.122 raeburn 1150: }
1151: my %storehash;
1152: if ($env{'form.choice'} eq 'minimal') {
1153: $storehash{'minimalsyllabus'} = $url;
1154: } else {
1155: $storehash{'uploadedsyllabus'} = $url;
1156: }
1157: if ($exturl) {
1158: $storehash{'externalsyllabus'} = $exturl;
1159: if ($exturl =~ /\.(html?|txt|js|css)$/) {
1160: $exturl .= '?inhibitmenu=yes';
1161: }
1162: } else {
1163: $storehash{'externalsyllabus'} = '',
1164: }
1165: my $putres =
1166: &Apache::lonnet::put('environment',\%storehash,$cdom,$cnum);
1167: if ($putres eq 'ok') {
1168: &Apache::lonnet::make_public_indefinitely($url);
1169: foreach my $key (keys(%storehash)) {
1170: &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.'.$key => $storehash{$key}});
1171: }
1172: if ($env{'form.choice'} eq 'minimal') {
1173: $minimal = $url;
1.121 raeburn 1174: } else {
1.122 raeburn 1175: $uploaded = $url;
1.121 raeburn 1176: }
1.122 raeburn 1177: if ($needlink) {
1178: $output .= &return_to_editor($cdom,$cnum);
1179: $earlyout = 1;
1.121 raeburn 1180: }
1.123 raeburn 1181: ($uploaded,$minimal,$external) =
1182: &update_syllabus_env($cdom,$cnum,$courseenv,$env{'form.choice'},$uploaded,
1183: $minimal,$external);
1.122 raeburn 1184: } else {
1185: $error = 1;
1186: $errormsg = $putres;
1187: }
1188: } else {
1189: $error = 1;
1190: }
1191: if ($error) {
1192: $output = '<div class="LC_error">';
1193: if ($env{'form.choice'} eq 'minimal') {
1194: $output = &mt('An error occurred creating the minimal template file [_1]',$errormsg);
1195: } else {
1196: $output = &mt('An error occurred storing the uploaded file [_1]',$errormsg);
1.121 raeburn 1197: }
1.122 raeburn 1198: $output .= '</div>';
1.121 raeburn 1199: }
1200: } elsif ($env{'form.phase'} eq 'upload_embedded') {
1201: # Process file upload - phase two - upload embedded objects
1202: my $uploadphase = 'check_embedded';
1203: my $primaryurl = &HTML::Entities::encode($env{'form.primaryurl'},'<>&"');
1204: my $state = &embedded_form_elems($uploadphase,$primaryurl);
1205: my $url_root = '/uploaded/'.$cdom.'/'.$cnum;
1206: my $actionurl = "/public/$cdom/$cnum/syllabus";
1207: my ($result,$flag,$numpathchgs) =
1208: &Apache::loncommon::upload_embedded('syllabus','portfolio/syllabus',
1209: $cnum,$cdom,'/userfiles',$url_root,undef,undef,undef,$state,
1210: $actionurl);
1211: unless ($numpathchgs) {
1212: my $modres =
1213: &Apache::loncommon::modify_html_refs('syllabus','portfolio/syllabus',
1214: $cnum,$cdom,
1215: '/userfiles',$env{'form.primaryurl'});
1216: $result .= $modres;
1217: }
1.122 raeburn 1218: $output = $result.&return_to_editor($cdom,$cnum);
1.121 raeburn 1219: $earlyout = 1;
1220: } elsif ($env{'form.phase'} eq 'check_embedded') {
1221: # Process file upload - phase three - modify references in HTML file
1222: my $uploadphase = 'modified_orightml';
1223: my $result =
1224: &Apache::loncommon::modify_html_refs('syllabus','portfolio/syllabus',
1225: $cnum,$cdom,
1226: '/userfiles',$env{'form.primaryurl'});
1.122 raeburn 1227: $output = $result.&return_to_editor($cdom,$cnum);
1.121 raeburn 1228: $earlyout = 1;
1229: }
1.122 raeburn 1230: return ($earlyout,$uploaded,$external,$minimal,$output);
1.121 raeburn 1231: }
1232:
1.123 raeburn 1233: sub update_syllabus_env {
1.124 ! raeburn 1234: my ($cdom,$cnum,$courseenv,$saved,$uploaded,$minimal,$external) = @_;
1.123 raeburn 1235: return unless(ref($courseenv) eq 'HASH');
1236: my $now = time;
1237: my (@envkeys,%storehash);
1238: if ($saved eq 'template') {
1239: if ($uploaded) {
1240: push(@envkeys,'uploaded');
1241: }
1242: if ($minimal) {
1243: push(@envkeys,'minimal');
1244: }
1245: if ($external) {
1246: push(@envkeys,'external');
1247: }
1248: $storehash{'updatedsyllabus'} = $now;
1249: &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.updatedsyllabus' => $now
1250: });
1251:
1252: } elsif ($saved eq 'url') {
1253: my $prefix = &home_http_host($cdom,$cnum);
1254: if ($external =~ m{^\Q$prefix/uploaded/$cdom/$cnum/portfolio/syllabus/\E(.+)$}) {
1255: my $file = $1;
1256: if ($file eq 'loncapa.html') {
1257: if ($uploaded) {
1258: push(@envkeys,'uploaded');
1259: }
1260: } elsif ($minimal) {
1261: push(@envkeys,'minimal');
1262: }
1263: } else {
1264: if ($uploaded) {
1265: push(@envkeys,'uploaded');
1266: }
1267: if ($minimal) {
1268: push(@envkeys,'minimal');
1269: }
1270: }
1271: } elsif ($saved eq 'file') {
1272: if ($minimal) {
1273: push(@envkeys,'minimal');
1274: }
1275: } elsif ($saved eq 'minimal') {
1276: if ($uploaded) {
1277: push(@envkeys,'uploaded');
1278: }
1279: }
1280: if (@envkeys > 0) {
1281: foreach my $item (@envkeys) {
1282: my $key = $item.'syllabus';
1283: if ($courseenv->{$key}) {
1284: &Apache::lonnet::delenv('course.'.$env{'request.course.id'}.'.'.$key);
1285: $storehash{$key} = '';
1286: }
1287: if ($item eq 'uploaded') {
1288: undef($uploaded);
1289: }
1290: if ($item eq 'external') {
1291: undef($external);
1292: }
1293: if ($item eq 'minimal') {
1294: undef($minimal);
1295: }
1296: }
1297: }
1298: if (keys(%storehash) > 0) {
1299: &Apache::lonnet::put('environment',\%storehash,$cdom,$cnum);
1300: }
1301: return ($uploaded,$minimal,$external);
1302: }
1303:
1304: sub home_http_host {
1305: my ($cdom,$cnum) = @_;
1306: my $home=&Apache::lonnet::homeserver($cnum,$cdom);
1307: if ($home ne 'no_host') {
1308: my $protocol = $Apache::lonnet::protocol{$home};
1309: $protocol = 'http' if ($protocol ne 'https');
1310: return $protocol.'//'.$home;
1311: }
1312: return;
1313: }
1314:
1.117 raeburn 1315: sub process_upload {
1316: my ($upload_output,$cnum,$cdom,$allfiles,$codebase) = @_;
1317: my ($parseaction,$showupload,$mimetype);
1318: my $dest = 'portfolio/syllabus';
1319: if ($env{'form.parserflag'}) {
1320: $parseaction = 'parse';
1321: }
1322: my $url=&Apache::lonnet::userfileupload('syllabusfile','syllabus',$dest,
1323: $parseaction,$allfiles,
1324: $codebase,undef,undef,undef,undef,
1325: undef,undef,\$mimetype);
1326: if ($url =~ m{^/uploaded/\Q$cdom\E/\Q$cnum\E.*/([^/]+)$}) {
1327: my $stored = $1;
1328: $showupload = '<p>'.&mt('Uploaded [_1]',
1329: '<span class="LC_filename">'.$stored.'</span>').
1330: '</p>';
1331: } else {
1332: my ($filename) = ($env{'form.syllabusfile.filename'} =~ m{([^/]+)$});
1333: $$upload_output = '<div class="LC_error" id="uploadfileresult">'.
1334: &mt('Unable to save file [_1].',
1335: '<span class="LC_filename">'.$filename.'</span>').
1336: '</div>';
1337: return ();
1338: }
1339: my $needlink;
1340: if (($parseaction eq 'parse') && ($mimetype eq 'text/html')) {
1341: $$upload_output = $showupload;
1342: my $total_embedded = scalar(keys(%{$allfiles}));
1343: if ($total_embedded > 0) {
1344: my $uploadphase = 'upload_embedded';
1345: my $primaryurl = &HTML::Entities::encode($url,'<>&"');
1346: my $state = &embedded_form_elems($uploadphase,$primaryurl);
1347: my $actionurl = "/public/$cdom/$cnum/syllabus";
1348: my ($embedded,$num,$numpathchanges,$existing);
1349: ($embedded,$num,$numpathchanges,$existing) =
1350: &Apache::loncommon::ask_for_embedded_content($actionurl,$state,
1351: $allfiles,$codebase,
1352: {'error_on_invalid_names' => 1,
1353: 'ignore_remote_references' => 1,});
1354: if ($embedded) {
1355: $needlink = 1;
1356: if ($num) {
1357: $$upload_output .=
1358: '<p>'.&mt('This file contains embedded multimedia objects, which need to be uploaded.').'</p>'.$embedded;
1359: } elsif ($numpathchanges) {
1360: $$upload_output .= $embedded;
1361: } else {
1362: $$upload_output .= $embedded;
1363: &Apache::loncommon::modify_html_refs('syllabus','portfolio/syllabus',
1364: $cnum,$cdom,'/userfiles',$url);
1365: }
1366: } else {
1367: $$upload_output .= &mt('Embedded item(s) already present, so no additional upload(s) required').'<br />';
1368: &Apache::loncommon::modify_html_refs('syllabus','portfolio/syllabus',
1369: $cnum,$cdom,'/userfiles',$url);
1370:
1371: }
1372: } else {
1373: $$upload_output .= &mt('No embedded items identified').'<br />';
1374: }
1375: $$upload_output = '<div id="uploadfileresult">'.$$upload_output.'</div>';
1376: }
1377: return ($url,$needlink);
1378: }
1379:
1380: sub embedded_form_elems {
1381: my ($phase,$primaryurl) = @_;
1382: return <<STATE;
1383: <input type="hidden" name="forceedit" value="1" />
1384: <input type="hidden" name="cmd" value="upload_embedded" />
1385: <input type="hidden" name="phase" value="$phase" />
1386: <input type="hidden" name="primaryurl" value="$primaryurl" />
1387: STATE
1388: }
1389:
1390: sub return_to_editor {
1391: my ($cdom,$cnum) = @_;
1392: my $actionurl = "/public/$cdom/$cnum/syllabus";
1393: return '<p><form name="backtoeditor" method="post" action="'.$actionurl.'" />'.
1394: '<input type="hidden" name="forceedit" value="1" />'."\n".
1395: '<a href="javascript:document.backtoeditor.submit();">'.&mt('Return to Editor').
1396: '</a></p>';
1397: }
1398:
1.118 raeburn 1399: sub editfile_button {
1.122 raeburn 1400: my ($url,$context) = @_;
1401: my $edittext=&mt('Edit');
1402: my $deltext=&mt('Delete');
1.118 raeburn 1403: return <<"END";
1.122 raeburn 1404: <input type="button" value="$edittext" onclick="javascript:gotoeditor('$url');" name="edit_$context" />
1405:
1406: <input type="button" value="$deltext" onclick="javascript:dodelete('$context');" name="del_$context" />
1407: <input type="hidden" value="" name="deleteuploaded" />
1.118 raeburn 1408: END
1409: }
1410:
1411: sub editbutton_js {
1412: return <<ENDJS;
1413: <script type="text/javascript">
1414: // <![CDATA[
1.122 raeburn 1415: function gotoeditor(url) {
1416: document.location.href = url+'?editmode=1&forceedit=1';
1417: }
1418: function dodelete(caller,url) {
1419: document.syllabus.deleteuploaded.value=caller;
1420: document.syllabus.submit();
1.118 raeburn 1421: }
1422: // ]]>
1423: </script>
1424: ENDJS
1425: }
1426:
1.1 www 1427: 1;
1428: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>