File:
[LON-CAPA] /
loncom /
interface /
coursecatalog.pm
Revision
1.19:
download - view:
text,
annotated -
select for diffs
Sun Jan 14 01:59:37 2007 UTC (17 years, 7 months ago) by
raeburn
Branches:
MAIN
CVS tags:
version_2_3_X,
version_2_3_2,
version_2_3_1,
HEAD
Move &additional_machine_domains() to lonnet.pm so it is more widely available
Move determination of default domain based on $ENV{'HTTP_HOST'} from lonlogin.pm to &default_login_domain() in lonnet.pm so it is more widely available
Default domain in coursecatalog now uses lonnet::default_login_domain() to display catlog for appropriate domain on a server with multiple domains, based on URL.
Bug 5136. If course catalog is displayed by a logged in user (other than public), catalog is shown for the domain of the current user's role, unless no role is selected, in which case catalog is shown for user's domain.
Non-logged in user and public users see course catalog of the domain of the machine, as determined from lonnet:::default_login_domain().
1: # The LearningOnline Network with CAPA
2: # Handler for displaying the course catalog interface
3: #
4: # $Id: coursecatalog.pm,v 1.19 2007/01/14 01:59:37 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: package Apache::coursecatalog;
30:
31: use strict;
32: use lib qw(/home/httpd/lib/perl);
33: use Apache::Constants qw(:common);
34: use Apache::loncommon;
35: use Apache::lonhtmlcommon;
36: use Apache::lonnet;
37: use Apache::lonlocal;
38: use Apache::courseclassifier;
39: use Apache::lonacc;
40: use LONCAPA;
41:
42: sub handler {
43: my ($r) = @_;
44: &Apache::loncommon::content_type($r,'text/html');
45: $r->send_http_header;
46: if ($r->header_only) {
47: return OK;
48: }
49: my %cookies=CGI::Cookie->parse($r->header_in('Cookie'));
50: my $lonid=$cookies{'lonID'};
51: my $lonidsdir=$r->dir_config('lonIDsDir');
52: my $handle;
53: if ($lonid) {
54: $handle=&LONCAPA::clean_handle($lonid->value);
55: }
56: if ((-e "$lonidsdir/$handle.id") && ($handle ne '')) {
57: &Apache::lonnet::transfer_profile_to_env($lonidsdir,$handle);
58: }
59: &Apache::lonacc::get_posted_cgi($r);
60: &Apache::lonlocal::get_language_handle($r);
61: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['sortby']);
62: my $codedom = &Apache::lonnet::default_login_domain();
63:
64: if (($env{'user.domain'} ne '') && ($env{'user.domain'} ne 'public')) {
65: $codedom = $env{'user.domain'};
66: if ($env{'request.role.domain'} ne '') {
67: $codedom = $env{'request.role.domain'};
68: }
69: }
70: my $formname = 'coursecatalog';
71: my $domdesc = $Apache::lonnet::domaindescription{$codedom};
72:
73: &Apache::lonhtmlcommon::clear_breadcrumbs();
74: if ($env{'form.coursenum'} ne '' && &user_is_known()) {
75: &course_details($r,$codedom,$formname,$domdesc);
76: } else {
77: my $numtitles = &course_selector($r,$codedom,$formname,$domdesc);
78: if ($env{'form.state'} eq 'listing') {
79: $r->print(&print_course_listing($codedom,$numtitles).'<br />');
80: }
81: }
82: $r->print(&Apache::loncommon::end_page());
83: return OK;
84: }
85:
86: sub course_details {
87: my ($r,$codedom,$formname,$domdesc) = @_;
88: my $output;
89: my %add_entries = (topmargin => "0",
90: marginheight => "0",);
91: my $start_page =
92: &Apache::loncommon::start_page('Course Catalog','',
93: {
94: 'add_entries' => \%add_entries,
95: 'no_inline_link' => 1,});
96: $r->print($start_page);
97: if ($env{'form.numtitles'} > 0) {
98: &Apache::lonhtmlcommon::add_breadcrumb
99: ({href=>"/adm/coursecatalog",
100: text=>"Select courses"});
101: }
102: &Apache::lonhtmlcommon::add_breadcrumb
103: ({href=>"javascript:document.$formname.submit()",
104: text=>"Course listing"},
105: {text=>"Course details"});
106: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Course Details'));
107: $r->print('<br />'.&mt('Detailed course information:').'<br /><br />'.
108: '<form name="coursecatalog" method="post">'.
109: &print_course_listing($codedom).'<br /><br />');
110: $r->print('<a href = "javascript:document.coursecatalog.submit()">'.
111: &mt('Back to course listing').'</a>'.
112: '<input type="hidden" name="sortby" value="'.
113: $env{'form.sortby'}.'" />'.
114: '<input type="hidden" name="state" value="listing" /></form>');
115: }
116:
117: sub course_selector {
118: my ($r,$codedom,$formname,$domdesc) = @_;
119: my %coursecodes = ();
120: my %codes = ();
121: my @codetitles = ();
122: my %cat_titles = ();
123: my %cat_order = ();
124: my %idlist = ();
125: my %idnums = ();
126: my %idlist_titles = ();
127: my %by_year;
128: my %by_sem;
129: my %by_dept;
130: my %cat_items;
131: my $caller = 'global';
132: my $format_reply;
133: my $totcodes = 0;
134: my $jscript = '';
135: my ($numtitles,$lasttitle);
136: $totcodes = &Apache::courseclassifier::retrieve_instcodes(\%coursecodes,$codedom,$totcodes);
137: if ($totcodes > 0) {
138: $format_reply = &Apache::lonnet::auto_instcode_format($caller,$codedom,\%coursecodes,\%codes,\@codetitles,\%cat_titles,\%cat_order);
139: if ($format_reply eq 'ok') {
140: my $numtypes = @codetitles;
141: &Apache::courseclassifier::build_code_selections(\%codes,\@codetitles,\%cat_titles,\%cat_order,\%idlist,\%idnums,\%idlist_titles);
142: my ($scripttext,$longtitles) = &Apache::courseclassifier::javascript_definitions(\@codetitles,\%idlist,\%idlist_titles,\%idnums,\%cat_titles);
143: my $longtitles_str = join('","',@{$longtitles});
144: my $allidlist = $idlist{$codetitles[0]};
145: $numtitles = @codetitles;
146: $lasttitle = $numtitles;
147: if ($numtitles > 4) {
148: $lasttitle = 4;
149: }
150: if ($numtitles == 0) {
151: if (!defined($env{'form.state'})) {
152: $env{'form.state'} = 'listing';
153: }
154: } else {
155: my @data = ('top');
156: for (my $k=0; $k<$lasttitle; $k++) {
157: my $cat = $codetitles[$k];
158: my $level = 1;
159: $level = &recurse_options($codetitles[$k],$idlist{$codetitles[$k]},$level,$cat,\%cat_items,\@data,\%by_year,\%by_sem,\%by_dept);
160: }
161: $scripttext .= &build_javascript(\%by_year,\%by_sem,\%by_dept,\%cat_order,\@codetitles);
162: $jscript .= &javascript_select_filler($formname,$scripttext,\@codetitles,$longtitles_str,$allidlist);
163: if ($env{'form.state'} eq 'listing') {
164: $jscript .= '
165: function setElements() {
166: ';
167: for (my $i=0; $i<@codetitles-1; $i++) {
168: if ($env{'form.'.$codetitles[$i]} != -1) {
169: $jscript .= '
170: for (var j=0; j<document.'.$formname.'.'.$codetitles[$i].'.length; j++) {
171: if (document.'.$formname.'.'.$codetitles[$i].'[j].value == "'.$env{'form.'.$codetitles[$i]}.'") {
172: document.'.$formname.'.'.$codetitles[$i].'.selectedIndex = j;
173: }
174: }
175: ';
176: }
177: }
178: $jscript .= ' courseSet()'."\n";
179: if ($env{'form.'.$codetitles[-1]} != -1) {
180: $jscript .= '
181: for (var j=0; j<document.'.$formname.'.'.$codetitles[-1].'.length; j++) {
182: if (document.'.$formname.'.'.$codetitles[-1].'[j].value == "'.$env{'form.'.$codetitles[-1]}.'") {
183: document.'.$formname.'.'.$codetitles[-1].'.selectedIndex = j;
184: }
185: }
186: ';
187: }
188: $jscript .= '}';
189: }
190: }
191: if ($env{'form.state'} eq 'listing') {
192: $jscript .= qq|
193: function changeSort(caller) {
194: document.$formname.sortby.value = caller;
195: document.$formname.submit();
196: }
197: function setCourseId(caller) {
198: document.$formname.coursenum.value = caller;
199: document.$formname.submit();
200: }\n|;
201: }
202: }
203: my $js = '<script type"text/javascript">'."\n$jscript\n".
204: '</script>';
205: my %add_entries = (topmargin => "0",
206: marginheight => "0",);
207: if (($env{'form.state'} eq 'listing') && ($numtitles > 0)) {
208: $add_entries{'onLoad'} = 'setElements()';
209: }
210: my $start_page =
211: &Apache::loncommon::start_page('Course Catalog',$js,
212: {
213: 'add_entries' => \%add_entries,
214: 'no_inline_link' => 1,});
215: $r->print($start_page);
216: if ($env{'form.state'} eq 'listing') {
217: if ($numtitles > 0) {
218: &Apache::lonhtmlcommon::add_breadcrumb
219: ({href=>"/adm/coursecatalog",
220: text=>"Select courses"},
221: {text=>"Course listing"});
222: } else {
223: &Apache::lonhtmlcommon::add_breadcrumb
224: ({text=>"Course listing"});
225: }
226: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Course Listing'));
227: } else {
228: &Apache::lonhtmlcommon::add_breadcrumb
229: ({href=>"/adm/coursecatalog",
230: text=>"Select courses"});
231: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Select courses'));
232: }
233: $r->print('<h3>'.&mt('Display information about official [_1] classes for which LON-CAPA courses have been created:',$domdesc).'</h3>');
234: $r->print('<form name="coursecatalog" method="post">');
235: if ($numtitles > 0) {
236: $r->print(&mt('<b>Choose which course(s) to list.</b><br />'));
237: $r->print('<table><tr>');
238: for (my $k=0; $k<$lasttitle-1; $k++) {
239: my @unsorted = @{$cat_items{$codetitles[$k]}};
240: my @items;
241: &Apache::courseclassifier::sort_cats($k,\%cat_order,\@codetitles,\@unsorted,\@items);
242: my @longitems;
243: if (defined($cat_titles{$codetitles[$k]})) {
244: foreach my $item (@items) {
245: push(@longitems,$cat_titles{$codetitles[$k]}{$item});
246: }
247: } else {
248: @longitems = @items;
249: }
250: $r->print('<td align="center">'.$codetitles[$k].'<br />'."\n".
251: '<select name="'.$codetitles[$k].'" onChange="courseSet()"');
252: $r->print('>'."\n".'<option value="0" />All'."\n");
253: for (my $i=0; $i<@items; $i++) {
254: if ($longitems[$i] eq '') {
255: $longitems[$i] = $items[$i];
256: }
257: $r->print(' <option value="'.$items[$i].'">'.$longitems[$i].'</option>');
258: }
259: $r->print('</select></td>');
260: }
261: $r->print('<td align="center">'.$codetitles[$lasttitle-1].'<br />'."\n".
262: '<select name="'.$codetitles[$lasttitle-1].'">'."\n".
263: '<option value="0">All'."\n".
264: '</option>'."\n".'</select>'."\n".
265: '</td>'
266: );
267: if (&user_is_dc($codedom)) {
268: my $showdetails_status;
269: if ($env{'form.showdetails'}) {
270: $showdetails_status = 'checked="checked" ';
271: }
272: $r->print('<td></td><td><input type="checkbox" name="showdetails" value="1" '.$showdetails_status.'/>'.&mt('Show full details for each course (DC only)').'</td>');
273: }
274: $r->print('</tr></table>');
275: if ($numtitles > 4) {
276: $r->print('<br /><br />'.$codetitles[$numtitles-1].'<br />'."\n".
277: '<input type="text" name="'.$codetitles[$numtitles-1].'" /><br />'."\n");
278: }
279: $r->print('<br />');
280: }
281: $r->print('<input type="hidden" name="coursenum" value="" /><input type="hidden" name="sortby" value="" /><input type="hidden" name="state" value="listing" />');
282: if ($numtitles > 0) {
283: $r->print('<input type="submit" name="catalogfilter" value="'.&mt('Display courses').'" />');
284: }
285: $r->print('<input type="hidden" name="numtitles" value="'.
286: $numtitles.'" /></form>');
287: if (($numtitles > 0) && ($env{'form.state'} eq 'listing')) {
288: $r->print('<br /><br />');
289: }
290: } else {
291: $r->print(&Apache::loncommon::start_page('Course Catalog','',
292: {
293: 'no_inline_link' => 1,}));
294: $r->print('<br />'.&mt('No official courses to display for [_1].',$domdesc));
295: }
296: return $numtitles;
297: }
298:
299: sub user_is_dc {
300: my ($codedom) = @_;
301: if (exists($env{'user.role.dc./'.$codedom.'/'})) {
302: my $livedc = 1;
303: my $now = time;
304: my ($start,$end)=split(/\./,$env{'user.role.dc./'.$codedom.'/'});
305: if ($start && $start>$now) { $livedc = 0; }
306: if ($end && $end <$now) { $livedc = 0; }
307: return $livedc;
308: }
309: return;
310: }
311:
312: sub recurse_options {
313: my ($currkey,$currlist,$level,$cat,$cat_options,$data,$by_year,$by_sem,$by_dept) = @_;
314: if (ref($currlist) eq 'HASH') {
315: $level ++;
316: foreach my $key (sort(keys(%{$currlist}))) {
317: $$data[$level-1]= $key;
318: &recurse_options($key,$currlist->{$key},$level,$cat,$cat_options,$data,$by_year,$by_sem,$by_dept);
319: }
320: } else {
321: $level --;
322: my @contents = split(/","/,$currlist);
323: foreach my $item (@contents) {
324: if (!grep(/^\Q$item\E$/,@{$cat_options->{$cat}})) {
325: push(@{$cat_options->{$cat}},$item);
326: }
327: if ($level == 3) {
328: if (!grep/^\Q$item\E$/,@{$by_year->{$data->[1]}->{$currkey}}) {
329: push(@{$by_year->{$data->[1]}->{$currkey}},$item);
330: }
331: if (!grep/^\Q$item\E$/,@{$by_sem->{$data->[2]}->{$currkey}}) {
332: push(@{$by_sem->{$data->[2]}->{$currkey}},$item);
333: }
334: if (!grep/^\Q$item\E$/,@{$by_dept->{$currkey}}) {
335: push(@{$by_dept->{$currkey}},$item);
336: }
337:
338: }
339: }
340: }
341: return $level;
342: }
343:
344: sub build_javascript {
345: my ($by_year,$by_sem,$by_dept,$cat_order,$codetitles) = @_;
346: my @unsorted = keys(%{$by_year});
347: my @sorted_yrs;
348: &Apache::courseclassifier::sort_cats('0',$cat_order,$codetitles,\@unsorted,\@sorted_yrs);
349: my $output = 'var idcse_by_yr_year = new Array("'.join('","',@sorted_yrs).'");'."\n".
350: 'var idcse_by_yr_dept = new Array('.scalar(@sorted_yrs).');'."\n".
351: 'var idcse_by_yr_num = new Array('.scalar(@sorted_yrs).');'."\n";
352: for (my $i=0; $i<@sorted_yrs; $i++) {
353: my $numkeys = keys(%{$by_year->{$sorted_yrs[$i]}});
354: $output .= " idcse_by_yr_num[$i] = new Array($numkeys);\n";
355: if (ref($by_year->{$sorted_yrs[$i]}) eq 'HASH') {
356: @unsorted = keys(%{$by_year->{$sorted_yrs[$i]}});
357: my @sorted_depts;
358: &Apache::courseclassifier::sort_cats('2',$cat_order,$codetitles,\@unsorted,\@sorted_depts);
359: $output .= qq| idcse_by_yr_dept[$i] = new Array ("|.join('","',@sorted_depts).'");'."\n";
360: for (my $j=0; $j<@sorted_depts; $j++) {
361: $output .= qq| idcse_by_yr_num[$i][$j] = new Array ("|;
362: $output .= join('","',sort(@{$by_year->{$sorted_yrs[$i]}->{$sorted_depts[$j]}})).'");'."\n";
363: }
364: }
365: }
366: @unsorted = keys(%{$by_sem});
367: my @sorted_sems;
368: &Apache::courseclassifier::sort_cats('1',$cat_order,$codetitles,\@unsorted,\@sorted_sems);
369: $output .= 'idcse_by_sem_sems = new Array("'.join('","',@sorted_sems).'");'."\n".
370: 'idcse_by_sem_dept = new Array('.scalar(@sorted_sems).');'."\n".
371: 'idcse_by_sem_num = new Array('.scalar(@sorted_sems).');'."\n";
372: for (my $i=0; $i<@sorted_sems; $i++) {
373: my $numkeys = keys(%{$by_sem->{$sorted_sems[$i]}});
374: $output .= " idcse_by_sem_num[$i] = new Array($numkeys);\n";
375: if (ref($by_sem->{$sorted_sems[$i]}) eq 'HASH') {
376: @unsorted = keys(%{$by_sem->{$sorted_sems[$i]}});
377: my @sorted_depts;
378: &Apache::courseclassifier::sort_cats('2',$cat_order,$codetitles,\@unsorted,\@sorted_depts);
379: $output .= qq| idcse_by_sem_dept[$i] = new Array("|.join('","',@sorted_depts).'");'."\n";
380: for (my $j=0; $j<@sorted_depts; $j++) {
381: $output .= qq| idcse_by_sem_num[$i][$j] = new Array ("|.join('","',sort(@{$by_sem->{$sorted_sems[$i]}->{$sorted_depts[$j]}})).'");'."\n";
382: }
383: }
384: }
385: @unsorted = keys(%{$by_dept});
386: my @sorted_deps;
387: &Apache::courseclassifier::sort_cats('2',$cat_order,$codetitles,\@unsorted,\@sorted_deps);
388: $output .= 'idcse_by_dep = new Array('.scalar(@sorted_deps).');'."\n";
389: for (my $k=0; $k<@sorted_deps; $k++) {
390: $output .= qq| idcse_by_dep[$k] = new Array ("|.join('","',sort(@{$by_dept->{$sorted_deps[$k]}})).'");'."\n";
391: }
392: return $output;
393: }
394:
395: sub search_courselist {
396: my ($domain,$numtitles) = @_;
397: my $instcode;
398: if (defined($numtitles) && $numtitles == 0) {
399: $instcode = '.+';
400: } else {
401: my (%codedefaults,@code_order);
402: my $defaults_result =
403: &Apache::lonnet::auto_instcode_defaults($domain,\%codedefaults,
404: \@code_order);
405: if ($defaults_result eq 'ok') {
406: $instcode ='^';
407: foreach my $item (@code_order) {
408: if ($env{'form.'.$item} eq '0' ) {
409: $instcode .= $codedefaults{$item};
410: } else {
411: $instcode .= $env{'form.'.$item};
412: }
413: }
414: $instcode .= '$';
415: } else {
416: $instcode = '.';
417: }
418: }
419: my %courses = &Apache::lonnet::courseiddump($domain,'.',1,$instcode,'.','.',
420: undef,undef,'Course',1);
421: return %courses;
422: }
423:
424:
425: sub print_course_listing {
426: my ($domain,$numtitles) = @_;
427: my $output;
428: my %courses;
429: my $knownuser = &user_is_known();
430: my $details = $env{'form.coursenum'};
431: if (&user_is_dc($domain)) {
432: if ($env{'form.showdetails'}) {
433: $details = 1;
434: }
435: }
436: if ($env{'form.coursenum'} ne '') {
437: %courses = &Apache::lonnet::courseiddump($domain,'.',1,'.','.',
438: $env{'form.coursenum'},
439: undef,undef,'Course');
440: if (keys(%courses) == 0) {
441: $output .= &mt('The courseID provided does not match a course in this domain.');
442: return $output;
443: }
444: } else {
445: %courses = &search_courselist($domain,$numtitles);
446: if (keys(%courses) == 0) {
447: $output = &mt('No courses match the criteria you selected.');
448: return $output;
449: }
450: if ($knownuser && !$env{'form.showdetails'}) {
451: $output = &mt('<b>Note for students:</b> If you are officially enrolled in a course but the course is not listed in your LON-CAPA courses, click the "Show more details" link for the specific course and check the default access dates and/or automated enrollment settings.<br /><br />');
452: }
453: }
454: $output .= &construct_data_table($knownuser,\%courses,$details);
455: $output .= &Apache::lonhtmlcommon::echo_form_input(['coursenum','state','catalogfilter','sortby','showdetails']);
456: return $output;
457: }
458:
459: sub construct_data_table {
460: my ($knownuser,$courses,$details,$usersections) = @_;
461: my %sortname;
462: if (($details eq '') || ($env{'form.showdetails'})) {
463: $sortname{'Code'} = 'code';
464: $sortname{'Title'} = 'title';
465: $sortname{'Owner'} = 'owner';
466: }
467: my $output = &Apache::loncommon::start_data_table().
468: &Apache::loncommon::start_data_table_header_row();
469: my @coltitles = ('Code','Sections','Crosslisted','Title','Owner');
470: if (ref($usersections) eq 'HASH') {
471: $coltitles[1] = 'Your Section';
472: }
473: foreach my $item (@coltitles) {
474: $output .= '<th>';
475: if (defined($sortname{$item})) {
476: $output .= '<a href="javascript:changeSort('."'$sortname{$item}'".')">'.&mt($item).'</a>';
477: } else {
478: $output .= &mt($item);
479: }
480: $output .= '</th>';
481: }
482: if ($knownuser) {
483: if ($details) {
484: $output .=
485: '<th>'.&mt('Default Access Dates for Students').'</th>'.
486: '<th>'.&mt('Student Counts').'</th>'.
487: '<th>'.&mt('Auto-enrollment of <br />registered students').'</th>';
488: } else {
489: $output .= '<th> </th>';
490: }
491: }
492: &Apache::loncommon::end_data_table_header_row();
493: my %courseinfo = &build_courseinfo_hash($courses,$knownuser,$details,
494: $usersections);
495: my %Sortby;
496: foreach my $course (sort(keys(%{$courses}))) {
497: if ($env{'form.sortby'} eq 'code') {
498: push(@{$Sortby{$courseinfo{$course}{'code'}}},$course);
499: } elsif ($env{'form.sortby'} eq 'owner') {
500: push(@{$Sortby{$courseinfo{$course}{'ownerlastname'}}},$course);
501: } else {
502: push(@{$Sortby{$courseinfo{$course}{'title'}}},$course);
503: }
504: }
505: my @sorted_courses;
506: if (($env{'form.sortby'} eq 'code') || ($env{'form.sortby'} eq 'owner')) {
507: @sorted_courses = sort(keys(%Sortby));
508: } else {
509: @sorted_courses = sort { lc($a) cmp lc($b) } (keys(%Sortby));
510: }
511: foreach my $item (@sorted_courses) {
512: foreach my $course (@{$Sortby{$item}}) {
513: $output.=&Apache::loncommon::start_data_table_row();
514: $output.=&courseinfo_row($courseinfo{$course},$knownuser,$details);
515: $output.=&Apache::loncommon::end_data_table_row();
516: }
517: }
518: $output .= &Apache::loncommon::end_data_table();
519: return $output;
520: }
521:
522: sub build_courseinfo_hash {
523: my ($courses,$knownuser,$details,$usersections) = @_;
524: my %courseinfo;
525: my $now = time;
526: foreach my $course (keys(%{$courses})) {
527: my $descr;
528: if ($courses->{$course} =~ m/^([^:]*):/i) {
529: $descr = &unescape($1);
530: } else {
531: $descr = &unescape($courses->{$course});
532: }
533: my $cleandesc=&HTML::Entities::encode($descr,'<>&"');
534: $cleandesc=~s/'/\\'/g;
535: $cleandesc =~ s/^\s+//;
536: my ($cdom,$cnum)=split(/\_/,$course);
537:
538: my ($desc,$instcode,$owner,$ttype) = split(/:/,$courses->{$course});
539: $owner = &unescape($owner);
540: my ($ownername,$ownerdom);
541: if ($owner =~ /:/) {
542: ($ownername,$ownerdom) = split(/:/,$owner);
543: } else {
544: $ownername = $owner;
545: if ($owner ne '') {
546: $ownerdom = $cdom;
547: }
548: }
549: my %ownernames;
550: if ($ownername ne '' && $ownerdom ne '') {
551: %ownernames = &Apache::loncommon::getnames($ownername,$ownerdom);
552: }
553: $courseinfo{$course}{'cdom'} = $cdom;
554: $courseinfo{$course}{'cnum'} = $cnum;
555: $courseinfo{$course}{'code'} = $instcode;
556: $courseinfo{$course}{'ownerlastname'} = $ownernames{'lastname'};
557: $courseinfo{$course}{'title'} = $cleandesc;
558: $courseinfo{$course}{'owner'} = $owner;
559:
560: my %coursehash = &Apache::lonnet::dump('environment',$cdom,$cnum);
561: my @classids;
562: my @crosslistings;
563: my ($seclist,$numsec) =
564: &identify_sections($coursehash{'internal.sectionnums'});
565: if (ref($usersections) eq 'HASH') {
566: if (ref($usersections->{$course}) eq 'ARRAY') {
567: $seclist = join(', ',@{$usersections->{$course}});
568: }
569: }
570: $courseinfo{$course}{'seclist'} = $seclist;
571: my ($xlist_items,$numxlist) =
572: &identify_sections($coursehash{'internal.crosslistings'});
573: my $showsyllabus = 1; # default is to include a syllabus link
574: if (defined($coursehash{'showsyllabus'})) {
575: $showsyllabus = $coursehash{'showsyllabus'};
576: }
577: $courseinfo{$course}{'showsyllabus'} = $showsyllabus;
578: if (((defined($env{'form.coursenum'}) && ($cnum eq $env{'form.coursenum'}))) ||
579: ($knownuser && ($details == 1))) {
580: $courseinfo{$course}{'counts'} = &count_students($cdom,$cnum,$numsec);
581: $courseinfo{$course}{'autoenrollment'} =
582: &autoenroll_info(\%coursehash,$now,$seclist,$xlist_items,
583: $instcode,$owner,$cdom,$cnum);
584:
585: my $startaccess = '';
586: my $endaccess = '';
587: my $accessdates;
588: if ( defined($coursehash{'default_enrollment_start_date'}) ) {
589: $startaccess = &Apache::lonlocal::locallocaltime($coursehash{'default_enrollment_start_date'});
590: }
591: if ( defined($coursehash{'default_enrollment_end_date'}) ) {
592: $endaccess = &Apache::lonlocal::locallocaltime($coursehash{'default_enrollment_end_date'});
593: if ($coursehash{'default_enrollment_end_date'} == 0) {
594: $endaccess = "No ending date";
595: }
596: }
597: if ($startaccess) {
598: $accessdates .= &mt('<i>From:</i> ').$startaccess.'<br />';
599: }
600: if ($endaccess) {
601: $accessdates .= &mt('<i>To:</i> ').$endaccess.'<br />';
602: }
603: $courseinfo{$course}{'access'} = $accessdates;
604: }
605: if ($xlist_items eq '') {
606: $xlist_items = &mt('No');
607: }
608: $courseinfo{$course}{'xlist'} = $xlist_items;
609: }
610: return %courseinfo;
611: }
612:
613: sub count_students {
614: my ($cdom,$cnum,$numsec) = @_;
615: my $classlist = &Apache::loncoursedata::get_classlist($cdom,$cnum);
616: my %student_count = (
617: Active => 0,
618: Future => 0,
619: Expired => 0,
620: );
621: my %idx;
622: $idx{'status'} = &Apache::loncoursedata::CL_STATUS();
623: my %status_title = &Apache::lonlocal::texthash(
624: Expired => 'Previous access',
625: Active => 'Current access',
626: Future => 'Future access',
627: );
628:
629: while (my ($student,$data) = each(%$classlist)) {
630: $student_count{$data->[$idx{'status'}]} ++;
631: }
632:
633: my $countslist = &mt('[quant,_1,section]',$numsec).':<br />';
634: foreach my $status ('Active','Future') {
635: $countslist .= '<nobr>'.$status_title{$status}.': '.
636: $student_count{$status}.'</nobr><br />';
637: }
638: return $countslist;
639: }
640:
641: sub courseinfo_row {
642: my ($info,$knownuser,$details) = @_;
643: my ($cdom,$cnum,$title,$ownerlast,$code,$owner,$seclist,$xlist_items,
644: $accessdates,$showsyllabus,$counts,$autoenrollment,$output);
645: if (ref($info) eq 'HASH') {
646: $cdom = $info->{'cdom'};
647: $cnum = $info->{'cnum'};
648: $title = $info->{'title'};
649: $ownerlast = $info->{'ownerlastname'};
650: $code = $info->{'code'};
651: $owner = $info->{'owner'};
652: $seclist = $info->{'seclist'};
653: $xlist_items = $info->{'xlist'};
654: $accessdates = $info->{'access'};
655: $counts = $info->{'counts'};
656: $autoenrollment = $info->{'autoenrollment'};
657: $showsyllabus = $info->{'showsyllabus'};
658: } else {
659: $output = '<td colspan="8">'.&mt('No information available for [_1].',
660: $code).'</td>';
661: return $output;
662: }
663: $output .= '<td>'.$code.'</td>'.
664: '<td>'.$seclist.'</td>'.
665: '<td>'.$xlist_items.'</td>'.
666: '<td>'.$title.' <font size="-2">';
667: if ($showsyllabus) {
668: $output .= &Apache::loncommon::syllabuswrapper(&mt('Syllabus'),$cnum,$cdom);
669: } else {
670: $output .= ' ';
671: }
672: $output .= '</font></td>'.
673: '<td>'.$ownerlast.'</td>';
674: if ($knownuser) {
675: if ($details) {
676: $output .=
677: '<td>'.$accessdates.'</td>'.
678: '<td>'.$counts.'</td>'.
679: '<td>'.$autoenrollment.'</td>';
680: } else {
681: $output .= "<td><a href=\"javascript:setCourseId('$cnum')\">".&mt('Show more details').'</a></td>';
682: }
683: }
684: return $output;
685: }
686:
687: sub identify_sections {
688: my ($seclist) = @_;
689: my @secnums;
690: if ($seclist =~ /,/) {
691: my @sections = split(/,/,$seclist);
692: foreach my $sec (@sections) {
693: $sec =~ s/:[^:]*$//;
694: push(@secnums,$sec);
695: }
696: } else {
697: if ($seclist =~ m/^([^:]+):/) {
698: my $sec = $1;
699: if (!grep(/^\Q$sec\E$/,@secnums)) {
700: push(@secnums,$sec);
701: }
702: }
703: }
704: @secnums = sort {$a <=> $b} @secnums;
705: my $seclist = join(', ',@secnums);
706: my $numsec = @secnums;
707: return ($seclist,$numsec);
708: }
709:
710: sub get_valid_classes {
711: my ($seclist,$xlist_items,$crscode,$owner,$cdom,$cnum) = @_;
712: my $response;
713: my %validations;
714: @{$validations{'sections'}} = ();
715: @{$validations{'xlists'}} = ();
716: my $totalitems = 0;
717: if ($seclist) {
718: foreach my $sec (split(/, /,$seclist)) {
719: my $class = $crscode.$sec;
720: if (&Apache::lonnet::auto_validate_class_sec($cdom,$cnum,$owner,
721: $class) eq 'ok') {
722: if (!grep(/^\Q$sec$\E/,@{$validations{'sections'}})) {
723: push(@{$validations{'sections'}},$sec);
724: $totalitems ++;
725: }
726: }
727: }
728: }
729: if ($xlist_items) {
730: foreach my $item (split(/, /,$xlist_items)) {
731: if (&Apache::lonnet::auto_validate_class_sec($cdom,$cnum,$owner,
732: $item) eq 'ok') {
733: if (!grep(/^\Q$item$\E/,@{$validations{'xlists'}})) {
734: push(@{$validations{'xlists'}},$item);
735: $totalitems ++;
736: }
737: }
738: }
739: }
740: if ($totalitems > 0) {
741: if (@{$validations{'sections'}}) {
742: $response = &mt('Sections: ').
743: join(', ',@{$validations{'sections'}}).'<br />';
744: }
745: if (@{$validations{'xlists'}}) {
746: $response .= &mt('Courses: ').
747: join(', ',@{$validations{'xlists'}});
748: }
749: }
750: return $response;
751: }
752:
753: sub javascript_select_filler {
754: my ($formname,$scripttext,$codetitles,$longtitles_str,$allidlist) = @_;
755: my $output = <<END;
756: function courseSet() {
757: var longtitles = new Array ("$longtitles_str");
758: var valyr = document.$formname.Year.options[document.$formname.Year.selectedIndex].value
759: var valsem = document.$formname.Semester.options[document.$formname.Semester.selectedIndex].value
760: var valdept = document.$formname.Department.options[document.$formname.Department.selectedIndex].value
761: var valclass = document.$formname.Number.options[document.$formname.Number.selectedIndex].value
762: var idyears = new Array("$allidlist");
763: var idyr = -1;
764: var idsem = -1;
765: var iddept = -1;
766: document.$formname.Number.length = 0;
767:
768: $scripttext
769:
770: selYear = document.$formname.Year.selectedIndex-1;
771: selSemester = document.$formname.Semester.selectedIndex-1;
772: selDepartment = document.$formname.Department.selectedIndex-1;
773: if (selYear == -1) {
774: if (selSemester == -1) {
775: if (selDepartment > -1) {
776: document.$formname.Number.options[0] = new Option('All','0',false,false);
777: for (var k=0; k<idcse_by_dep[selDepartment].length; k++) {
778: document.$formname.Number.options[k+1] = new Option(idcse_by_dep[selDepartment][k],idcse_by_dep[selDepartment][k],false,false);
779:
780: }
781: }
782: else {
783: document.$formname.Number.options[0] = new Option("All","0",true,true);
784: }
785: }
786: else {
787: if (selDepartment > -1) {
788: for (var i=0; i<idcse_by_sem_sems.length; i++) {
789: if (idcse_by_sem_sems[i] == valsem) {
790: idsem = i;
791: }
792: }
793: if (idsem != -1) {
794: for (var i=0; i<idcse_by_sem_dept[idsem].length; i++) {
795: if (idcse_by_sem_dept[idsem][i] == valdept) {
796: iddept = i;
797: }
798: }
799: }
800: if (iddept != -1) {
801: document.$formname.Number.options[0] = new Option('All','0',false,false);
802: for (var k=0; k<idcse_by_sem_num[idsem][iddept].length; k++) {
803: document.$formname.Number.options[k+1] = new Option(idcse_by_sem_num[idsem][iddept][k],idcse_by_sem_num[idsem][iddept][k],false,false);
804: }
805: }
806: else {
807: document.$formname.Number.options[0] = new Option('No courses','0',true,true);
808: }
809: }
810: else {
811: document.$formname.Number.options[0] = new Option("All","0",true,true);
812: }
813: }
814: }
815: else {
816: if (selSemester == -1) {
817: if (selDepartment > -1) {
818: for (var i=0; i<idcse_by_yr_year.length; i++) {
819: if (idcse_by_yr_year[i] == valyr) {
820: idyr = i;
821: }
822: }
823: if (idyr != -1) {
824: for (var i=0; i<idcse_by_yr_dept[idyr].length; i++) {
825: if (idcse_by_yr_dept[idyr][i] == valdept) {
826: iddept = i;
827: }
828: }
829: }
830: if (iddept != -1) {
831: document.$formname.Number.options[0] = new Option('All','0',false,false);
832: for (var k=0; k<idcse_by_yr_num[idyr][iddept].length; k++) {
833: document.$formname.Number.options[k+1] = new Option(idcse_by_yr_num[idyr][iddept][k],idcse_by_yr_num[idyr][iddept][k],false,false);
834: }
835: }
836: else {
837: document.$formname.Number.options[0] = new Option('No courses','0',true,true);
838: }
839: }
840: else {
841: document.$formname.Number.options[0] = new Option("All","0",true,true);
842: }
843: }
844: else {
845: if (selDepartment > -1) {
846: for (var k=0; k<idyears.length; k++) {
847: if (idyears[k] == valyr) {
848: idyr = k;
849: }
850: }
851: if (idyr != -1) {
852: for (var k=0; k<idsems[idyr].length; k++) {
853: if (idsems[idyr][k] == valsem) {
854: idsem = k;
855: }
856: }
857: }
858: if (idsem != -1) {
859: for (var k=0; k<idcodes[idyr][idsem].length; k++) {
860: if (idcodes[idyr][idsem][k] == valdept) {
861: iddept = k;
862: }
863: }
864: }
865: if (iddept != -1) {
866: document.$formname.Number.options[0] = new Option('All','0',false,false);
867: for (var i=0; i<idcourses[idyr][idsem][iddept].length; i++) {
868: var display = idcourses[idyr][idsem][iddept][i];
869: if (longtitles[3] == 1) {
870: if (idcourseslongs[idyr][idsem][iddept][i] != "") {
871: display = idcourseslongs[idyr][idsem][iddept][i]
872: }
873: }
874: document.$formname.Number.options[i+1] = new Option(display,idcourses[idyr][idsem][iddept][i],false,false)
875: }
876: }
877: else {
878: document.$formname.Number.options[0] = new Option('No courses','0',true,true);
879: }
880: }
881: else {
882: document.$formname.Number.options[0] = new Option('All','0',true,true);
883: }
884: }
885: document.$formname.Number.selectedIndex = 0
886: }
887: }
888: END
889: return $output;
890: }
891:
892: sub autoenroll_info {
893: my ($coursehash,$now,$seclist,$xlist_items,$code,$owner,$cdom,$cnum) = @_;
894: my $autoenrolldates = &mt('Not enabled');
895: if (defined($coursehash->{'internal.autoadds'}) && $coursehash->{'internal.autoadds'} == 1) {
896: my ($autostart,$autoend);
897: if ( defined($coursehash->{'internal.autostart'}) ) {
898: $autostart = &Apache::lonlocal::locallocaltime($coursehash->{'internal.autostart'});
899: }
900: if ( defined($coursehash->{'internal.autoend'}) ) {
901: $autoend = &Apache::lonlocal::locallocaltime($coursehash->{'internal.autoend'});
902: }
903: if ($coursehash->{'internal.autostart'} > $now) {
904: if ($coursehash->{'internal.autoend'} && $coursehash->{'internal.autoend'} < $now) {
905: $autoenrolldates = &mt('Not enabled');
906: } else {
907: my $valid_classes =
908: &get_valid_classes($seclist,$xlist_items,$code,
909: $owner,$cdom,$cnum);
910: if ($valid_classes ne '') {
911: $autoenrolldates = &mt('Not enabled<br />Starts: ').
912: $autostart.'<br />'.$valid_classes; }
913: }
914: } else {
915: if ($coursehash->{'internal.autoend'} && $coursehash->{'internal.autoend'} < $now) {
916: $autoenrolldates = &mt('Not enabled<br />Ended: ').$autoend;
917: } else {
918: my $valid_classes = &get_valid_classes($seclist,$xlist_items,
919: $code,$owner,$cdom,$cnum);
920: if ($valid_classes ne '') {
921: $autoenrolldates = &mt('Currently enabled<br />').
922: $valid_classes;
923: }
924: }
925: }
926: }
927: return $autoenrolldates;
928: }
929:
930: sub user_is_known {
931: my $known = 0;
932: if ($env{'user.name'} ne '' && $env{'user.name'} ne 'public'
933: && $env{'user.domain'} ne '' && $env{'user.domain'} ne 'public') {
934: $known = 1;
935: }
936: return $known;
937: }
938:
939: 1;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>