From 92e2e85523ac04ee35eb7fbeaf754179fab63ce5 Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Fri, 14 Mar 2014 15:01:40 +0800 Subject: [PATCH] MDL-44720 modinfo: make it easier to use cm_info instead of get_coursemodule_from_id by adding function cm_info::get_course_module_record() --- lib/classes/event/base.php | 8 +++ lib/datalib.php | 8 +++ lib/grouplib.php | 10 ++-- lib/modinfolib.php | 33 ++++++++++ lib/tests/modinfolib_test.php | 110 ++++++++++++++++++++++++++++++++++ 5 files changed, 164 insertions(+), 5 deletions(-) diff --git a/lib/classes/event/base.php b/lib/classes/event/base.php index 0050d963642..524b099b7b4 100644 --- a/lib/classes/event/base.php +++ b/lib/classes/event/base.php @@ -664,9 +664,17 @@ abstract class base implements \IteratorAggregate { throw new \coding_exception('It is not possible to add snapshots after triggering of events'); } + // Special case for course module, allow instance of cm_info to be passed instead of stdClass. + if ($tablename === 'course_modules' && $record instanceof \cm_info) { + $record = $record->get_course_module_record(); + } + // NOTE: this might use some kind of MUC cache, // hopefully we will not run out of memory here... if ($CFG->debugdeveloper) { + if (!($record instanceof \stdClass)) { + debugging('Argument $record must be an instance of stdClass.', DEBUG_DEVELOPER); + } if (!$DB->get_manager()->table_exists($tablename)) { debugging("Invalid table name '$tablename' specified, database table does not exist.", DEBUG_DEVELOPER); } else { diff --git a/lib/datalib.php b/lib/datalib.php index b3f0ddcb072..258a61aa8ec 100644 --- a/lib/datalib.php +++ b/lib/datalib.php @@ -1293,6 +1293,10 @@ function get_course_mods($courseid) { /** * Given an id of a course module, finds the coursemodule description * + * Please note that this function performs 1-2 DB queries. When possible use cached + * course modinfo. For example get_fast_modinfo($courseorid)->get_cm($cmid) + * See also {@link cm_info::get_course_module_record()} + * * @global object * @param string $modulename name of module type, eg. resource, assignment,... (optional, slower and less safe if not specified) * @param int $cmid course module id (id in course_modules table) @@ -1347,6 +1351,10 @@ function get_coursemodule_from_id($modulename, $cmid, $courseid=0, $sectionnum=f /** * Given an instance number of a module, finds the coursemodule description * + * Please note that this function performs DB query. When possible use cached course + * modinfo. For example get_fast_modinfo($courseorid)->instances[$modulename][$instance] + * See also {@link cm_info::get_course_module_record()} + * * @global object * @param string $modulename name of module type, eg. resource, assignment,... * @param int $instance module instance number (id in resource, assignment etc. table) diff --git a/lib/grouplib.php b/lib/grouplib.php index ac8c7d6ffda..8fc93e48bfe 100644 --- a/lib/grouplib.php +++ b/lib/grouplib.php @@ -375,7 +375,7 @@ function groups_is_member($groupid, $userid=null) { * * @category group * @staticvar array $cache - * @param cm_info $cm course module object + * @param stdClass|cm_info $cm course module object * @param int $userid id of user, null means $USER->id * @return bool true if user member of at least one group used in activity */ @@ -625,7 +625,7 @@ function groups_allgroups_course_menu($course, $urlroot, $update = false, $activ * Print group menu selector for activity. * * @category group - * @param stdClass $cm course module object + * @param stdClass|cm_info $cm course module object * @param string|moodle_url $urlroot return address that users get to if they choose an option; * should include any parameters needed, e.g. "$CFG->wwwroot/mod/forum/view.php?id=34" * @param bool $return return as string instead of printing @@ -770,7 +770,7 @@ function groups_get_course_group($course, $update=false, $allowedgroups=null) { * Returns group active in activity, changes the group by default if 'group' page param present * * @category group - * @param stdClass $cm course module object + * @param stdClass|cm_info $cm course module object * @param bool $update change active group if group param submitted * @param array $allowedgroups list of groups user may access (INTERNAL, to be used only from groups_print_activity_menu()) * @return mixed false if groups not used, int if groups used, 0 means all groups (access must be verified in SEPARATE mode) @@ -823,7 +823,7 @@ function groups_get_activity_group($cm, $update=false, $allowedgroups=null) { * specified activity. * * @category group - * @param stdClass $cm Course-module + * @param stdClass|cm_info $cm Course-module * @param int $userid User ID (defaults to current user) * @return array An array of group objects, or false if none */ @@ -925,7 +925,7 @@ function groups_filter_users_by_course_module_visible($cm, $users) { * $USER If $userid is null, use the global object. * * @category group - * @param stdClass $cm The course module + * @param stdClass|cm_info $cm The course module * @param int $userid The user to check against the group. * @return bool True if the user can view the course module, false otherwise. */ diff --git a/lib/modinfolib.php b/lib/modinfolib.php index 2890108712d..3327dd82064 100644 --- a/lib/modinfolib.php +++ b/lib/modinfolib.php @@ -1510,6 +1510,39 @@ class cm_info implements IteratorAggregate { return context_module::instance($this->id); } + /** + * Returns itself in the form of stdClass. + * + * The object includes all fields that table course_modules has and additionally + * fields 'name', 'modname', 'sectionnum' (if requested). + * + * This can be used as a faster alternative to {@link get_coursemodule_from_id()} + * + * @param bool $additionalfields include additional fields 'name', 'modname', 'sectionnum' + * @return stdClass + */ + public function get_course_module_record($additionalfields = false) { + $cmrecord = new stdClass(); + + // Standard fields from table course_modules. + static $cmfields = array('id', 'course', 'module', 'instance', 'section', 'idnumber', 'added', + 'score', 'indent', 'visible', 'visibleold', 'groupmode', 'groupingid', 'groupmembersonly', + 'completion', 'completiongradeitemnumber', 'completionview', 'completionexpected', + 'availablefrom', 'availableuntil', 'showavailability', 'showdescription'); + foreach ($cmfields as $key) { + $cmrecord->$key = $this->$key; + } + + // Additional fields that function get_coursemodule_from_id() adds. + if ($additionalfields) { + $cmrecord->name = $this->name; + $cmrecord->modname = $this->modname; + $cmrecord->sectionnum = $this->sectionnum; + } + + return $cmrecord; + } + // Set functions //////////////// diff --git a/lib/tests/modinfolib_test.php b/lib/tests/modinfolib_test.php index 83b9daff9e3..8b9ccdeb57b 100644 --- a/lib/tests/modinfolib_test.php +++ b/lib/tests/modinfolib_test.php @@ -695,4 +695,114 @@ class core_modinfolib_testcase extends advanced_testcase { $cm->obtain_dynamic_data(); $this->assertDebuggingCalled('cm_info::obtain_dynamic_data() is deprecated and should not be used.'); } + + /** + * Tests for function cm_info::get_course_module_record() + */ + public function test_cm_info_get_course_module_record() { + global $DB, $CFG; + + $this->resetAfterTest(); + + set_config('enableavailability', 1); + set_config('enablecompletion', 1); + + $course = $this->getDataGenerator()->create_course( + array('format' => 'topics', 'numsections' => 3, 'enablecompletion' => 1), + array('createsections' => true)); + $mods = array(); + $mods[0] = $this->getDataGenerator()->create_module('forum', array('course' => $course->id)); + $mods[1] = $this->getDataGenerator()->create_module('assign', + array('course' => $course->id, + 'section' => 3, + 'idnumber' => '12345', + 'showdescription' => true + )); + $mods[2] = $this->getDataGenerator()->create_module('book', + array('course' => $course->id, + 'indent' => 5, + 'showavailability' => true, + 'showdescription' => false, + 'completion' => true, + 'completionview' => true, + 'completionexpected' => time() + 5000, + )); + $mods[3] = $this->getDataGenerator()->create_module('forum', + array('course' => $course->id, + 'visible' => 0, + 'availablefrom' => time() - 1000, + 'availableto' => time() + 1000, + 'groupmode' => 1, + 'showavailability' => false)); + $mods[4] = $this->getDataGenerator()->create_module('forum', + array('course' => $course->id, + 'groupmembersonly' => true, + 'grouping' => 12)); + + $modinfo = get_fast_modinfo($course->id); + + // Make sure that object returned by get_course_module_record(false) has exactly the same fields as DB table 'course_modules'. + $dbfields = array_keys($DB->get_columns('course_modules')); + sort($dbfields); + $cmrecord = $modinfo->get_cm($mods[0]->cmid)->get_course_module_record(); + $cmrecordfields = array_keys((array)$cmrecord); + sort($cmrecordfields); + $this->assertEquals($dbfields, $cmrecordfields); + + // Make sure that object returned by get_course_module_record(true) has exactly the same fields + // as object returned by get_coursemodule_from_id(,,,true,); + $cmrecordfull = $modinfo->get_cm($mods[0]->cmid)->get_course_module_record(true); + $cmrecordfullfields = array_keys((array)$cmrecordfull); + $cm = get_coursemodule_from_id(null, $mods[0]->cmid, 0, true, MUST_EXIST); + $cmfields = array_keys((array)$cm); + $this->assertEquals($cmfields, $cmrecordfullfields); + + // Make sure that object returned by get_course_module_record(true) has exactly the same fields + // as object returned by get_coursemodule_from_instance(,,,true,); + $cm = get_coursemodule_from_instance('forum', $mods[0]->id, null, true, MUST_EXIST); + $cmfields = array_keys((array)$cm); + $this->assertEquals($cmfields, $cmrecordfullfields); + + // Make sure the objects have the same properties. + $cm1 = get_coursemodule_from_id(null, $mods[0]->cmid, 0, true, MUST_EXIST); + $cm2 = get_coursemodule_from_instance('forum', $mods[0]->id, 0, true, MUST_EXIST); + $cminfo = $modinfo->get_cm($mods[0]->cmid); + $record = $DB->get_record('course_modules', array('id' => $mods[0]->cmid)); + $this->assertEquals($record, $cminfo->get_course_module_record()); + $this->assertEquals($cm1, $cminfo->get_course_module_record(true)); + $this->assertEquals($cm2, $cminfo->get_course_module_record(true)); + + $cm1 = get_coursemodule_from_id(null, $mods[1]->cmid, 0, true, MUST_EXIST); + $cm2 = get_coursemodule_from_instance('assign', $mods[1]->id, 0, true, MUST_EXIST); + $cminfo = $modinfo->get_cm($mods[1]->cmid); + $record = $DB->get_record('course_modules', array('id' => $mods[1]->cmid)); + $this->assertEquals($record, $cminfo->get_course_module_record()); + $this->assertEquals($cm1, $cminfo->get_course_module_record(true)); + $this->assertEquals($cm2, $cminfo->get_course_module_record(true)); + + $cm1 = get_coursemodule_from_id(null, $mods[2]->cmid, 0, true, MUST_EXIST); + $cm2 = get_coursemodule_from_instance('book', $mods[2]->id, 0, true, MUST_EXIST); + $cminfo = $modinfo->get_cm($mods[2]->cmid); + $record = $DB->get_record('course_modules', array('id' => $mods[2]->cmid)); + $this->assertEquals($record, $cminfo->get_course_module_record()); + $this->assertEquals($cm1, $cminfo->get_course_module_record(true)); + $this->assertEquals($cm2, $cminfo->get_course_module_record(true)); + + $cm1 = get_coursemodule_from_id(null, $mods[3]->cmid, 0, true, MUST_EXIST); + $cm2 = get_coursemodule_from_instance('forum', $mods[3]->id, 0, true, MUST_EXIST); + $cminfo = $modinfo->get_cm($mods[3]->cmid); + $record = $DB->get_record('course_modules', array('id' => $mods[3]->cmid)); + $this->assertEquals($record, $cminfo->get_course_module_record()); + $this->assertEquals($cm1, $cminfo->get_course_module_record(true)); + $this->assertEquals($cm2, $cminfo->get_course_module_record(true)); + + $cm1 = get_coursemodule_from_id(null, $mods[4]->cmid, 0, true, MUST_EXIST); + $cm2 = get_coursemodule_from_instance('forum', $mods[4]->id, 0, true, MUST_EXIST); + $cminfo = $modinfo->get_cm($mods[4]->cmid); + $record = $DB->get_record('course_modules', array('id' => $mods[4]->cmid)); + $this->assertEquals($record, $cminfo->get_course_module_record()); + $this->assertEquals($cm1, $cminfo->get_course_module_record(true)); + $this->assertEquals($cm2, $cminfo->get_course_module_record(true)); + + } }