--- loncom/interface/coursecatalog.pm 2014/04/28 22:12:55 1.84 +++ loncom/interface/coursecatalog.pm 2019/07/19 13:18:27 1.88.2.4 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler for displaying the course catalog interface # -# $Id: coursecatalog.pm,v 1.84 2014/04/28 22:12:55 raeburn Exp $ +# $Id: coursecatalog.pm,v 1.88.2.4 2019/07/19 13:18:27 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -38,6 +38,7 @@ use Apache::lonlocal; use Apache::courseclassifier; use Apache::lonacc; use LONCAPA; +use LONCAPA::lonauthcgi; sub handler { my ($r) = @_; @@ -79,15 +80,19 @@ sub handler { my %domconfig = &Apache::lonnet::get_dom('configuration',['coursecategories'],$codedom); my $knownuser = &user_is_known(); - + my $canviewall = &canview_all($knownuser,$codedom); + my ($cathash,$cattype); if (ref($domconfig{'coursecategories'}) eq 'HASH') { $cathash = $domconfig{'coursecategories'}{'cats'}; - if ($knownuser) { + if ($knownuser || $canviewall) { $cattype = $domconfig{'coursecategories'}{'auth'}; } else { $cattype = $domconfig{'coursecategories'}{'unauth'}; } + if ($cattype eq '') { + $cattype = 'std'; + } } else { $cathash = {}; $cattype = 'std'; @@ -98,7 +103,7 @@ sub handler { ({href=>"/adm/coursecatalog", text=>"Course/Community Catalog"}); $r->print(&Apache::lonhtmlcommon::breadcrumbs('Course/Community Catalog')); - if ($knownuser) { + if ($knownuser || $canviewall) { $r->print('
'.&mt('No catalog of LON-CAPA courses/communities is provided for: [_1]',$domdesc).'
'); } else { if ($domconfig{'coursecategories'}{'auth'} eq 'none') { @@ -146,8 +151,8 @@ sub handler { my %courses = &Apache::lonnet::courseiddump($codedom,'.',1,'.','.', $cnum,undef,undef,'.',1); if (keys(%courses)) { - $env{'form.coursenum'} = $cnum; - my %courseinfo = &build_courseinfo_hash(\%courses,$knownuser,$codedom); + $env{'form.coursenum'} = $cnum; + my %courseinfo = &build_courseinfo_hash(\%courses,$knownuser,$codedom,$canviewall); undef($env{'form.coursenum'}); if (ref($courseinfo{$codedom.'_'.$cnum}) eq 'HASH') { $r->print(&Apache::lonhtmlcommon::start_pick_box()); @@ -202,21 +207,31 @@ sub handler { $r->print('
'.&Apache::loncommon::end_page()); return OK; } else { - if ($env{'form.coursenum'}) { - $cnum = $env{'form.coursenum'}; + if ($env{'form.coursenum'} ne '') { + if ($env{'form.coursenum'} =~ /^$LONCAPA::match_courseid$/) { + $cnum = $env{'form.coursenum'}; + } else { + delete($env{'form.coursenum'}); + } } } - if ($env{'form.catalog_maxdepth'} ne '') { - $env{'form.catalog_maxdepth'} =~ s{\D}{}g; - } - - my (@cats,@trails,%allitems,%idx,@jsarray,%subcathash,$subcats); + my (@cats,@trails,%allitems,%idx,@jsarray,%subcathash,$subcats,%maxd, + $toplevelstr,$maxdepthstr); if ($env{'form.withsubcats'}) { $subcats = \%subcathash; } &Apache::loncommon::extract_categories($cathash,\@cats,\@trails,\%allitems, - \%idx,\@jsarray,$subcats); + \%idx,\@jsarray,$subcats,\%maxd); + if (ref($cats[0]) eq 'ARRAY') { + foreach my $item (@{$cats[0]}) { + $toplevelstr .= "'".&js_escape($item)."::0',"; + $maxdepthstr .= "'$maxd{$item}',"; + } + $toplevelstr =~ s/,$//; + $maxdepthstr =~ s/,$//; + } + &validate_input(\@cats,\%maxd); my ($numtitles,@codetitles); if (($env{'form.coursenum'} ne '') && ($knownuser)) { &course_details($r,$codedom,$formname,$domdesc,\@trails,\%allitems,\@codetitles); @@ -226,9 +241,29 @@ sub handler { my $catjs = <<"ENDSCRIPT"; function setCatDepth(depth) { - document.coursecats.catalog_maxdepth.value = depth; - if (depth == '') { + var depth = parseInt(depth); + if (depth !== NaN) { + if (depth > 0) { + var possmaxd = 0; + var toplevel = new Array($toplevelstr); + var maxdepths = new Array($maxdepthstr); + if (toplevel.length) { + for (var i=0; i possmaxd) { + depth = possmaxd; + } + } + document.coursecats.catalog_maxdepth.value = depth; + } else { document.coursecats.currcat_0.value = ''; + document.coursecats.catalog_maxdepth.value = ''; } document.coursecats.submit(); return; @@ -246,7 +281,7 @@ function setCourseId(caller) { ENDSCRIPT $catjs .= &courselink_javascript(); - if (&user_is_dc($codedom)) { + if (&user_is_dc($codedom) || $canviewall) { $catjs .= <print(&print_course_listing($codedom,$numtitles,undef,undef,undef, - \@codetitles)); + \@codetitles,$canviewall)); } } else { my (%add_entries); @@ -290,6 +325,7 @@ ENDTOGGJS if (!$deeper) { $alert = &mt('Choose a category to display'); } + &js_escape(\$alert); $catjs .= <print('
'. - &additional_filters($codedom,$has_subcats)."\n"); + &additional_filters($codedom,$has_subcats,$canviewall)."\n"); $r->print(''."\n"); for (my $i=0; $i<$deeper; $i++) { @@ -325,7 +361,8 @@ ENDJS $display_button.'" />


'); } if ($env{'form.state'} eq 'listing') { - $r->print(&print_course_listing($codedom,undef,\@trails,\%allitems,$subcats,\@codetitles)); + $r->print(&print_course_listing($codedom,undef,\@trails,\%allitems,$subcats,\@codetitles, + $canviewall)); } } } @@ -333,6 +370,67 @@ ENDJS return OK; } +sub validate_input { + my ($cats,$maxd) = @_; + my $currcat = ''; + my $depth = 0; + if ($env{'form.catalog_maxdepth'} ne '') { + $env{'form.catalog_maxdepth'} =~ s{\D}{}g; + } + if ((ref($cats) eq 'ARRAY') && (ref($maxd) eq 'HASH')) { + if (ref($cats->[0]) eq 'ARRAY') { + if (@{$cats->[0]} == 1) { + if ($cats->[0][0] eq 'instcode') { + $currcat = 'instcode::0'; + } elsif ($cats->[0][0] eq 'communities') { + $currcat = 'communities::0'; + } elsif ($cats->[0][0] eq 'placement') { + $currcat = 'placement::0'; + } else { + my $name = $cats->[0][0]; + $currcat = &escape($name).'::0'; + } + if (exists($maxd->{$cats->[0][0]})) { + if ($env{'form.catalog_maxdepth'} <= $maxd->{$cats->[0][0]}) { + $depth = $env{'form.catalog_maxdepth'}; + } else { + $depth = $maxd->{$cats->[0][0]}; + } + } + } elsif ((@{$cats->[0]} > 1) && ($env{'form.currcat_0'} ne '')) { + my ($escname) = ($env{'form.currcat_0'} =~ /^([^:]+)\:\:0$/); + if ($escname =~ /^instcode|communities|placement$/) { + $currcat = $env{'form.currcat_0'}; + if (exists($maxd->{$escname})) { + if ($env{'form.catalog_maxdepth'} <= $maxd->{$escname}) { + $depth = $env{'form.catalog_maxdepth'}; + } else { + $depth = $maxd->{$escname}; + } + } else { + $depth = 1; + } + } elsif ($escname ne '') { + my $name = &unescape($escname); + if (grep(/^\Q$name\E$/,@{$cats->[0]})) { + $currcat = $env{'form.currcat_0'}; + if (exists($maxd->{$name})) { + if ($env{'form.catalog_maxdepth'} <= $maxd->{$name}) { + $depth = $env{'form.catalog_maxdepth'}; + } else { + $depth = $maxd->{$name}; + } + } + } + } + } + } + } + $env{'form.currcat_0'} = $currcat; + $env{'form.catalog_maxdepth'} = $depth; + return; +} + sub course_details { my ($r,$codedom,$formname,$domdesc,$trails,$allitems,$codetitles) = @_; my $output; @@ -428,7 +526,7 @@ END } sub instcode_course_selector { - my ($r,$codedom,$formname,$domdesc,$catlinks,$catjs,$codetitles,$cattype) = @_; + my ($r,$codedom,$formname,$domdesc,$catlinks,$catjs,$codetitles,$cattype,$canviewall) = @_; my %coursecodes = (); my %codes = (); my %cat_titles = (); @@ -448,10 +546,10 @@ sub instcode_course_selector { ''; if ($totcodes) { if (($env{'form.state'} eq 'listing') && ($numtitles > 0)) { - $add_entries{'onLoad'} = 'setElements();'; + $add_entries{'onload'} = 'setElements();'; } - if (&user_is_dc($codedom)) { - $add_entries{'onLoad'} .= ' toggleStatuses();toggleWasActive();' + if (&user_is_dc($codedom) || $canviewall) { + $add_entries{'onload'} .= ' toggleStatuses();toggleWasActive();' } &cat_header($r,$codedom,$js,\%add_entries,$catlinks,$numtitles,$cattype); my $cat_maxdepth = $env{'form.catalog_maxdepth'}; @@ -459,7 +557,7 @@ sub instcode_course_selector { ''."\n". ''."\n". ''. - &additional_filters($codedom)); + &additional_filters($codedom,undef,$canviewall)); if ($numtitles > 0) { $r->print(''.&mt('Choose which course(s) to list.').'
'. &Apache::courseclassifier::build_instcode_selectors($numtitles, @@ -680,10 +778,10 @@ sub get_depth_values { } sub additional_filters { - my ($codedom,$has_subcats) = @_; + my ($codedom,$has_subcats,$canviewall) = @_; my $is_dc = &user_is_dc($codedom); my $output = '
'; - if ($is_dc) { + if ($is_dc || $canviewall) { $output .= '
'.&mt('Options').''; } $output .= ''."\n". @@ -865,6 +964,22 @@ sub user_is_dc { return; } +sub canview_all { + my ($knownuser,$codedom) = @_; + my $canviewall = 0; + my $page = 'coursecatalog'; + if (&LONCAPA::lonauthcgi::can_view($page)) { + $canviewall = 1; + } elsif (&LONCAPA::lonauthcgi::check_ipbased_access($page)) { + $canviewall= 1; + } elsif (($knownuser) && ($codedom ne '')) { + if (&Apache::lonnet::allowed('dcd',$codedom)) { + $canviewall = 1; + } + } + return $canviewall; +} + sub get_statustitles { my ($caller) = @_; my @status_order = ('Active','Future','Previous'); @@ -958,12 +1073,13 @@ sub search_courselist { } sub print_course_listing { - my ($domain,$numtitles,$trails,$allitems,$subcats,$codetitles) = @_; + my ($domain,$numtitles,$trails,$allitems,$subcats,$codetitles,$canviewall) = @_; my $output; my %courses; my $knownuser = &user_is_known(); + my $canviewall = &canview_all(); my $details = $env{'form.coursenum'}; - if (&user_is_dc($domain)) { + if (&user_is_dc($domain) || $canviewall) { if ($env{'form.showdetails'}) { $details = 1; } @@ -998,7 +1114,7 @@ sub print_course_listing { $output .= '

'; return $output; } - if (($knownuser) && (!$env{'form.showdetails'}) && (!&user_is_dc($domain))) { + if (($knownuser) && (!$env{'form.showdetails'}) && (!&user_is_dc($domain)) && (!$canviewall)) { $output = ''.&mt('Note for students:').' ' .&mt('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.') .'

'; @@ -1006,7 +1122,7 @@ sub print_course_listing { } my $now = time; $output .= &construct_data_table($knownuser,$domain,\%courses,$details,undef, - $now,$trails,$allitems); + $now,$trails,$allitems,$canviewall); $output .= "\n".''. ''. ''. @@ -1015,7 +1131,7 @@ sub print_course_listing { } sub construct_data_table { - my ($knownuser,$domain,$courses,$details,$usersections,$now,$trails,$allitems) = @_; + my ($knownuser,$domain,$courses,$details,$usersections,$now,$trails,$allitems,$canviewall) = @_; my %sortname; if (($details eq '') || ($env{'form.showdetails'})) { $sortname{'Code'} = 'code'; @@ -1047,7 +1163,7 @@ sub construct_data_table { $output .= ''; } my (@fields,%fieldtitles,$wasactiveon); - if ($knownuser) { + if ($knownuser || ($canviewall && $details)) { if ($details) { if ($env{'form.currcat_0'} eq 'communities::0') { $output .= ''. @@ -1060,7 +1176,7 @@ sub construct_data_table { } my ($titlesref,$orderref) = &get_statustitles(); my @statuses; - if (&user_is_dc($domain)) { + if (&user_is_dc($domain) || $canviewall) { @statuses = &Apache::loncommon::get_env_multiple('form.showcounts'); if (grep(/^Previous$/,@statuses)) { if ($env{'form.wasactive'} eq 'date') { @@ -1107,7 +1223,7 @@ sub construct_data_table { $deftextbook = $domdefaults{'textbookcredits'}; } } - my %courseinfo = &build_courseinfo_hash($courses,$knownuser,$domain,$details, + my %courseinfo = &build_courseinfo_hash($courses,$knownuser,$domain,$canviewall,$details, $usersections,\@fields,\%fieldtitles, $wasactiveon,\%numbers,\%creditsum, $showcredits,$defofficial,$defunofficial,$deftextbook); @@ -1141,12 +1257,12 @@ sub construct_data_table { foreach my $course (@{$Sortby{$item}}) { $output.=&Apache::loncommon::start_data_table_row(); $output.=&courseinfo_row($courseinfo{$course},$knownuser,$details, - \$count,$now,$course,$trails,$allitems,\%numbers); + \$count,$now,$course,$trails,$allitems,\%numbers,$canviewall); $output.=&Apache::loncommon::end_data_table_row(); } } - if (($knownuser) && ($count > 1) && $env{'form.showdetails'}) { - if (&user_is_dc($domain)) { + if (($knownuser || $canviewall) && ($count > 1) && $env{'form.showdetails'}) { + if (&user_is_dc($domain) || $canviewall) { my %lt = &Apache::lonlocal::texthash ( 'Active' => 'Total current students', 'Future' => 'Total future students', @@ -1205,12 +1321,12 @@ sub construct_data_table { } sub build_courseinfo_hash { - my ($courses,$knownuser,$domain,$details,$usersections,$fields,$fieldtitles, + my ($courses,$knownuser,$domain,$canviewall,$details,$usersections,$fields,$fieldtitles, $wasactiveon,$numbers,$creditsum,$showcredits,$defofficial,$defunofficial) = @_; my %courseinfo; my $now = time; my $gettotals; - if ((keys(%{$courses}) > 0) && (&user_is_dc($domain)) && ($details)) { + if ((keys(%{$courses}) > 0) && (&user_is_dc($domain) || $canviewall) && ($details)) { $gettotals = 1; } my (%uniquecodes,$nocodes,$defcreds); @@ -1306,7 +1422,7 @@ sub build_courseinfo_hash { $defcreds = $courseinfo{$course}{'defaultcredits'}; } if (((defined($env{'form.coursenum'}) && ($cnum eq $env{'form.coursenum'}))) || - ($knownuser && ($details == 1))) { + (($knownuser || $canviewall) && ($details == 1))) { my $milestone; if ($wasactiveon eq 'accessend') { if ($coursehash{'default_enrollment_end_date'}) { @@ -1459,7 +1575,7 @@ sub count_students { } sub courseinfo_row { - my ($info,$knownuser,$details,$countref,$now,$course,$trails,$allitems,$numbers) = @_; + my ($info,$knownuser,$details,$countref,$now,$course,$trails,$allitems,$numbers,$canviewall) = @_; my ($cdom,$cnum,$title,$ownerlast,$code,$owner,$seclist,$xlist_items, $accessdates,$showsyllabus,$counts,$autoenrollment,$output,$categories); if (ref($info) eq 'HASH') { @@ -1508,7 +1624,7 @@ sub courseinfo_row { } $output .= ''. ''; - if ($knownuser) { + if (($knownuser) || ($canviewall && $details)) { if ($details) { $output .= ''. @@ -1582,27 +1698,32 @@ sub identify_sections { sub get_valid_classes { my ($seclist,$xlist_items,$crscode,$owners,$cdom,$cnum) = @_; my $response; - my %validations; + my (@sections,@xlists,%possclasses,%okclasses,%validations); @{$validations{'sections'}} = (); @{$validations{'xlists'}} = (); my $totalitems = 0; if ($seclist) { - foreach my $sec (split(/, /,$seclist)) { - my $class = $crscode.$sec; - if (&Apache::lonnet::auto_validate_class_sec($cdom,$cnum,$owners, - $class) eq 'ok') { + @sections = split(/,\s+/,$seclist); + map { $possclasses{$crscode.$_} = 1; } @sections; + } + if ($xlist_items) { + @xlists = split(/,\s+/,$xlist_items); + map { $possclasses{$_} = 1; } @xlists; + } + my %okclasses = &Apache::lonnet::auto_validate_instclasses($cdom,$cnum,$owners, + \%possclasses); + if (keys(%okclasses)) { + foreach my $sec (@sections) { + if ($okclasses{$crscode.$sec}) { if (!grep(/^\Q$sec$\E/,@{$validations{'sections'}})) { push(@{$validations{'sections'}},$sec); $totalitems ++; } } } - } - if ($xlist_items) { - foreach my $item (split(/, /,$xlist_items)) { - if (&Apache::lonnet::auto_validate_class_sec($cdom,$cnum,$owners, - $item) eq 'ok') { - if (!grep(/^\Q$item$\E/,@{$validations{'xlists'}})) { + foreach my $item (@xlists) { + if ($okclasses{$item}) { + if (!grep(/^\Q$item\E$/,@{$validations{'xlists'}})) { push(@{$validations{'xlists'}},$item); $totalitems ++; }
'; @@ -724,7 +822,7 @@ sub additional_filters { '
'; - if ($is_dc) { + if ($is_dc || $canviewall) { my ($titlesref,$orderref) = &get_statustitles('filters'); my $showdetails_status; if ($env{'form.showdetails'}) { @@ -735,7 +833,6 @@ sub additional_filters { $showhidden_status = 'checked="checked" '; } my @currstatuses = &Apache::loncommon::get_env_multiple('form.showcounts'); - my $dc_title = &Apache::lonnet::plaintext('dc'); my ($details_text,$hidden_text,$statusdisplay,$cellborder); my $wasactivedisplay = 'none'; if ($env{'form.showdetails'}) { @@ -749,17 +846,19 @@ sub additional_filters { $cellborder = 'border-left: 0px'; } if ($env{'form.currcat_0'} eq 'communities::0') { - $details_text = &mt('Show full details for each community ([_1] only)',$dc_title); - $hidden_text = &mt('Include communities set to be hidden from catalog ([_1] only)',$dc_title); + $details_text = &mt('Show full details for each community (domain staff only)'); + $hidden_text = &mt('Include communities set to be hidden from catalog (domain staff only)'); } else { - $details_text = &mt('Show full details for each course ([_1] only)',$dc_title); - $hidden_text = &mt('Include courses set to be hidden from catalog ([_1] only)',$dc_title); + $details_text = &mt('Show full details for each course (domain staff only)'); + $hidden_text = &mt('Include courses set to be hidden from catalog (domain staff only)'); + } + if ($is_dc) { + $output .= ''. + '
'."\n"; } $output .= ''. - '
'."\n". - ''. '
'.&mt('Default Access Dates for Members').''.$ownerlast.''.$accessdates.'