-
Matt Petro authoredMatt Petro authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
block_course_overview_uwmoodle.php 15.74 KiB
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Course overview block for UW Moodle
*
* This block improves on the course_summary block by presenting courses sorted by term.
* It also allows showing/hiding of terms and course news summaries.
*
* The block is dependent on the UW enrollment plugins.
*
* @author Matt Petro
*/
require_once($CFG->dirroot.'/lib/weblib.php');
class block_course_overview_uwmoodle extends block_base {
/**
* block initializations
*/
public function init() {
$this->title = get_string('pluginname', 'block_course_overview_uwmoodle');
}
const TERM_OTHER = 0; // UW "term_code" for non-timetable classes
/**
* block contents
*
* @return object
*/
public function get_content() {
global $USER, $CFG, $PAGE, $OUTPUT, $DB;
if($this->content !== NULL) {
return $this->content;
}
ob_start();
$courses = enrol_get_my_courses('id, shortname, modinfo, sectioncache', 'visible DESC,sortorder ASC', 0);
$site = get_site();
$course = $site; //just in case we need the old global $course hack
// Keep track of hideable items for initializing javascript
$yuiitems = array();
// Process GET parameters. Generally AJAX will be used instead of these.
$uwmterm = optional_param('uwmterm', null, PARAM_INT);
$uwmcourse = optional_param('uwmcourse', null, PARAM_INT);
$uwmshow = optional_param('uwmshow', 1, PARAM_INT);
if (!is_null($uwmterm)) {
set_user_preference('block_course_overview_uwmoodle-show-term-'.$uwmterm, $uwmshow);
}
if (!is_null($uwmcourse)) {
set_user_preference('block_course_overview_uwmoodle-show-coursenews-'.$uwmcourse, $uwmshow);
}
$currentterm = get_config('block_course_overview_uwmoodle', 'currentterm');
if (!$currentterm) {
$currentterm = self::TERM_OTHER;
}
// Find the termcode for each course
if (!empty($courses)) {
$courseids = array();
foreach ($courses as $course) {
$courseids[] = $course->id;
}
list ($insql, $inparams) = $DB->get_in_or_equal($courseids);
$select = "enrol='wisc' AND courseid $insql";
$enrols = $DB->get_records_select('enrol', $select, $inparams, '', 'id,courseid,customchar1');
foreach ($enrols as $enrol) {
if (empty($courses[$enrol->courseid]->term) || $courses[$enrol->courseid]->term < $enrol->customchar1) {
$courses[$enrol->courseid]->term = $enrol->customchar1;
}
}
}
// Sort courses by course shortname
uasort($courses, function($a,$b) { if ($a->shortname == $b->shortname) {return 0;} return ($a->shortname > $b->shortname)? 1 : -1;} );
// Organize courses into terms, maintaining shortname sorting inside each term
$terms = array();
foreach ($courses as $course) {
if (!empty($course->term)) {
$terms[$course->term][] = $course;
} else {
$terms[self::TERM_OTHER][] = $course;
}
}
// Sort terms with the current term and Misc terms first, followed by others in decreasing order
$sortedterms = array();
if (isset($terms[$currentterm])) {
$sortedterms[$currentterm] = $terms[$currentterm];
unset($terms[$currentterm]);
}
if (isset($terms[self::TERM_OTHER])) {
$sortedterms[self::TERM_OTHER] = $terms[self::TERM_OTHER];
unset($terms[self::TERM_OTHER]);
}
ksort($terms);
$terms = array_reverse($terms, true);
// can't use array_merge as the termCodes are numeric, and we want them preserved
foreach ($terms as $termCode=>$term) {
$sortedterms[$termCode] = $term;
}
$terms = $sortedterms;
// Update lastaccess for news summary
foreach ($courses as $c) {
if (isset($USER->lastcourseaccess[$c->id])) {
$courses[$c->id]->lastaccess = $USER->lastcourseaccess[$c->id];
} else {
$courses[$c->id]->lastaccess = 0;
}
}
if (empty($courses)) {
echo get_string('nocourses','my');
} else {
// Get modinfo -- copied from print_overview()
$htmlarray = array();
if ($modules = $DB->get_records('modules')) {
foreach ($modules as $mod) {
if (file_exists($CFG->dirroot.'/mod/'.$mod->name.'/lib.php')) {
include_once($CFG->dirroot.'/mod/'.$mod->name.'/lib.php');
$fname = $mod->name.'_print_overview';
if (function_exists($fname)) {
$fname($courses,$htmlarray);
}
}
}
}
// display courses
echo '<div class="courselist">';
echo '<ul class="treelist">';
$incurrentterms = true;
foreach ($terms as $termcode=>$termcourses) {
if ($incurrentterms && $termcode != $currentterm && $termcode != self::TERM_OTHER) {
//display the separator between current and other terms
echo '<hr />';
echo '<h3>Other semesters</h3>';
$incurrentterms = false;
}
$yuiitems[] = "term-$termcode";
$termname = $this->get_term_name($termcode);
$defaultshowterm = ($termcode == $currentterm || $termcode == self::TERM_OTHER)? 1 : 0;
$showterm = get_user_preferences("block_course_overview_uwmoodle-show-term-$termcode", $defaultshowterm);
if (!$showterm) {
$class = 'collapsed';
$ariaexpanded = "aria-expanded='false'";
} else {
$class = '';
$ariaexpanded = "aria-expanded='true'";
}
if ($termcode == $currentterm) {
$termclass = 'currentterm';
} else if ($termcode == self::TERM_OTHER) {
$termclass = 'miscterm';
} else {
$termclass = 'noncurrentterm';
}
$aria = "$ariaexpanded aria-controls='uwm-{$this->instance->id}-term-$termcode-list' role='button'";
$showhidetermurl = $PAGE->url->out_as_local_url(true, array('uwmterm' => $termcode, 'uwmshow' => ($showterm)? 0 : 1 ));
echo "<li class='$class'>";
if ($termcode == $currentterm) {
echo "<h3 class='$termclass'>$termname</h3>";
} else {
echo "<h3 class='$termclass'>";
// The data-ajax attribute prevents the Moodle mobile theme from overriding the AJAX behavior
echo "<a class='showhide' data-ajax='false' $aria href='$showhidetermurl' id='uwm-{$this->instance->id}-term-$termcode'><span class='term treeitem'>$termname</span></a>";
echo "</h3>";
}
echo "<ul class='treelist' id='uwm-{$this->instance->id}-term-$termcode-list' role='region'>";
foreach ($termcourses as $course) {
$fullname = format_string($course->fullname, true, array('context' => get_context_instance(CONTEXT_COURSE, $course->id)));
$hasnews = !empty($htmlarray[$course->id]);
$attributes = array('title' => s($fullname));
if (empty($course->visible)) {
$attributes['class'] = 'dimmed';
}
$newsclass = '';
$showhidehtml = '';
if ($hasnews) {
$defaultshownews = ($termcode == $currentterm || $termcode == self::TERM_OTHER)? 1 : 0;
$shownews = get_user_preferences('block_course_overview_uwmoodle-show-coursenews-'.$course->id, $defaultshownews);
$yuiitems[] = "coursenews-$course->id";
$showhidenewsurl = $PAGE->url->out_as_local_url(true, array('uwmcourse' => $course->id, 'uwmshow' => ($shownews)? 0 : 1));
if (!$shownews) {
$newsclass = 'collapsed';
$showhidetext = "Show";
$ariaexpanded = "aria-expanded='false'";
} else {
$newsclass = '';
$showhidetext = "Hide";
$ariaexpanded = "aria-expanded='true'";
}
$aria = "$ariaexpanded aria-controls='uwm-{$this->instance->id}-coursenews-{$course->id}-list' role='button'";
// The data-ajax attribute prevents the Moodle mobile theme from overriding the AJAX behavior
$showhidehtml = "<div class='shownews'><a data-ajax='false' $aria href='$showhidenewsurl' id='uwm-{$this->instance->id}-coursenews-$course->id' >";
$showhidehtml .= "<span class='coursenews treeitem'><span class='showhidetext'>$showhidetext</span> news";
$showhidehtml .= "</span></a></div>";
}
echo "<li class='$newsclass'>";
echo $OUTPUT->box_start("coursebox");
echo $OUTPUT->heading(html_writer::link(
new moodle_url('/course/view.php', array('id' => $course->id)), $fullname, $attributes) . $showhidehtml, 3);
if ($hasnews) {
echo "<ul class='treelist' id='uwm-{$this->instance->id}-coursenews-{$course->id}-list' role='region'>";
foreach ($htmlarray[$course->id] as $modname => $html) {
echo "<li>$html</li>";
}
echo "</ul>";
}
echo $OUTPUT->box_end();
echo "</li>";
}
echo "</ul>";
echo '</li>';
}
echo '</ul>';
echo "</div>";
}
// Initialize YUI module if needed
if (!empty($yuiitems)) {
$arguments = array(
'id' => $this->instance->id,
'items' => implode(' ', $yuiitems),
);
$PAGE->requires->yui_module('moodle-block_course_overview_uwmoodle-showhide', 'M.block_course_overview_uwmoodle.initialize', array($arguments));
foreach ($yuiitems as $item) {
user_preference_allow_ajax_update('block_course_overview_uwmoodle-show-'.$item, PARAM_INT);
}
}
// Get and end output buffer
$content = ob_get_contents();
ob_end_clean();
$this->content = new stdClass();
$this->content->footer = '';
$this->content->text = $content;
// Show "more courses" link if appropriate
if (has_capability('moodle/course:update', get_context_instance(CONTEXT_SYSTEM)) || empty($CFG->block_course_list_hideallcourseslink)) {
$this->content->footer = "<a href=\"$CFG->wwwroot/course/index.php\">".get_string("fulllistofcourses")."</a> ...";
}
return $this->content;
}
/**
* Return a string representing the term (e.g. "Fall 2010")
* This function doesn't make any remote calls.
*
* @param string $termCode
* @return string $termName
*/
public function get_term_name($termCode) {
$termCode = (string)$termCode;
$c = substr($termCode,0,1);
$yy = substr($termCode,1,2);
$year = 1900+100*$c+$yy;
$semester = substr($termCode,3,1);
switch($semester) {
case 2:
$name = sprintf("Fall %d courses", $year-1);
break;
case 3:
$name = sprintf("Winter %d courses", $year);
break;
case 4:
$name = sprintf("Spring %d courses", $year);
break;
case 6:
$name = sprintf("Summer %d courses", $year);
break;
default:
$name = "Miscellaneous courses";
}
return $name;
}
/**
* Get the current term from the datastore, and update user show/hide preferences when it changes.
*
* @return boolean true on success
*/
public function update_current_term() {
global $CFG, $DB;
$oldcurrentterm = get_config('block_course_overview_uwmoodle', 'currentterm');
try {
$currentterm = $this->get_current_term();
} catch (Exception $e) {
mtrace("Error fetching current term: ".$e->getMessage());
return false;
}
if ($currentterm === false) {
mtrace("No current term found");
return false;
}
if ($currentterm === $oldcurrentterm) {
// no change, so return
return true;
}
mtrace('new current term: '.$currentterm);
// New term, so clear user preferences for both current and previous term
if ($oldcurrentterm) {
$DB->delete_records('user_preferences', array('name'=> 'block_course_overview_uwmoodle-show-term-'.$oldcurrentterm));
}
$DB->delete_records('user_preferences', array('name'=> 'block_course_overview_uwmoodle-show-term-'.$currentterm));
set_config('currentterm', $currentterm, 'block_course_overview_uwmoodle');
return true;
}
/**
* Fetch current term from CHUB. Throw exception on CHUB error.
*
* @return string|false term_code or false if none found.
*/
public function get_current_term() {
global $CFG;
require_once($CFG->dirroot.'/enrol/wisc/lib/datastore.php');
$datastore = wisc_timetable_datastore::get_timetable_datastore();
$terms = $datastore->getAvailableTerms();
$now = time();
$futureterms = array();
foreach ($terms as $term) {
// check that term hasn't ended and doesn't have an odd termCode
// odd term codes (e.g. Winter) are never considered the current term
if ($term->endDate > $now && ($term->termCode % 2 != 1)) {
$futureterms[] = $term->termCode;
}
}
if (!empty($futureterms)) {
$currentterm = min($futureterms);
} else {
$currentterm = false;
}
return $currentterm;
}
/**
* allow the block to have a configuration page
*
* @return boolean
*/
public function has_config() {
return false;
}
/**
* locations where block can be displayed
*
* @return array
*/
public function applicable_formats() {
return array('my-index'=>true);
}
/**
* Block cron to update currentterm
*
* @return boolean true on success
*/
public function cron() {
return $this->update_current_term();
}
}