/** * Constructs based on course. * Note: This constructor should not usually be called directly. * Use get_fast_modinfo($course) instead as this maintains a cache. * @param object $course Moodle course object, which may include modinfo * @param int $userid User ID */ public function __construct($course, $userid) { global $CFG, $DB; // Set initial values $this->courseid = $course->id; $this->userid = $userid; $this->sections = array(); $this->cms = array(); $this->instances = array(); $this->groups = null; $this->course = $course; // Check modinfo field is set. If not, build and load it. if (empty($course->modinfo)) { rebuild_course_cache($course->id); $course->modinfo = $DB->get_field('course', 'modinfo', array('id' => $course->id)); } // Load modinfo field into memory as PHP object and check it's valid $info = unserialize($course->modinfo); if (!is_array($info)) { // hmm, something is wrong - lets try to fix it rebuild_course_cache($course->id); $course->modinfo = $DB->get_field('course', 'modinfo', array('id' => $course->id)); $info = unserialize($course->modinfo); if (!is_array($info)) { // If it still fails, abort debugging('Problem with "modinfo" data for this course'); return; } } // If we haven't already preloaded contexts for the course, do it now preload_course_contexts($course->id); // Loop through each piece of module data, constructing it $modexists = array(); foreach ($info as $mod) { if (empty($mod->name)) { // something is wrong here continue; } // Skip modules which don't exist if (empty($modexists[$mod->mod])) { if (!file_exists("{$CFG->dirroot}/mod/{$mod->mod}/lib.php")) { continue; } $modexists[$mod->mod] = true; } // Construct info for this module $cm = new cm_info($this, $course, $mod, $info); // Store module in instances and cms array if (!isset($this->instances[$cm->modname])) { $this->instances[$cm->modname] = array(); } $this->instances[$cm->modname][$cm->instance] = $cm; $this->cms[$cm->id] = $cm; // Reconstruct sections. This works because modules are stored in order if (!isset($this->sections[$cm->sectionnum])) { $this->sections[$cm->sectionnum] = array(); } $this->sections[$cm->sectionnum][] = $cm->id; } // We need at least 'dynamic' data from each course-module (this is basically the remaining // data which was always present in previous version of get_fast_modinfo, so it's required // for BC). Creating it in a second pass is necessary because obtain_dynamic_data sometimes // needs to be able to refer to a 'complete' (with basic data) modinfo. foreach ($this->cms as $cm) { $cm->obtain_dynamic_data(); } }
/** * Constructs based on course. * Note: This constructor should not usually be called directly. * Use get_fast_modinfo($course) instead as this maintains a cache. * @param object $course Moodle course object, which may include modinfo * @param int $userid User ID */ public function __construct($course, $userid) { global $CFG, $DB, $COURSE, $SITE; if (!isset($course->modinfo) || !isset($course->sectioncache)) { $course = get_course($course->id, false); } // Check modinfo field is set. If not, build and load it. if (empty($course->modinfo) || empty($course->sectioncache)) { rebuild_course_cache($course->id); $course = $DB->get_record('course', array('id' => $course->id), '*', MUST_EXIST); } // Set initial values $this->courseid = $course->id; $this->userid = $userid; $this->sections = array(); $this->cms = array(); $this->instances = array(); $this->groups = null; $this->course = $course; // Load modinfo field into memory as PHP object and check it's valid $info = unserialize($course->modinfo); if (!is_array($info)) { // hmm, something is wrong - lets try to fix it rebuild_course_cache($course->id); $course->modinfo = $DB->get_field('course', 'modinfo', array('id' => $course->id)); $info = unserialize($course->modinfo); if (!is_array($info)) { // If it still fails, abort debugging('Problem with "modinfo" data for this course'); return; } } // Load sectioncache field into memory as PHP object and check it's valid $sectioncache = unserialize($course->sectioncache); if (!is_array($sectioncache)) { // hmm, something is wrong - let's fix it rebuild_course_cache($course->id); $course->sectioncache = $DB->get_field('course', 'sectioncache', array('id' => $course->id)); $sectioncache = unserialize($course->sectioncache); if (!is_array($sectioncache)) { // If it still fails, abort debugging('Problem with "sectioncache" data for this course'); return; } } // If we haven't already preloaded contexts for the course, do it now. // Modules are also cached here as long as it's the first time this course has been preloaded. preload_course_contexts($course->id); // Quick integrity check: as a result of race conditions modinfo may not be regenerated after the change. // It is especially dangerous if modinfo contains the deleted course module, as it results in fatal error. // We can check it very cheap by validating the existence of module context. if ($course->id == $COURSE->id || $course->id == $SITE->id) { // Only verify current course (or frontpage) as pages with many courses may not have module contexts cached. // (Uncached modules will result in a very slow verification). foreach ($info as $mod) { if (!context_module::instance($mod->cm, IGNORE_MISSING)) { debugging('Course cache integrity check failed: course module with id ' . $mod->cm . ' does not have context. Rebuilding cache for course ' . $course->id); rebuild_course_cache($course->id); $this->course = $DB->get_record('course', array('id' => $course->id), '*', MUST_EXIST); $info = unserialize($this->course->modinfo); $sectioncache = unserialize($this->course->sectioncache); break; } } } // Loop through each piece of module data, constructing it $modexists = array(); foreach ($info as $mod) { if (empty($mod->name)) { // something is wrong here continue; } // Skip modules which don't exist if (empty($modexists[$mod->mod])) { if (!file_exists("{$CFG->dirroot}/mod/{$mod->mod}/lib.php")) { continue; } $modexists[$mod->mod] = true; } // Construct info for this module $cm = new cm_info($this, $course, $mod, $info); // Store module in instances and cms array if (!isset($this->instances[$cm->modname])) { $this->instances[$cm->modname] = array(); } $this->instances[$cm->modname][$cm->instance] = $cm; $this->cms[$cm->id] = $cm; // Reconstruct sections. This works because modules are stored in order if (!isset($this->sections[$cm->sectionnum])) { $this->sections[$cm->sectionnum] = array(); } $this->sections[$cm->sectionnum][] = $cm->id; } // Expand section objects $this->sectioninfo = array(); foreach ($sectioncache as $number => $data) { // Calculate sequence if (isset($this->sections[$number])) { $sequence = implode(',', $this->sections[$number]); } else { $sequence = ''; } // Expand $this->sectioninfo[$number] = new section_info($data, $number, $course->id, $sequence, $this, $userid); } // We need at least 'dynamic' data from each course-module (this is basically the remaining // data which was always present in previous version of get_fast_modinfo, so it's required // for BC). Creating it in a second pass is necessary because obtain_dynamic_data sometimes // needs to be able to refer to a 'complete' (with basic data) modinfo. foreach ($this->cms as $cm) { $cm->obtain_dynamic_data(); } }