MDL-72991 Course: Partial course cache rebuild with cache versioning
This commit is contained in:
@@ -1393,7 +1393,7 @@ abstract class base {
|
||||
}
|
||||
if (!is_object($section)) {
|
||||
$section = $DB->get_record('course_sections', array('course' => $this->get_courseid(), 'section' => $section),
|
||||
'id,course,section,sequence,summary');
|
||||
'id,section,sequence,summary');
|
||||
}
|
||||
if (!$section || !$section->section) {
|
||||
// Not possible to delete 0-section.
|
||||
|
||||
-198
@@ -386,204 +386,6 @@ function course_integrity_check($courseid, $rawmods = null, $sections = null, $f
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given course, returns an array of course activity objects
|
||||
* Each item in the array contains he following properties:
|
||||
*
|
||||
* @param int $courseid course id
|
||||
* @param bool $usecache get activities from cache if modinfo exists when $usecache is true
|
||||
* @return array list of activities
|
||||
*/
|
||||
function get_array_of_activities(int $courseid, bool $usecache = false): array {
|
||||
// cm - course module id
|
||||
// mod - name of the module (eg forum)
|
||||
// section - the number of the section (eg week or topic)
|
||||
// name - the name of the instance
|
||||
// visible - is the instance visible or not
|
||||
// groupingid - grouping id
|
||||
// extra - contains extra string to include in any link
|
||||
global $CFG, $DB;
|
||||
|
||||
$course = $DB->get_record('course', array('id'=>$courseid));
|
||||
|
||||
if (empty($course)) {
|
||||
throw new moodle_exception('courseidnotfound');
|
||||
}
|
||||
|
||||
$rawmods = get_course_mods($courseid);
|
||||
if (empty($rawmods)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$mods = [];
|
||||
if ($usecache) {
|
||||
// Get existing cache.
|
||||
$cachecoursemodinfo = cache::make('core', 'coursemodinfo');
|
||||
$coursemodinfo = $cachecoursemodinfo->get($courseid);
|
||||
if ($coursemodinfo !== false) {
|
||||
$mods = $coursemodinfo->modinfo;
|
||||
}
|
||||
}
|
||||
|
||||
$courseformat = course_get_format($course);
|
||||
|
||||
if ($sections = $DB->get_records('course_sections', array('course' => $courseid),
|
||||
'section ASC', 'id,section,sequence,visible')) {
|
||||
// First check and correct obvious mismatches between course_sections.sequence and course_modules.section.
|
||||
if ($errormessages = course_integrity_check($courseid, $rawmods, $sections)) {
|
||||
debugging(join('<br>', $errormessages));
|
||||
$rawmods = get_course_mods($courseid);
|
||||
$sections = $DB->get_records('course_sections', array('course' => $courseid),
|
||||
'section ASC', 'id,section,sequence,visible');
|
||||
}
|
||||
// Build array of activities.
|
||||
foreach ($sections as $section) {
|
||||
if (!empty($section->sequence)) {
|
||||
$cmids = explode(",", $section->sequence);
|
||||
$numberofmods = count($cmids);
|
||||
for ($order = 0; $order < $numberofmods; $order++) {
|
||||
$cmid = $cmids[$order];
|
||||
// Activity does not exist in the database.
|
||||
$notexistindb = empty($rawmods[$cmid]);
|
||||
$activitycached = isset($mods[$cmid]);
|
||||
if ($activitycached || $notexistindb) {
|
||||
continue;
|
||||
}
|
||||
$modposition = ($order === 0) ? 0 : array_search($cmids[$order - 1], array_keys($mods)) + 1;
|
||||
$mods = array_slice($mods, 0, $modposition, true)
|
||||
+ [$cmid => new stdClass()]
|
||||
+ array_slice($mods, $modposition, null, true);
|
||||
|
||||
// Adjust visibleoncoursepage, value in DB may not respect format availability.
|
||||
$rawmods[$cmid]->visibleoncoursepage = (!$rawmods[$cmid]->visible
|
||||
|| $rawmods[$cmid]->visibleoncoursepage
|
||||
|| empty($CFG->allowstealth)
|
||||
|| !$courseformat->allow_stealth_module_visibility($rawmods[$cmid], $section)) ? 1 : 0;
|
||||
|
||||
$mods[$cmid]->id = $rawmods[$cmid]->instance;
|
||||
$mods[$cmid]->cm = $rawmods[$cmid]->id;
|
||||
$mods[$cmid]->mod = $rawmods[$cmid]->modname;
|
||||
|
||||
// Oh dear. Inconsistent names left here for backward compatibility.
|
||||
$mods[$cmid]->section = $section->section;
|
||||
$mods[$cmid]->sectionid = $rawmods[$cmid]->section;
|
||||
|
||||
$mods[$cmid]->module = $rawmods[$cmid]->module;
|
||||
$mods[$cmid]->added = $rawmods[$cmid]->added;
|
||||
$mods[$cmid]->score = $rawmods[$cmid]->score;
|
||||
$mods[$cmid]->idnumber = $rawmods[$cmid]->idnumber;
|
||||
$mods[$cmid]->visible = $rawmods[$cmid]->visible;
|
||||
$mods[$cmid]->visibleoncoursepage = $rawmods[$cmid]->visibleoncoursepage;
|
||||
$mods[$cmid]->visibleold = $rawmods[$cmid]->visibleold;
|
||||
$mods[$cmid]->groupmode = $rawmods[$cmid]->groupmode;
|
||||
$mods[$cmid]->groupingid = $rawmods[$cmid]->groupingid;
|
||||
$mods[$cmid]->indent = $rawmods[$cmid]->indent;
|
||||
$mods[$cmid]->completion = $rawmods[$cmid]->completion;
|
||||
$mods[$cmid]->extra = "";
|
||||
$mods[$cmid]->completiongradeitemnumber =
|
||||
$rawmods[$cmid]->completiongradeitemnumber;
|
||||
$mods[$cmid]->completionpassgrade = $rawmods[$cmid]->completionpassgrade;
|
||||
$mods[$cmid]->completionview = $rawmods[$cmid]->completionview;
|
||||
$mods[$cmid]->completionexpected = $rawmods[$cmid]->completionexpected;
|
||||
$mods[$cmid]->showdescription = $rawmods[$cmid]->showdescription;
|
||||
$mods[$cmid]->availability = $rawmods[$cmid]->availability;
|
||||
$mods[$cmid]->deletioninprogress = $rawmods[$cmid]->deletioninprogress;
|
||||
$mods[$cmid]->downloadcontent = $rawmods[$cmid]->downloadcontent;
|
||||
|
||||
$modname = $mods[$cmid]->mod;
|
||||
$functionname = $modname . "_get_coursemodule_info";
|
||||
|
||||
if (!file_exists("$CFG->dirroot/mod/$modname/lib.php")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
include_once("$CFG->dirroot/mod/$modname/lib.php");
|
||||
|
||||
if ($hasfunction = function_exists($functionname)) {
|
||||
if ($info = $functionname($rawmods[$cmid])) {
|
||||
if (!empty($info->icon)) {
|
||||
$mods[$cmid]->icon = $info->icon;
|
||||
}
|
||||
if (!empty($info->iconcomponent)) {
|
||||
$mods[$cmid]->iconcomponent = $info->iconcomponent;
|
||||
}
|
||||
if (!empty($info->name)) {
|
||||
$mods[$cmid]->name = $info->name;
|
||||
}
|
||||
if ($info instanceof cached_cm_info) {
|
||||
// When using cached_cm_info you can include three new fields.
|
||||
// That aren't available for legacy code.
|
||||
if (!empty($info->content)) {
|
||||
$mods[$cmid]->content = $info->content;
|
||||
}
|
||||
if (!empty($info->extraclasses)) {
|
||||
$mods[$cmid]->extraclasses = $info->extraclasses;
|
||||
}
|
||||
if (!empty($info->iconurl)) {
|
||||
// Convert URL to string as it's easier to store.
|
||||
// Also serialized object contains \0 byte,
|
||||
// ... and can not be written to Postgres DB.
|
||||
$url = new moodle_url($info->iconurl);
|
||||
$mods[$cmid]->iconurl = $url->out(false);
|
||||
}
|
||||
if (!empty($info->onclick)) {
|
||||
$mods[$cmid]->onclick = $info->onclick;
|
||||
}
|
||||
if (!empty($info->customdata)) {
|
||||
$mods[$cmid]->customdata = $info->customdata;
|
||||
}
|
||||
} else {
|
||||
// When using a stdclass, the (horrible) deprecated ->extra field,
|
||||
// ... that is available for BC.
|
||||
if (!empty($info->extra)) {
|
||||
$mods[$cmid]->extra = $info->extra;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// When there is no modname_get_coursemodule_info function,
|
||||
// ... but showdescriptions is enabled, then we use the 'intro',
|
||||
// ... and 'introformat' fields in the module table.
|
||||
if (!$hasfunction && $rawmods[$cmid]->showdescription) {
|
||||
if ($modvalues = $DB->get_record($rawmods[$cmid]->modname,
|
||||
['id' => $rawmods[$cmid]->instance], 'name, intro, introformat')) {
|
||||
// Set content from intro and introformat. Filters are disabled.
|
||||
// Because we filter it with format_text at display time.
|
||||
$mods[$cmid]->content = format_module_intro($rawmods[$cmid]->modname,
|
||||
$modvalues, $rawmods[$cmid]->id, false);
|
||||
|
||||
// To save making another query just below, put name in here.
|
||||
$mods[$cmid]->name = $modvalues->name;
|
||||
}
|
||||
}
|
||||
if (!isset($mods[$cmid]->name)) {
|
||||
$mods[$cmid]->name = $DB->get_field($rawmods[$cmid]->modname, "name",
|
||||
["id" => $rawmods[$cmid]->instance]);
|
||||
}
|
||||
|
||||
// Minimise the database size by unsetting default options when they are 'empty'.
|
||||
// This list corresponds to code in the cm_info constructor.
|
||||
foreach (['idnumber', 'groupmode', 'groupingid',
|
||||
'indent', 'completion', 'extra', 'extraclasses', 'iconurl', 'onclick', 'content',
|
||||
'icon', 'iconcomponent', 'customdata', 'availability', 'completionview',
|
||||
'completionexpected', 'score', 'showdescription', 'deletioninprogress'] as $property) {
|
||||
if (property_exists($mods[$cmid], $property) &&
|
||||
empty($mods[$cmid]->{$property})) {
|
||||
unset($mods[$cmid]->{$property});
|
||||
}
|
||||
}
|
||||
// Special case: this value is usually set to null, but may be 0.
|
||||
if (property_exists($mods[$cmid], 'completiongradeitemnumber') &&
|
||||
is_null($mods[$cmid]->completiongradeitemnumber)) {
|
||||
unset($mods[$cmid]->completiongradeitemnumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $mods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array where the key is the module name (component name without 'mod_')
|
||||
* and the value is a lang_string object with a human-readable string.
|
||||
|
||||
@@ -1063,7 +1063,7 @@ class courselib_test extends advanced_testcase {
|
||||
// Build course cache.
|
||||
get_fast_modinfo($course->id);
|
||||
// Get the course modinfo cache.
|
||||
$coursemodinfo = $cache->get($course->id);
|
||||
$coursemodinfo = $cache->get_versioned($course->id, $course->cacherev);
|
||||
// Get the section cache.
|
||||
$sectioncaches = $coursemodinfo->sectioncache;
|
||||
|
||||
@@ -1077,7 +1077,7 @@ class courselib_test extends advanced_testcase {
|
||||
// Move section.
|
||||
move_section_to($course, 2, 3);
|
||||
// Get the course modinfo cache.
|
||||
$coursemodinfo = $cache->get($course->id);
|
||||
$coursemodinfo = $cache->get_versioned($course->id, $course->cacherev);
|
||||
// Get the section cache.
|
||||
$sectioncaches = $coursemodinfo->sectioncache;
|
||||
|
||||
|
||||
@@ -92,6 +92,8 @@ course formats don't have their own renderer.
|
||||
* The following functions have been deprecated in favour partial course cache rebuild:
|
||||
- course_purge_section_cache (replaced by course_modinfo::purge_course_section_cache_by_id() and course_modinfo::purge_course_section_cache_by_number())
|
||||
- course_purge_module_cache (replaced by course_modinfo::purge_course_module_cache())
|
||||
- get_array_of_activities (replaced by course_modinfo::get_array_of_activities() for better performance)
|
||||
* New course_modinfo::purge_course_cache function was created to purge the cache of a given course.
|
||||
|
||||
=== 3.11 ===
|
||||
* A new callback xxx_coursemodule_definition_after_data that allows plugins to extend activity forms after the data is set.
|
||||
|
||||
@@ -3729,3 +3729,18 @@ function print_grade_plugin_selector($plugin_info, $active_type, $active_plugin,
|
||||
course_modinfo::purge_course_module_cache($courseid, $cmid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given course, returns an array of course activity objects
|
||||
* Each item in the array contains he following properties:
|
||||
*
|
||||
* @param int $courseid course id
|
||||
* @param bool $usecache get activities from cache if modinfo exists when $usecache is true
|
||||
* @return array list of activities
|
||||
* @deprecated since Moodle 4.0. Please use {@link course_modinfo::get_array_of_activities()} instead.
|
||||
*/
|
||||
function get_array_of_activities(int $courseid, bool $usecache = false): array {
|
||||
debugging(__FUNCTION__ . '() is deprecated. ' . 'Please use course_modinfo::get_array_of_activities() instead.',
|
||||
DEBUG_DEVELOPER);
|
||||
return course_modinfo::get_array_of_activities(get_course($courseid), $usecache);
|
||||
}
|
||||
|
||||
+214
-19
@@ -476,13 +476,13 @@ class course_modinfo {
|
||||
|
||||
// Retrieve modinfo from cache. If not present or cacherev mismatches, call rebuild and retrieve again.
|
||||
$coursemodinfo = $cachecoursemodinfo->get_versioned($course->id, $course->cacherev);
|
||||
if (!$coursemodinfo) {
|
||||
if ($coursemodinfo === false || ($course->cacherev != $coursemodinfo->cacherev)) {
|
||||
$lock = self::get_course_cache_lock($course->id);
|
||||
try {
|
||||
// Only actually do the build if it's still needed after getting the lock (not if
|
||||
// somebody else, who might have been holding the lock, built it already).
|
||||
$coursemodinfo = $cachecoursemodinfo->get_versioned($course->id, $course->cacherev);
|
||||
if (!$coursemodinfo) {
|
||||
if ($coursemodinfo === false || ($course->cacherev != $coursemodinfo->cacherev)) {
|
||||
$coursemodinfo = self::inner_build_course_cache($course, $lock);
|
||||
}
|
||||
} finally {
|
||||
@@ -553,7 +553,6 @@ class course_modinfo {
|
||||
$this->instances[$cm->modname] = array();
|
||||
}
|
||||
$this->instances[$cm->modname][$cm->instance] = $cm;
|
||||
ksort($this->instances[$cm->modname]);
|
||||
$this->cms[$cm->id] = $cm;
|
||||
|
||||
// Reconstruct sections. This works because modules are stored in order
|
||||
@@ -563,8 +562,6 @@ class course_modinfo {
|
||||
$this->sections[$cm->sectionnum][] = $cm->id;
|
||||
}
|
||||
|
||||
ksort($this->cms);
|
||||
ksort($this->instances);
|
||||
// Expand section objects
|
||||
$this->sectioninfo = array();
|
||||
foreach ($coursemodinfo->sectioncache as $number => $data) {
|
||||
@@ -605,7 +602,7 @@ class course_modinfo {
|
||||
|
||||
if ($usecache) {
|
||||
$cachecoursemodinfo = \cache::make('core', 'coursemodinfo');
|
||||
$coursemodinfo = $cachecoursemodinfo->get($course->id);
|
||||
$coursemodinfo = $cachecoursemodinfo->get_versioned($course->id, $course->cacherev);
|
||||
if ($coursemodinfo !== false) {
|
||||
$compressedsections = $coursemodinfo->sectioncache;
|
||||
}
|
||||
@@ -709,7 +706,7 @@ class course_modinfo {
|
||||
|
||||
// Retrieve all information about activities and sections.
|
||||
$coursemodinfo = new stdClass();
|
||||
$coursemodinfo->modinfo = get_array_of_activities($course->id, $partialrebuild);
|
||||
$coursemodinfo->modinfo = self::get_array_of_activities($course, $partialrebuild);
|
||||
$coursemodinfo->sectioncache = self::build_course_section_cache($course, $partialrebuild);
|
||||
foreach (self::$cachedfields as $key) {
|
||||
$coursemodinfo->$key = $course->$key;
|
||||
@@ -727,20 +724,21 @@ class course_modinfo {
|
||||
* @param int $sectionid The section _id_ to purge
|
||||
*/
|
||||
public static function purge_course_section_cache_by_id(int $courseid, int $sectionid): void {
|
||||
$course = get_course($courseid);
|
||||
$cache = cache::make('core', 'coursemodinfo');
|
||||
$cache->acquire_lock($courseid);
|
||||
$coursemodinfo = $cache->get($courseid);
|
||||
$cache->acquire_lock($course->id);
|
||||
$coursemodinfo = $cache->get_versioned($course->id, $course->cacherev);
|
||||
if ($coursemodinfo !== false) {
|
||||
foreach ($coursemodinfo->sectioncache as $sectionno => $sectioncache) {
|
||||
if ($sectioncache->id == $sectionid) {
|
||||
$coursemodinfo->cacherev = -1;
|
||||
unset($coursemodinfo->sectioncache[$sectionno]);
|
||||
$cache->set($courseid, $coursemodinfo);
|
||||
$cache->set_versioned($course->id, $course->cacherev, $coursemodinfo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$cache->release_lock($courseid);
|
||||
$cache->release_lock($course->id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -750,15 +748,16 @@ class course_modinfo {
|
||||
* @param int $sectionno The section number to purge
|
||||
*/
|
||||
public static function purge_course_section_cache_by_number(int $courseid, int $sectionno): void {
|
||||
$course = get_course($courseid);
|
||||
$cache = cache::make('core', 'coursemodinfo');
|
||||
$cache->acquire_lock($courseid);
|
||||
$coursemodinfo = $cache->get($courseid);
|
||||
$cache->acquire_lock($course->id);
|
||||
$coursemodinfo = $cache->get_versioned($course->id, $course->cacherev);
|
||||
if ($coursemodinfo !== false && array_key_exists($sectionno, $coursemodinfo->sectioncache)) {
|
||||
$coursemodinfo->cacherev = -1;
|
||||
unset($coursemodinfo->sectioncache[$sectionno]);
|
||||
$cache->set($courseid, $coursemodinfo);
|
||||
$cache->set_versioned($course->id, $course->cacherev, $coursemodinfo);
|
||||
}
|
||||
$cache->release_lock($courseid);
|
||||
$cache->release_lock($course->id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -768,16 +767,212 @@ class course_modinfo {
|
||||
* @param int $cmid Course module id
|
||||
*/
|
||||
public static function purge_course_module_cache(int $courseid, int $cmid): void {
|
||||
$course = get_course($courseid);
|
||||
$cache = cache::make('core', 'coursemodinfo');
|
||||
$cache->acquire_lock($courseid);
|
||||
$coursemodinfo = $cache->get($courseid);
|
||||
$cache->acquire_lock($course->id);
|
||||
$coursemodinfo = $cache->get_versioned($course->id, $course->cacherev);
|
||||
$hascache = ($coursemodinfo !== false) && array_key_exists($cmid, $coursemodinfo->modinfo);
|
||||
if ($hascache) {
|
||||
$coursemodinfo->cacherev = -1;
|
||||
unset($coursemodinfo->modinfo[$cmid]);
|
||||
$cache->set($courseid, $coursemodinfo);
|
||||
$cache->set_versioned($course->id, $course->cacherev, $coursemodinfo);
|
||||
$coursemodinfo = $cache->get_versioned($course->id, $course->cacherev);
|
||||
}
|
||||
$cache->release_lock($courseid);
|
||||
$cache->release_lock($course->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given course, returns an array of course activity objects
|
||||
*
|
||||
* @param stdClass $course Course object
|
||||
* @param bool $usecache get activities from cache if modinfo exists when $usecache is true
|
||||
* @return array list of activities
|
||||
*/
|
||||
public static function get_array_of_activities(stdClass $course, bool $usecache = false): array {
|
||||
global $CFG, $DB;
|
||||
|
||||
if (empty($course)) {
|
||||
throw new moodle_exception('courseidnotfound');
|
||||
}
|
||||
|
||||
$rawmods = get_course_mods($course->id);
|
||||
if (empty($rawmods)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$mods = [];
|
||||
if ($usecache) {
|
||||
// Get existing cache.
|
||||
$cachecoursemodinfo = cache::make('core', 'coursemodinfo');
|
||||
$coursemodinfo = $cachecoursemodinfo->get_versioned($course->id, $course->cacherev);
|
||||
if ($coursemodinfo !== false) {
|
||||
$mods = $coursemodinfo->modinfo;
|
||||
}
|
||||
}
|
||||
|
||||
$courseformat = course_get_format($course);
|
||||
|
||||
if ($sections = $DB->get_records('course_sections', ['course' => $course->id],
|
||||
'section ASC', 'id,section,sequence,visible')) {
|
||||
// First check and correct obvious mismatches between course_sections.sequence and course_modules.section.
|
||||
if ($errormessages = course_integrity_check($course->id, $rawmods, $sections)) {
|
||||
debugging(join('<br>', $errormessages));
|
||||
$rawmods = get_course_mods($course->id);
|
||||
$sections = $DB->get_records('course_sections', ['course' => $course->id],
|
||||
'section ASC', 'id,section,sequence,visible');
|
||||
}
|
||||
// Build array of activities.
|
||||
foreach ($sections as $section) {
|
||||
if (!empty($section->sequence)) {
|
||||
$cmids = explode(",", $section->sequence);
|
||||
$numberofmods = count($cmids);
|
||||
foreach ($cmids as $cmid) {
|
||||
// Activity does not exist in the database.
|
||||
$notexistindb = empty($rawmods[$cmid]);
|
||||
$activitycached = isset($mods[$cmid]);
|
||||
if ($activitycached || $notexistindb) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Adjust visibleoncoursepage, value in DB may not respect format availability.
|
||||
$rawmods[$cmid]->visibleoncoursepage = (!$rawmods[$cmid]->visible
|
||||
|| $rawmods[$cmid]->visibleoncoursepage
|
||||
|| empty($CFG->allowstealth)
|
||||
|| !$courseformat->allow_stealth_module_visibility($rawmods[$cmid], $section)) ? 1 : 0;
|
||||
|
||||
$mods[$cmid] = new stdClass();
|
||||
$mods[$cmid]->id = $rawmods[$cmid]->instance;
|
||||
$mods[$cmid]->cm = $rawmods[$cmid]->id;
|
||||
$mods[$cmid]->mod = $rawmods[$cmid]->modname;
|
||||
|
||||
// Oh dear. Inconsistent names left here for backward compatibility.
|
||||
$mods[$cmid]->section = $section->section;
|
||||
$mods[$cmid]->sectionid = $rawmods[$cmid]->section;
|
||||
|
||||
$mods[$cmid]->module = $rawmods[$cmid]->module;
|
||||
$mods[$cmid]->added = $rawmods[$cmid]->added;
|
||||
$mods[$cmid]->score = $rawmods[$cmid]->score;
|
||||
$mods[$cmid]->idnumber = $rawmods[$cmid]->idnumber;
|
||||
$mods[$cmid]->visible = $rawmods[$cmid]->visible;
|
||||
$mods[$cmid]->visibleoncoursepage = $rawmods[$cmid]->visibleoncoursepage;
|
||||
$mods[$cmid]->visibleold = $rawmods[$cmid]->visibleold;
|
||||
$mods[$cmid]->groupmode = $rawmods[$cmid]->groupmode;
|
||||
$mods[$cmid]->groupingid = $rawmods[$cmid]->groupingid;
|
||||
$mods[$cmid]->indent = $rawmods[$cmid]->indent;
|
||||
$mods[$cmid]->completion = $rawmods[$cmid]->completion;
|
||||
$mods[$cmid]->extra = "";
|
||||
$mods[$cmid]->completiongradeitemnumber =
|
||||
$rawmods[$cmid]->completiongradeitemnumber;
|
||||
$mods[$cmid]->completionpassgrade = $rawmods[$cmid]->completionpassgrade;
|
||||
$mods[$cmid]->completionview = $rawmods[$cmid]->completionview;
|
||||
$mods[$cmid]->completionexpected = $rawmods[$cmid]->completionexpected;
|
||||
$mods[$cmid]->showdescription = $rawmods[$cmid]->showdescription;
|
||||
$mods[$cmid]->availability = $rawmods[$cmid]->availability;
|
||||
$mods[$cmid]->deletioninprogress = $rawmods[$cmid]->deletioninprogress;
|
||||
$mods[$cmid]->downloadcontent = $rawmods[$cmid]->downloadcontent;
|
||||
|
||||
$modname = $mods[$cmid]->mod;
|
||||
$functionname = $modname . "_get_coursemodule_info";
|
||||
|
||||
if (!file_exists("$CFG->dirroot/mod/$modname/lib.php")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
include_once("$CFG->dirroot/mod/$modname/lib.php");
|
||||
|
||||
if ($hasfunction = function_exists($functionname)) {
|
||||
if ($info = $functionname($rawmods[$cmid])) {
|
||||
if (!empty($info->icon)) {
|
||||
$mods[$cmid]->icon = $info->icon;
|
||||
}
|
||||
if (!empty($info->iconcomponent)) {
|
||||
$mods[$cmid]->iconcomponent = $info->iconcomponent;
|
||||
}
|
||||
if (!empty($info->name)) {
|
||||
$mods[$cmid]->name = $info->name;
|
||||
}
|
||||
if ($info instanceof cached_cm_info) {
|
||||
// When using cached_cm_info you can include three new fields.
|
||||
// That aren't available for legacy code.
|
||||
if (!empty($info->content)) {
|
||||
$mods[$cmid]->content = $info->content;
|
||||
}
|
||||
if (!empty($info->extraclasses)) {
|
||||
$mods[$cmid]->extraclasses = $info->extraclasses;
|
||||
}
|
||||
if (!empty($info->iconurl)) {
|
||||
// Convert URL to string as it's easier to store.
|
||||
// Also serialized object contains \0 byte,
|
||||
// ... and can not be written to Postgres DB.
|
||||
$url = new moodle_url($info->iconurl);
|
||||
$mods[$cmid]->iconurl = $url->out(false);
|
||||
}
|
||||
if (!empty($info->onclick)) {
|
||||
$mods[$cmid]->onclick = $info->onclick;
|
||||
}
|
||||
if (!empty($info->customdata)) {
|
||||
$mods[$cmid]->customdata = $info->customdata;
|
||||
}
|
||||
} else {
|
||||
// When using a stdclass, the (horrible) deprecated ->extra field,
|
||||
// ... that is available for BC.
|
||||
if (!empty($info->extra)) {
|
||||
$mods[$cmid]->extra = $info->extra;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// When there is no modname_get_coursemodule_info function,
|
||||
// ... but showdescriptions is enabled, then we use the 'intro',
|
||||
// ... and 'introformat' fields in the module table.
|
||||
if (!$hasfunction && $rawmods[$cmid]->showdescription) {
|
||||
if ($modvalues = $DB->get_record($rawmods[$cmid]->modname,
|
||||
['id' => $rawmods[$cmid]->instance], 'name, intro, introformat')) {
|
||||
// Set content from intro and introformat. Filters are disabled.
|
||||
// Because we filter it with format_text at display time.
|
||||
$mods[$cmid]->content = format_module_intro($rawmods[$cmid]->modname,
|
||||
$modvalues, $rawmods[$cmid]->id, false);
|
||||
|
||||
// To save making another query just below, put name in here.
|
||||
$mods[$cmid]->name = $modvalues->name;
|
||||
}
|
||||
}
|
||||
if (!isset($mods[$cmid]->name)) {
|
||||
$mods[$cmid]->name = $DB->get_field($rawmods[$cmid]->modname, "name",
|
||||
["id" => $rawmods[$cmid]->instance]);
|
||||
}
|
||||
|
||||
// Minimise the database size by unsetting default options when they are 'empty'.
|
||||
// This list corresponds to code in the cm_info constructor.
|
||||
foreach (['idnumber', 'groupmode', 'groupingid',
|
||||
'indent', 'completion', 'extra', 'extraclasses', 'iconurl', 'onclick', 'content',
|
||||
'icon', 'iconcomponent', 'customdata', 'availability', 'completionview',
|
||||
'completionexpected', 'score', 'showdescription', 'deletioninprogress'] as $property) {
|
||||
if (property_exists($mods[$cmid], $property) &&
|
||||
empty($mods[$cmid]->{$property})) {
|
||||
unset($mods[$cmid]->{$property});
|
||||
}
|
||||
}
|
||||
// Special case: this value is usually set to null, but may be 0.
|
||||
if (property_exists($mods[$cmid], 'completiongradeitemnumber') &&
|
||||
is_null($mods[$cmid]->completiongradeitemnumber)) {
|
||||
unset($mods[$cmid]->completiongradeitemnumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $mods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Purge the cache of a given course
|
||||
*
|
||||
* @param int $courseid Course id
|
||||
*/
|
||||
public static function purge_course_cache(int $courseid): void {
|
||||
$cachemodinfo = cache::make('core', 'coursemodinfo');
|
||||
$cachemodinfo->delete($courseid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -5347,8 +5347,7 @@ function remove_course_contents($courseid, $showfeedback = true, array $options
|
||||
fulldelete($CFG->dataroot.'/'.$course->id);
|
||||
|
||||
// Delete from cache to reduce the cache size especially makes sense in case of bulk course deletion.
|
||||
$cachemodinfo = cache::make('core', 'coursemodinfo');
|
||||
$cachemodinfo->delete($courseid);
|
||||
course_modinfo::purge_course_cache($courseid);
|
||||
|
||||
// Trigger a course content deleted event.
|
||||
$event = \core\event\course_content_deleted::create(array(
|
||||
|
||||
@@ -367,7 +367,7 @@ class modinfolib_test extends advanced_testcase {
|
||||
$this->assertEquals($USER->id, $modinfo->userid);
|
||||
$this->assertEquals(array(0 => array($forum0->cmid, $assign0->cmid),
|
||||
1 => array($forum1->cmid, $assign1->cmid, $page1->cmid), 3 => array($page3->cmid)), $modinfo->sections);
|
||||
$this->assertEquals(array('assign', 'forum', 'page'), array_keys($modinfo->instances));
|
||||
$this->assertEquals(array('forum', 'assign', 'page'), array_keys($modinfo->instances));
|
||||
$this->assertEquals(array($assign0->id, $assign1->id), array_keys($modinfo->instances['assign']));
|
||||
$this->assertEquals(array($forum0->id, $forum1->id), array_keys($modinfo->instances['forum']));
|
||||
$this->assertEquals(array($page1->id, $page3->id), array_keys($modinfo->instances['page']));
|
||||
@@ -1023,7 +1023,7 @@ class modinfolib_test extends advanced_testcase {
|
||||
// Build course cache.
|
||||
get_fast_modinfo($course->id);
|
||||
// Get the course modinfo cache.
|
||||
$coursemodinfo = $cache->get($course->id);
|
||||
$coursemodinfo = $cache->get_versioned($course->id, $course->cacherev);
|
||||
// Get the section cache.
|
||||
$sectioncaches = $coursemodinfo->sectioncache;
|
||||
|
||||
@@ -1037,7 +1037,7 @@ class modinfolib_test extends advanced_testcase {
|
||||
// Purge cache for the section by id.
|
||||
course_modinfo::purge_course_section_cache_by_id($course->id, $sectioncaches[1]->id);
|
||||
// Get the course modinfo cache.
|
||||
$coursemodinfo = $cache->get($course->id);
|
||||
$coursemodinfo = $cache->get_versioned($course->id, $course->cacherev);
|
||||
// Get the section cache.
|
||||
$sectioncaches = $coursemodinfo->sectioncache;
|
||||
|
||||
@@ -1069,7 +1069,7 @@ class modinfolib_test extends advanced_testcase {
|
||||
// Build course cache.
|
||||
get_fast_modinfo($course->id);
|
||||
// Get the course modinfo cache.
|
||||
$coursemodinfo = $cache->get($course->id);
|
||||
$coursemodinfo = $cache->get_versioned($course->id, $course->cacherev);
|
||||
// Get the section cache.
|
||||
$sectioncaches = $coursemodinfo->sectioncache;
|
||||
|
||||
@@ -1083,7 +1083,7 @@ class modinfolib_test extends advanced_testcase {
|
||||
// Purge cache for the section with section number is 1.
|
||||
course_modinfo::purge_course_section_cache_by_number($course->id, 1);
|
||||
// Get the course modinfo cache.
|
||||
$coursemodinfo = $cache->get($course->id);
|
||||
$coursemodinfo = $cache->get_versioned($course->id, $course->cacherev);
|
||||
// Get the section cache.
|
||||
$sectioncaches = $coursemodinfo->sectioncache;
|
||||
|
||||
|
||||
+1
-1
@@ -201,7 +201,7 @@ function page_delete_instance($id) {
|
||||
* "extra" information that may be needed when printing
|
||||
* this activity in a course listing.
|
||||
*
|
||||
* See {@link get_array_of_activities()} in course/lib.php
|
||||
* See {@link course_modinfo::get_array_of_activities()}
|
||||
*
|
||||
* @param stdClass $coursemodule
|
||||
* @return cached_cm_info Info to customise main page display
|
||||
|
||||
@@ -192,7 +192,7 @@ function resource_delete_instance($id) {
|
||||
* "extra" information that may be needed when printing
|
||||
* this activity in a course listing.
|
||||
*
|
||||
* See {@link get_array_of_activities()} in course/lib.php
|
||||
* See {@link course_modinfo::get_array_of_activities()}
|
||||
*
|
||||
* @param stdClass $coursemodule
|
||||
* @return cached_cm_info info
|
||||
|
||||
+1
-1
@@ -203,7 +203,7 @@ function url_delete_instance($id) {
|
||||
* "extra" information that may be needed when printing
|
||||
* this activity in a course listing.
|
||||
*
|
||||
* See {@link get_array_of_activities()} in course/lib.php
|
||||
* See {@link course_modinfo::get_array_of_activities()}
|
||||
*
|
||||
* @param object $coursemodule
|
||||
* @return cached_cm_info info
|
||||
|
||||
Reference in New Issue
Block a user