mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 16:32:18 +02:00
Merge branch 'MDL-56307-master' of git://github.com/jleyva/moodle
This commit is contained in:
commit
26aa08b2f8
@ -217,4 +217,50 @@ class comment_manager {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get comments created since a given time.
|
||||
*
|
||||
* @param stdClass $course course object
|
||||
* @param stdClass $context context object
|
||||
* @param string $component component name
|
||||
* @param int $since the time to check
|
||||
* @param stdClass $cm course module object
|
||||
* @return array list of comments db records since the given timelimit
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
public function get_component_comments_since($course, $context, $component, $since, $cm = null) {
|
||||
global $DB;
|
||||
|
||||
$commentssince = array();
|
||||
$where = 'contextid = ? AND component = ? AND timecreated > ?';
|
||||
$comments = $DB->get_records_select('comments', $where, array($context->id, $component, $since));
|
||||
// Check item by item if we have permissions.
|
||||
$managersviewstatus = array();
|
||||
foreach ($comments as $comment) {
|
||||
// Check if the manager for the item is cached.
|
||||
if (!isset($managersviewstatus[$comment->commentarea]) or
|
||||
!isset($managersviewstatus[$comment->commentarea][$comment->itemid])) {
|
||||
|
||||
$args = new stdClass;
|
||||
$args->area = $comment->commentarea;
|
||||
$args->itemid = $comment->itemid;
|
||||
$args->context = $context;
|
||||
$args->course = $course;
|
||||
$args->client_id = 0;
|
||||
$args->component = $component;
|
||||
if (!empty($cm)) {
|
||||
$args->cm = $cm;
|
||||
}
|
||||
|
||||
$manager = new comment($args);
|
||||
$managersviewstatus[$comment->commentarea][$comment->itemid] = $manager->can_view();
|
||||
}
|
||||
|
||||
if ($managersviewstatus[$comment->commentarea][$comment->itemid]) {
|
||||
$commentssince[$comment->id] = $comment;
|
||||
}
|
||||
}
|
||||
return $commentssince;
|
||||
}
|
||||
}
|
||||
|
@ -3021,4 +3021,132 @@ class core_course_external extends external_api {
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method parameters
|
||||
*
|
||||
* @return external_function_parameters
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
public static function check_updates_parameters() {
|
||||
return new external_function_parameters(
|
||||
array(
|
||||
'courseid' => new external_value(PARAM_INT, 'Course id to check'),
|
||||
'tocheck' => new external_multiple_structure(
|
||||
new external_single_structure(
|
||||
array(
|
||||
'contextlevel' => new external_value(PARAM_ALPHA, 'The context level for the file location.
|
||||
Only module supported right now.'),
|
||||
'id' => new external_value(PARAM_INT, 'Context instance id'),
|
||||
'since' => new external_value(PARAM_INT, 'Check updates since this time stamp'),
|
||||
)
|
||||
),
|
||||
'Instances to check'
|
||||
),
|
||||
'filter' => new external_multiple_structure(
|
||||
new external_value(PARAM_ALPHANUM, 'Area name: configuration, fileareas, completion, ratings, comments,
|
||||
gradeitems, outcomes'),
|
||||
'Check only for updates in these areas', VALUE_DEFAULT, array()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there is updates affecting the user for the given course and contexts.
|
||||
* Right now only modules are supported.
|
||||
* This WS calls mod_check_updates_since for each module to check if there is any update the user should we aware of.
|
||||
*
|
||||
* @param int $courseid the list of modules to check
|
||||
* @param array $tocheck the list of modules to check
|
||||
* @param array $filter check only for updates in these areas
|
||||
* @return array list of updates and warnings
|
||||
* @throws moodle_exception
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
public static function check_updates($courseid, $tocheck, $filter = array()) {
|
||||
global $CFG, $DB;
|
||||
|
||||
$params = self::validate_parameters(
|
||||
self::check_updates_parameters(),
|
||||
array(
|
||||
'courseid' => $courseid,
|
||||
'tocheck' => $tocheck,
|
||||
'filter' => $filter,
|
||||
)
|
||||
);
|
||||
|
||||
$course = get_course($params['courseid']);
|
||||
$context = context_course::instance($course->id);
|
||||
self::validate_context($context);
|
||||
|
||||
list($instances, $warnings) = course_check_updates($course, $params['tocheck'], $filter);
|
||||
|
||||
$instancesformatted = array();
|
||||
foreach ($instances as $instance) {
|
||||
$updates = array();
|
||||
foreach ($instance['updates'] as $name => $data) {
|
||||
if (empty($data->updated)) {
|
||||
continue;
|
||||
}
|
||||
$updatedata = array(
|
||||
'name' => $name,
|
||||
);
|
||||
if (!empty($data->timeupdated)) {
|
||||
$updatedata['timeupdated'] = $data->timeupdated;
|
||||
}
|
||||
if (!empty($data->itemids)) {
|
||||
$updatedata['itemids'] = $data->itemids;
|
||||
}
|
||||
$updates[] = $updatedata;
|
||||
}
|
||||
if (!empty($updates)) {
|
||||
$instancesformatted[] = array(
|
||||
'contextlevel' => $instance['contextlevel'],
|
||||
'id' => $instance['id'],
|
||||
'updates' => $updates
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
'instances' => $instancesformatted,
|
||||
'warnings' => $warnings
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method result value
|
||||
*
|
||||
* @return external_description
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
public static function check_updates_returns() {
|
||||
return new external_single_structure(
|
||||
array(
|
||||
'instances' => new external_multiple_structure(
|
||||
new external_single_structure(
|
||||
array(
|
||||
'contextlevel' => new external_value(PARAM_ALPHA, 'The context level'),
|
||||
'id' => new external_value(PARAM_INT, 'Instance id'),
|
||||
'updates' => new external_multiple_structure(
|
||||
new external_single_structure(
|
||||
array(
|
||||
'name' => new external_value(PARAM_ALPHANUMEXT, 'Name of the area updated.'),
|
||||
'timeupdated' => new external_value(PARAM_INT, 'Last time was updated', VALUE_OPTIONAL),
|
||||
'itemids' => new external_multiple_structure(
|
||||
new external_value(PARAM_INT, 'Instance id'),
|
||||
'The ids of the items updated',
|
||||
VALUE_OPTIONAL
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
'warnings' => new external_warnings()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
189
course/lib.php
189
course/lib.php
@ -3606,3 +3606,192 @@ function course_validate_dates($coursedata) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for course updates in the given context level instances (only modules supported right Now)
|
||||
*
|
||||
* @param stdClass $course course object
|
||||
* @param array $tocheck instances to check for updates
|
||||
* @param array $filter check only for updates in these areas
|
||||
* @return array list of warnings and instances with updates information
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
function course_check_updates($course, $tocheck, $filter = array()) {
|
||||
global $CFG, $DB;
|
||||
|
||||
$instances = array();
|
||||
$warnings = array();
|
||||
$modulescallbacksupport = array();
|
||||
$modinfo = get_fast_modinfo($course);
|
||||
|
||||
$supportedplugins = get_plugin_list_with_function('mod', 'check_updates_since');
|
||||
|
||||
// Check instances.
|
||||
foreach ($tocheck as $instance) {
|
||||
if ($instance['contextlevel'] == 'module') {
|
||||
// Check module visibility.
|
||||
try {
|
||||
$cm = $modinfo->get_cm($instance['id']);
|
||||
} catch (Exception $e) {
|
||||
$warnings[] = array(
|
||||
'item' => 'module',
|
||||
'itemid' => $instance['id'],
|
||||
'warningcode' => 'cmidnotincourse',
|
||||
'message' => 'This module id does not belong to this course.'
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$cm->uservisible) {
|
||||
$warnings[] = array(
|
||||
'item' => 'module',
|
||||
'itemid' => $instance['id'],
|
||||
'warningcode' => 'nonuservisible',
|
||||
'message' => 'You don\'t have access to this module.'
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if (empty($supportedplugins['mod_' . $cm->modname])) {
|
||||
$warnings[] = array(
|
||||
'item' => 'module',
|
||||
'itemid' => $instance['id'],
|
||||
'warningcode' => 'missingcallback',
|
||||
'message' => 'This module does not implement the check_updates_since callback: ' . $instance['contextlevel'],
|
||||
);
|
||||
continue;
|
||||
}
|
||||
// Retrieve the module instance.
|
||||
$instances[] = array(
|
||||
'contextlevel' => $instance['contextlevel'],
|
||||
'id' => $instance['id'],
|
||||
'updates' => call_user_func($cm->modname . '_check_updates_since', $cm, $instance['since'], $filter)
|
||||
);
|
||||
|
||||
} else {
|
||||
$warnings[] = array(
|
||||
'item' => 'contextlevel',
|
||||
'itemid' => $instance['id'],
|
||||
'warningcode' => 'contextlevelnotsupported',
|
||||
'message' => 'Context level not yet supported ' . $instance['contextlevel'],
|
||||
);
|
||||
}
|
||||
}
|
||||
return array($instances, $warnings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check module updates since a given time.
|
||||
* This function checks for updates in the module config, file areas, completion, grades, comments and ratings.
|
||||
*
|
||||
* @param cm_info $cm course module data
|
||||
* @param int $from the time to check
|
||||
* @param array $fileareas additional file ares to check
|
||||
* @param array $filter if we need to filter and return only selected updates
|
||||
* @return stdClass object with the different updates
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
function course_check_module_updates_since($cm, $from, $fileareas = array(), $filter = array()) {
|
||||
global $DB, $CFG, $USER;
|
||||
|
||||
$context = $cm->context;
|
||||
$mod = $DB->get_record($cm->modname, array('id' => $cm->instance), '*', MUST_EXIST);
|
||||
|
||||
$updates = new stdClass();
|
||||
$course = get_course($cm->course);
|
||||
$component = 'mod_' . $cm->modname;
|
||||
|
||||
// Check changes in the module configuration.
|
||||
if (isset($mod->timemodified) and (empty($filter) or in_array('configuration', $filter))) {
|
||||
$updates->configuration = (object) array('updated' => false);
|
||||
if ($updates->configuration->updated = $mod->timemodified > $from) {
|
||||
$updates->configuration->timeupdated = $mod->timemodified;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for updates in files.
|
||||
if (plugin_supports('mod', $cm->modname, FEATURE_MOD_INTRO)) {
|
||||
$fileareas[] = 'intro';
|
||||
}
|
||||
if (!empty($fileareas) and (empty($filter) or in_array('fileareas', $filter))) {
|
||||
$fs = get_file_storage();
|
||||
$files = $fs->get_area_files($context->id, $component, $fileareas, false, "filearea, timemodified DESC", true, $from);
|
||||
foreach ($fileareas as $filearea) {
|
||||
$updates->{$filearea . 'files'} = (object) array('updated' => false);
|
||||
}
|
||||
foreach ($files as $file) {
|
||||
$updates->{$file->get_filearea() . 'files'}->updated = true;
|
||||
$updates->{$file->get_filearea() . 'files'}->itemids[] = $file->get_id();
|
||||
}
|
||||
}
|
||||
|
||||
// Check completion.
|
||||
$supportcompletion = plugin_supports('mod', $cm->modname, FEATURE_COMPLETION_HAS_RULES);
|
||||
$supportcompletion = $supportcompletion or plugin_supports('mod', $cm->modname, FEATURE_COMPLETION_TRACKS_VIEWS);
|
||||
if ($supportcompletion and (empty($filter) or in_array('completion', $filter))) {
|
||||
$updates->completion = (object) array('updated' => false);
|
||||
$completion = new completion_info($course);
|
||||
// Use wholecourse to cache all the modules the first time.
|
||||
$completiondata = $completion->get_data($cm, true);
|
||||
if ($updates->completion->updated = !empty($completiondata->timemodified) && $completiondata->timemodified > $from) {
|
||||
$updates->completion->timemodified = $completiondata->timemodified;
|
||||
}
|
||||
}
|
||||
|
||||
// Check grades.
|
||||
$supportgrades = plugin_supports('mod', $cm->modname, FEATURE_GRADE_HAS_GRADE);
|
||||
$supportgrades = $supportgrades or plugin_supports('mod', $cm->modname, FEATURE_GRADE_OUTCOMES);
|
||||
if ($supportgrades and (empty($filter) or (in_array('gradeitems', $filter) or in_array('outcomes', $filter)))) {
|
||||
require_once($CFG->libdir . '/gradelib.php');
|
||||
$grades = grade_get_grades($course->id, 'mod', $cm->modname, $mod->id, $USER->id);
|
||||
|
||||
if (empty($filter) or in_array('gradeitems', $filter)) {
|
||||
$updates->gradeitems = (object) array('updated' => false);
|
||||
foreach ($grades->items as $gradeitem) {
|
||||
foreach ($gradeitem->grades as $grade) {
|
||||
if ($grade->datesubmitted > $from or $grade->dategraded > $from) {
|
||||
$updates->gradeitems->updated = true;
|
||||
$updates->gradeitems->itemids[] = $gradeitem->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($filter) or in_array('outcomes', $filter)) {
|
||||
$updates->outcomes = (object) array('updated' => false);
|
||||
foreach ($grades->outcomes as $outcome) {
|
||||
foreach ($outcome->grades as $grade) {
|
||||
if ($grade->datesubmitted > $from or $grade->dategraded > $from) {
|
||||
$updates->outcomes->updated = true;
|
||||
$updates->outcomes->itemids[] = $outcome->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check comments.
|
||||
if (plugin_supports('mod', $cm->modname, FEATURE_COMMENT) and (empty($filter) or in_array('comments', $filter))) {
|
||||
$updates->comments = (object) array('updated' => false);
|
||||
require_once($CFG->dirroot . '/comment/locallib.php');
|
||||
$manager = new comment_manager();
|
||||
$comments = $manager->get_component_comments_since($course, $context, $component, $from, $cm);
|
||||
if (!empty($comments)) {
|
||||
$updates->comments->updated = true;
|
||||
$updates->comments->itemids = array_keys($comments);
|
||||
}
|
||||
}
|
||||
|
||||
// Check ratings.
|
||||
if (plugin_supports('mod', $cm->modname, FEATURE_RATE) and (empty($filter) or in_array('ratings', $filter))) {
|
||||
$updates->ratings = (object) array('updated' => false);
|
||||
require_once($CFG->dirroot . '/rating/lib.php');
|
||||
$manager = new rating_manager();
|
||||
$ratings = $manager->get_component_ratings_since($context, $component, $from);
|
||||
if (!empty($ratings)) {
|
||||
$updates->ratings->updated = true;
|
||||
$updates->ratings->itemids = array_keys($ratings);
|
||||
}
|
||||
}
|
||||
|
||||
return $updates;
|
||||
}
|
||||
|
@ -3291,4 +3291,92 @@ class core_course_courselib_testcase extends advanced_testcase {
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function test_course_check_module_updates_since() {
|
||||
global $CFG, $DB, $USER;
|
||||
require_once($CFG->dirroot . '/mod/glossary/lib.php');
|
||||
require_once($CFG->dirroot . '/rating/lib.php');
|
||||
require_once($CFG->dirroot . '/comment/lib.php');
|
||||
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
$CFG->enablecompletion = true;
|
||||
$course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
|
||||
$glossary = $this->getDataGenerator()->create_module('glossary', array(
|
||||
'course' => $course->id,
|
||||
'completion' => COMPLETION_TRACKING_AUTOMATIC,
|
||||
'completionview' => 1,
|
||||
'allowcomments' => 1,
|
||||
'assessed' => RATING_AGGREGATE_AVERAGE,
|
||||
'scale' => 100
|
||||
));
|
||||
$glossarygenerator = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
|
||||
$context = context_module::instance($glossary->cmid);
|
||||
$modinfo = get_fast_modinfo($course);
|
||||
$cm = $modinfo->get_cm($glossary->cmid);
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
|
||||
$this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id);
|
||||
$from = time();
|
||||
|
||||
$teacher = $this->getDataGenerator()->create_user();
|
||||
$teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
|
||||
$this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id);
|
||||
|
||||
assign_capability('mod/glossary:viewanyrating', CAP_ALLOW, $studentrole->id, $context->id, true);
|
||||
|
||||
// Check nothing changed right now.
|
||||
$updates = course_check_module_updates_since($cm, $from);
|
||||
$this->assertFalse($updates->configuration->updated);
|
||||
$this->assertFalse($updates->completion->updated);
|
||||
$this->assertFalse($updates->gradeitems->updated);
|
||||
$this->assertFalse($updates->comments->updated);
|
||||
$this->assertFalse($updates->ratings->updated);
|
||||
$this->assertFalse($updates->introfiles->updated);
|
||||
$this->assertFalse($updates->outcomes->updated);
|
||||
|
||||
$this->waitForSecond();
|
||||
|
||||
// Do some changes.
|
||||
$this->setUser($user);
|
||||
$entry = $glossarygenerator->create_content($glossary);
|
||||
|
||||
$this->setUser($teacher);
|
||||
// Name.
|
||||
set_coursemodule_name($glossary->cmid, 'New name');
|
||||
|
||||
// Add some ratings.
|
||||
$rm = new rating_manager();
|
||||
$result = $rm->add_rating($cm, $context, 'mod_glossary', 'entry', $entry->id, 100, 50, $user->id, RATING_AGGREGATE_AVERAGE);
|
||||
|
||||
// Change grades.
|
||||
$glossary->cmidnumber = $glossary->cmid;
|
||||
glossary_update_grades($glossary, $user->id);
|
||||
|
||||
$this->setUser($user);
|
||||
// Completion status.
|
||||
glossary_view($glossary, $course, $cm, $context, 'letter');
|
||||
|
||||
// Add one comment.
|
||||
$args = new stdClass;
|
||||
$args->context = $context;
|
||||
$args->course = $course;
|
||||
$args->cm = $cm;
|
||||
$args->area = 'glossary_entry';
|
||||
$args->itemid = $entry->id;
|
||||
$args->client_id = 1;
|
||||
$args->component = 'mod_glossary';
|
||||
$manager = new comment($args);
|
||||
$manager->add('blah blah blah');
|
||||
|
||||
// Check upgrade status.
|
||||
$updates = course_check_module_updates_since($cm, $from);
|
||||
$this->assertTrue($updates->configuration->updated);
|
||||
$this->assertTrue($updates->completion->updated);
|
||||
$this->assertTrue($updates->gradeitems->updated);
|
||||
$this->assertTrue($updates->comments->updated);
|
||||
$this->assertTrue($updates->ratings->updated);
|
||||
$this->assertFalse($updates->introfiles->updated);
|
||||
$this->assertFalse($updates->outcomes->updated);
|
||||
}
|
||||
}
|
||||
|
@ -2096,4 +2096,82 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
|
||||
$result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
|
||||
$this->assertCount(0, $result['courses']);
|
||||
}
|
||||
|
||||
public function test_check_updates() {
|
||||
global $DB;
|
||||
$this->resetAfterTest(true);
|
||||
$this->setAdminUser();
|
||||
|
||||
// Create different types of activities.
|
||||
$course = self::getDataGenerator()->create_course();
|
||||
$tocreate = array('assign', 'book', 'choice', 'folder', 'forum', 'glossary', 'imscp', 'label', 'lti', 'page', 'quiz',
|
||||
'resource', 'scorm', 'survey', 'url', 'wiki');
|
||||
|
||||
$modules = array();
|
||||
foreach ($tocreate as $modname) {
|
||||
$modules[$modname]['instance'] = $this->getDataGenerator()->create_module($modname, array('course' => $course->id));
|
||||
$modules[$modname]['cm'] = get_coursemodule_from_id(false, $modules[$modname]['instance']->cmid);
|
||||
$modules[$modname]['context'] = context_module::instance($modules[$modname]['instance']->cmid);
|
||||
}
|
||||
|
||||
$student = self::getDataGenerator()->create_user();
|
||||
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
|
||||
self::getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id);
|
||||
$this->setUser($student);
|
||||
|
||||
$since = time();
|
||||
$this->waitForSecond();
|
||||
$params = array();
|
||||
foreach ($modules as $modname => $data) {
|
||||
$params[$data['cm']->id] = array(
|
||||
'contextlevel' => 'module',
|
||||
'id' => $data['cm']->id,
|
||||
'since' => $since
|
||||
);
|
||||
}
|
||||
|
||||
// Check there is nothing updated because modules are fresh new.
|
||||
$result = core_course_external::check_updates($course->id, $params);
|
||||
$result = external_api::clean_returnvalue(core_course_external::check_updates_returns(), $result);
|
||||
$this->assertCount(0, $result['instances']);
|
||||
$this->assertCount(0, $result['warnings']);
|
||||
|
||||
// Update a module after a second.
|
||||
$this->waitForSecond();
|
||||
set_coursemodule_name($modules['forum']['cm']->id, 'New forum name');
|
||||
|
||||
$found = false;
|
||||
$result = core_course_external::check_updates($course->id, $params);
|
||||
$result = external_api::clean_returnvalue(core_course_external::check_updates_returns(), $result);
|
||||
$this->assertCount(1, $result['instances']);
|
||||
$this->assertCount(0, $result['warnings']);
|
||||
foreach ($result['instances'] as $module) {
|
||||
foreach ($module['updates'] as $update) {
|
||||
if ($module['id'] == $modules['forum']['cm']->id and $update['name'] == 'configuration') {
|
||||
$found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->assertTrue($found);
|
||||
|
||||
// Do not retrieve the configuration field.
|
||||
$filter = array('files');
|
||||
$found = false;
|
||||
$result = core_course_external::check_updates($course->id, $params, $filter);
|
||||
$result = external_api::clean_returnvalue(core_course_external::check_updates_returns(), $result);
|
||||
$this->assertCount(0, $result['instances']);
|
||||
$this->assertCount(0, $result['warnings']);
|
||||
$this->assertFalse($found);
|
||||
|
||||
// Add invalid cmid.
|
||||
$params[] = array(
|
||||
'contextlevel' => 'module',
|
||||
'id' => -2,
|
||||
'since' => $since
|
||||
);
|
||||
$result = core_course_external::check_updates($course->id, $params);
|
||||
$result = external_api::clean_returnvalue(core_course_external::check_updates_returns(), $result);
|
||||
$this->assertCount(1, $result['warnings']);
|
||||
$this->assertEquals(-2, $result['warnings'][0]['itemid']);
|
||||
}
|
||||
}
|
||||
|
@ -335,6 +335,15 @@ $functions = array(
|
||||
'type' => 'read',
|
||||
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
|
||||
),
|
||||
'core_course_check_updates' => array(
|
||||
'classname' => 'core_course_external',
|
||||
'methodname' => 'check_updates',
|
||||
'classpath' => 'course/externallib.php',
|
||||
'description' => 'Check if there is updates affecting the user for the given course and contexts.',
|
||||
'type' => 'read',
|
||||
'ajax' => true,
|
||||
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
|
||||
),
|
||||
'core_enrol_get_course_enrolment_methods' => array(
|
||||
'classname' => 'core_enrol_external',
|
||||
'methodname' => 'get_course_enrolment_methods',
|
||||
|
@ -794,30 +794,44 @@ class file_storage {
|
||||
*
|
||||
* @param int $contextid context ID
|
||||
* @param string $component component
|
||||
* @param string $filearea file area
|
||||
* @param mixed $filearea file area/s, you cannot specify multiple fileareas as well as an itemid
|
||||
* @param int $itemid item ID or all files if not specified
|
||||
* @param string $sort A fragment of SQL to use for sorting
|
||||
* @param bool $includedirs whether or not include directories
|
||||
* @param int $updatedsince return files updated since this time
|
||||
* @return stored_file[] array of stored_files indexed by pathanmehash
|
||||
*/
|
||||
public function get_area_files($contextid, $component, $filearea, $itemid = false, $sort = "itemid, filepath, filename", $includedirs = true) {
|
||||
public function get_area_files($contextid, $component, $filearea, $itemid = false, $sort = "itemid, filepath, filename",
|
||||
$includedirs = true, $updatedsince = 0) {
|
||||
global $DB;
|
||||
|
||||
$conditions = array('contextid'=>$contextid, 'component'=>$component, 'filearea'=>$filearea);
|
||||
if ($itemid !== false) {
|
||||
list($areasql, $conditions) = $DB->get_in_or_equal($filearea, SQL_PARAMS_NAMED);
|
||||
$conditions['contextid'] = $contextid;
|
||||
$conditions['component'] = $component;
|
||||
|
||||
if ($itemid !== false && is_array($filearea)) {
|
||||
throw new coding_exception('You cannot specify multiple fileareas as well as an itemid.');
|
||||
} else if ($itemid !== false) {
|
||||
$itemidsql = ' AND f.itemid = :itemid ';
|
||||
$conditions['itemid'] = $itemid;
|
||||
} else {
|
||||
$itemidsql = '';
|
||||
}
|
||||
|
||||
$updatedsincesql = '';
|
||||
if (!empty($updatedsince)) {
|
||||
$conditions['time'] = $updatedsince;
|
||||
$updatedsincesql = 'AND f.timemodified > :time';
|
||||
}
|
||||
|
||||
$sql = "SELECT ".self::instance_sql_fields('f', 'r')."
|
||||
FROM {files} f
|
||||
LEFT JOIN {files_reference} r
|
||||
ON f.referencefileid = r.id
|
||||
WHERE f.contextid = :contextid
|
||||
AND f.component = :component
|
||||
AND f.filearea = :filearea
|
||||
AND f.filearea $areasql
|
||||
$updatedsincesql
|
||||
$itemidsql";
|
||||
if (!empty($sort)) {
|
||||
$sql .= " ORDER BY {$sort}";
|
||||
|
@ -583,6 +583,8 @@ function grade_get_grades($courseid, $itemtype, $itemmodule, $iteminstance, $use
|
||||
$grade->feedback = $grade_grades[$userid]->feedback;
|
||||
$grade->feedbackformat = $grade_grades[$userid]->feedbackformat;
|
||||
$grade->usermodified = $grade_grades[$userid]->usermodified;
|
||||
$grade->datesubmitted = $grade_grades[$userid]->get_datesubmitted();
|
||||
$grade->dategraded = $grade_grades[$userid]->get_dategraded();
|
||||
|
||||
// create text representation of grade
|
||||
if (in_array($grade_item->id, $needsupdate)) {
|
||||
|
@ -223,6 +223,8 @@ function assign_supports($feature) {
|
||||
return true;
|
||||
case FEATURE_PLAGIARISM:
|
||||
return true;
|
||||
case FEATURE_COMMENT:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return null;
|
||||
@ -1515,3 +1517,39 @@ function mod_assign_output_fragment_gradingpanel($args) {
|
||||
|
||||
return $assign->view('gradingpanel', $viewargs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the module has any update that affects the current user since a given time.
|
||||
*
|
||||
* @param cm_info $cm course module data
|
||||
* @param int $from the time to check updates from
|
||||
* @param array $filter if we need to check only specific updates
|
||||
* @return stdClass an object with the different type of areas indicating if they were updated or not
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
function assign_check_updates_since(cm_info $cm, $from, $filter = array()) {
|
||||
global $DB, $USER, $CFG;
|
||||
require_once($CFG->dirroot . '/mod/assign/locallib.php');
|
||||
|
||||
$updates = new stdClass();
|
||||
$updates = course_check_module_updates_since($cm, $from, array(ASSIGN_INTROATTACHMENT_FILEAREA), $filter);
|
||||
|
||||
// Check if there is a new submission by the user or new grades.
|
||||
$select = 'assignment = :id AND userid = :userid AND (timecreated > :since1 OR timemodified > :since2)';
|
||||
$params = array('id' => $cm->instance, 'userid' => $USER->id, 'since1' => $from, 'since2' => $from);
|
||||
$updates->submissions = (object) array('updated' => false);
|
||||
$submissions = $DB->get_records_select('assign_submission', $select, $params, '', 'id');
|
||||
if (!empty($submissions)) {
|
||||
$updates->submissions->updated = true;
|
||||
$updates->submissions->itemids = array_keys($submissions);
|
||||
}
|
||||
|
||||
$updates->grades = (object) array('updated' => false);
|
||||
$grades = $DB->get_records_select('assign_grades', $select, $params, '', 'id');
|
||||
if (!empty($grades)) {
|
||||
$updates->grades->updated = true;
|
||||
$updates->grades->itemids = array_keys($grades);
|
||||
}
|
||||
|
||||
return $updates;
|
||||
}
|
||||
|
@ -636,3 +636,37 @@ function book_view($book, $chapter, $islastchapter, $course, $cm, $context) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the module has any update that affects the current user since a given time.
|
||||
*
|
||||
* @param cm_info $cm course module data
|
||||
* @param int $from the time to check updates from
|
||||
* @param array $filter if we need to check only specific updates
|
||||
* @return stdClass an object with the different type of areas indicating if they were updated or not
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
function book_check_updates_since(cm_info $cm, $from, $filter = array()) {
|
||||
global $DB;
|
||||
|
||||
$context = $cm->context;
|
||||
$updates = new stdClass();
|
||||
if (!has_capability('mod/book:read', $context)) {
|
||||
return $updates;
|
||||
}
|
||||
$updates = course_check_module_updates_since($cm, $from, array('content'), $filter);
|
||||
|
||||
$select = 'bookid = :id AND (timecreated > :since1 OR timemodified > :since2)';
|
||||
$params = array('id' => $cm->instance, 'since1' => $from, 'since2' => $from);
|
||||
if (!has_capability('mod/book:viewhiddenchapters', $context)) {
|
||||
$select .= ' AND hidden = 0';
|
||||
}
|
||||
$updates->entries = (object) array('updated' => false);
|
||||
$entries = $DB->get_records_select('book_chapters', $select, $params, '', 'id');
|
||||
if (!empty($entries)) {
|
||||
$updates->entries->updated = true;
|
||||
$updates->entries->itemids = array_keys($entries);
|
||||
}
|
||||
|
||||
return $updates;
|
||||
}
|
||||
|
@ -1131,3 +1131,39 @@ function choice_refresh_events($courseid = 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the module has any update that affects the current user since a given time.
|
||||
*
|
||||
* @param cm_info $cm course module data
|
||||
* @param int $from the time to check updates from
|
||||
* @param array $filter if we need to check only specific updates
|
||||
* @return stdClass an object with the different type of areas indicating if they were updated or not
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
function choice_check_updates_since(cm_info $cm, $from, $filter = array()) {
|
||||
global $DB;
|
||||
|
||||
$updates = new stdClass();
|
||||
$choice = $DB->get_record($cm->modname, array('id' => $cm->instance), '*', MUST_EXIST);
|
||||
list($available, $warnings) = choice_get_availability_status($choice);
|
||||
if (!$available) {
|
||||
return $updates;
|
||||
}
|
||||
|
||||
$updates = course_check_module_updates_since($cm, $from, array(), $filter);
|
||||
|
||||
if (!choice_can_view_results($choice)) {
|
||||
return $updates;
|
||||
}
|
||||
// Check if there are new responses in the choice.
|
||||
$updates->answers = (object) array('updated' => false);
|
||||
$select = 'choiceid = :id AND timemodified > :since';
|
||||
$params = array('id' => $choice->id, 'since' => $from);
|
||||
$answers = $DB->get_records_select('choice_answers', $select, $params, '', 'id');
|
||||
if (!empty($answers)) {
|
||||
$updates->answers->updated = true;
|
||||
$updates->answers->itemids = array_keys($answers);
|
||||
}
|
||||
|
||||
return $updates;
|
||||
}
|
||||
|
@ -2861,6 +2861,7 @@ function data_supports($feature) {
|
||||
case FEATURE_RATE: return true;
|
||||
case FEATURE_BACKUP_MOODLE2: return true;
|
||||
case FEATURE_SHOW_DESCRIPTION: return true;
|
||||
case FEATURE_COMMENT: return true;
|
||||
|
||||
default: return null;
|
||||
}
|
||||
|
@ -746,3 +746,17 @@ function folder_print_recent_activity($course, $viewfullnames, $timestart) {
|
||||
echo $list;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the module has any update that affects the current user since a given time.
|
||||
*
|
||||
* @param cm_info $cm course module data
|
||||
* @param int $from the time to check updates from
|
||||
* @param array $filter if we need to check only specific updates
|
||||
* @return stdClass an object with the different type of areas indicating if they were updated or not
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
function folder_check_updates_since(cm_info $cm, $from, $filter = array()) {
|
||||
$updates = course_check_module_updates_since($cm, $from, array('content'), $filter);
|
||||
return $updates;
|
||||
}
|
||||
|
@ -2521,10 +2521,12 @@ function forum_count_discussions($forum, $cm, $course) {
|
||||
* @param int $perpage
|
||||
* @param int $groupid if groups enabled, get discussions for this group overriding the current group.
|
||||
* Use FORUM_POSTS_ALL_USER_GROUPS for all the user groups
|
||||
* @param int $updatedsince retrieve only discussions updated since the given time
|
||||
* @return array
|
||||
*/
|
||||
function forum_get_discussions($cm, $forumsort="", $fullpost=true, $unused=-1, $limit=-1,
|
||||
$userlastmodified=false, $page=-1, $perpage=0, $groupid = -1) {
|
||||
$userlastmodified=false, $page=-1, $perpage=0, $groupid = -1,
|
||||
$updatedsince = 0) {
|
||||
global $CFG, $DB, $USER;
|
||||
|
||||
$timelimit = '';
|
||||
@ -2635,6 +2637,12 @@ function forum_get_discussions($cm, $forumsort="", $fullpost=true, $unused=-1, $
|
||||
$umtable = " LEFT JOIN {user} um ON (d.usermodified = um.id)";
|
||||
}
|
||||
|
||||
$updatedsincesql = '';
|
||||
if (!empty($updatedsince)) {
|
||||
$updatedsincesql = 'AND d.timemodified > ?';
|
||||
$params[] = $updatedsince;
|
||||
}
|
||||
|
||||
$allnames = get_all_user_name_fields(true, 'u');
|
||||
$sql = "SELECT $postdata, d.name, d.timemodified, d.usermodified, d.groupid, d.timestart, d.timeend, d.pinned, $allnames,
|
||||
u.email, u.picture, u.imagealt $umfields
|
||||
@ -2643,8 +2651,9 @@ function forum_get_discussions($cm, $forumsort="", $fullpost=true, $unused=-1, $
|
||||
JOIN {user} u ON p.userid = u.id
|
||||
$umtable
|
||||
WHERE d.forum = ? AND p.parent = 0
|
||||
$timelimit $groupselect
|
||||
$timelimit $groupselect $updatedsincesql
|
||||
ORDER BY $forumsort, d.id DESC";
|
||||
|
||||
return $DB->get_records_sql($sql, $params, $limitfrom, $limitnum);
|
||||
}
|
||||
|
||||
@ -8038,3 +8047,33 @@ function forum_discussion_is_locked($forum, $discussion) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the module has any update that affects the current user since a given time.
|
||||
*
|
||||
* @param cm_info $cm course module data
|
||||
* @param int $from the time to check updates from
|
||||
* @param array $filter if we need to check only specific updates
|
||||
* @return stdClass an object with the different type of areas indicating if they were updated or not
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
function forum_check_updates_since(cm_info $cm, $from, $filter = array()) {
|
||||
|
||||
$context = $cm->context;
|
||||
$updates = new stdClass();
|
||||
if (!has_capability('mod/forum:viewdiscussion', $context)) {
|
||||
return $updates;
|
||||
}
|
||||
|
||||
$updates = course_check_module_updates_since($cm, $from, array(), $filter);
|
||||
|
||||
// Check if there are new discussions in the forum.
|
||||
$updates->discussions = (object) array('updated' => false);
|
||||
$discussions = forum_get_discussions($cm, '', false, -1, -1, true, -1, 0, FORUM_POSTS_ALL_USER_GROUPS, $from);
|
||||
if (!empty($discussions)) {
|
||||
$updates->discussions->updated = true;
|
||||
$updates->discussions->itemids = array_keys($discussions);
|
||||
}
|
||||
|
||||
return $updates;
|
||||
}
|
||||
|
@ -3018,6 +3018,7 @@ function glossary_supports($feature) {
|
||||
case FEATURE_RATE: return true;
|
||||
case FEATURE_BACKUP_MOODLE2: return true;
|
||||
case FEATURE_SHOW_DESCRIPTION: return true;
|
||||
case FEATURE_COMMENT: return true;
|
||||
|
||||
default: return null;
|
||||
}
|
||||
@ -4100,3 +4101,33 @@ function glossary_edit_entry($entry, $course, $cm, $glossary, $context) {
|
||||
}
|
||||
return $entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the module has any update that affects the current user since a given time.
|
||||
*
|
||||
* @param cm_info $cm course module data
|
||||
* @param int $from the time to check updates from
|
||||
* @param array $filter if we need to check only specific updates
|
||||
* @return stdClass an object with the different type of areas indicating if they were updated or not
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
function glossary_check_updates_since(cm_info $cm, $from, $filter = array()) {
|
||||
global $DB;
|
||||
|
||||
$updates = course_check_module_updates_since($cm, $from, array('attachment', 'entry'), $filter);
|
||||
|
||||
$updates->entries = (object) array('updated' => false);
|
||||
$select = 'glossaryid = :id AND (timecreated > :since1 OR timemodified > :since2)';
|
||||
$params = array('id' => $cm->instance, 'since1' => $from, 'since2' => $from);
|
||||
if (!has_capability('mod/glossary:approve', $cm->context)) {
|
||||
$select .= ' AND approved = 1';
|
||||
}
|
||||
|
||||
$entries = $DB->get_records_select('glossary_entries', $select, $params, '', 'id');
|
||||
if (!empty($entries)) {
|
||||
$updates->entries->updated = true;
|
||||
$updates->entries->itemids = array_keys($entries);
|
||||
}
|
||||
|
||||
return $updates;
|
||||
}
|
||||
|
@ -444,3 +444,17 @@ function imscp_view($imscp, $course, $cm, $context) {
|
||||
$completion = new completion_info($course);
|
||||
$completion->set_module_viewed($cm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the module has any update that affects the current user since a given time.
|
||||
*
|
||||
* @param cm_info $cm course module data
|
||||
* @param int $from the time to check updates from
|
||||
* @param array $filter if we need to check only specific updates
|
||||
* @return stdClass an object with the different type of areas indicating if they were updated or not
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
function imscp_check_updates_since(cm_info $cm, $from, $filter = array()) {
|
||||
$updates = course_check_module_updates_since($cm, $from, array('content'), $filter);
|
||||
return $updates;
|
||||
}
|
||||
|
@ -324,3 +324,17 @@ function label_generate_resized_image(stored_file $file, $maxwidth, $maxheight)
|
||||
return $img;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the module has any update that affects the current user since a given time.
|
||||
*
|
||||
* @param cm_info $cm course module data
|
||||
* @param int $from the time to check updates from
|
||||
* @param array $filter if we need to check only specific updates
|
||||
* @return stdClass an object with the different type of areas indicating if they were updated or not
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
function label_check_updates_since(cm_info $cm, $from, $filter = array()) {
|
||||
$updates = course_check_module_updates_since($cm, $from, array(), $filter);
|
||||
return $updates;
|
||||
}
|
||||
|
@ -560,3 +560,30 @@ function lti_view($lti, $course, $cm, $context) {
|
||||
$completion = new completion_info($course);
|
||||
$completion->set_module_viewed($cm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the module has any update that affects the current user since a given time.
|
||||
*
|
||||
* @param cm_info $cm course module data
|
||||
* @param int $from the time to check updates from
|
||||
* @param array $filter if we need to check only specific updates
|
||||
* @return stdClass an object with the different type of areas indicating if they were updated or not
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
function lti_check_updates_since(cm_info $cm, $from, $filter = array()) {
|
||||
global $DB, $USER;
|
||||
|
||||
$updates = course_check_module_updates_since($cm, $from, array(), $filter);
|
||||
|
||||
// Check if there is a new submission.
|
||||
$updates->submissions = (object) array('updated' => false);
|
||||
$select = 'ltiid = :id AND userid = :userid AND (datesubmitted > :since1 OR dateupdated > :since2)';
|
||||
$params = array('id' => $cm->instance, 'userid' => $USER->id, 'since1' => $from, 'since2' => $from);
|
||||
$submissions = $DB->get_records_select('lti_submission', $select, $params, '', 'id');
|
||||
if (!empty($submissions)) {
|
||||
$updates->submissions->updated = true;
|
||||
$updates->submissions->itemids = array_keys($submissions);
|
||||
}
|
||||
|
||||
return $updates;
|
||||
}
|
||||
|
@ -508,3 +508,17 @@ function page_view($page, $course, $cm, $context) {
|
||||
$completion = new completion_info($course);
|
||||
$completion->set_module_viewed($cm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the module has any update that affects the current user since a given time.
|
||||
*
|
||||
* @param cm_info $cm course module data
|
||||
* @param int $from the time to check updates from
|
||||
* @param array $filter if we need to check only specific updates
|
||||
* @return stdClass an object with the different type of areas indicating if they were updated or not
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
function page_check_updates_since(cm_info $cm, $from, $filter = array()) {
|
||||
$updates = course_check_module_updates_since($cm, $from, array('content'), $filter);
|
||||
return $updates;
|
||||
}
|
||||
|
@ -1908,3 +1908,56 @@ function quiz_get_completion_state($course, $cm, $userid, $type) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the module has any update that affects the current user since a given time.
|
||||
*
|
||||
* @param cm_info $cm course module data
|
||||
* @param int $from the time to check updates from
|
||||
* @param array $filter if we need to check only specific updates
|
||||
* @return stdClass an object with the different type of areas indicating if they were updated or not
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
function quiz_check_updates_since(cm_info $cm, $from, $filter = array()) {
|
||||
global $DB, $USER, $CFG;
|
||||
require_once($CFG->dirroot . '/mod/quiz/locallib.php');
|
||||
|
||||
$updates = course_check_module_updates_since($cm, $from, array(), $filter);
|
||||
|
||||
// Check if questions were updated.
|
||||
$updates->questions = (object) array('updated' => false);
|
||||
$quizobj = quiz::create($cm->instance, $USER->id);
|
||||
$quizobj->preload_questions();
|
||||
$quizobj->load_questions();
|
||||
$questionids = array_keys($quizobj->get_questions());
|
||||
if (!empty($questionids)) {
|
||||
list($questionsql, $params) = $DB->get_in_or_equal($questionids, SQL_PARAMS_NAMED);
|
||||
$select = 'id ' . $questionsql . ' AND (timemodified > :time1 OR timecreated > :time2)';
|
||||
$params['time1'] = $from;
|
||||
$params['time2'] = $from;
|
||||
$questions = $DB->count_records_select('question', $select, $params) > 0;
|
||||
if (!empty($questions)) {
|
||||
$updates->questions->updated = true;
|
||||
$updates->questions->itemids = array_keys($questions);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for new attempts or grades.
|
||||
$updates->attempts = (object) array('updated' => false);
|
||||
$updates->grades = (object) array('updated' => false);
|
||||
$select = 'quiz = ? AND userid = ? AND timemodified > ?';
|
||||
$params = array($cm->instance, $USER->id, $from);
|
||||
|
||||
$attempts = $DB->get_records_select('quiz_attempts', $select, $params, '', 'id');
|
||||
if (!empty($attempts)) {
|
||||
$updates->attempts->updated = true;
|
||||
$updates->attempts->itemids = array_keys($attempts);
|
||||
}
|
||||
$grades = $DB->get_records_select('quiz_grades', $select, $params, '', 'id');
|
||||
if (!empty($grades)) {
|
||||
$updates->grades->updated = true;
|
||||
$updates->grades->itemids = array_keys($grades);
|
||||
}
|
||||
|
||||
return $updates;
|
||||
}
|
||||
|
@ -519,3 +519,17 @@ function resource_view($resource, $course, $cm, $context) {
|
||||
$completion = new completion_info($course);
|
||||
$completion->set_module_viewed($cm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the module has any update that affects the current user since a given time.
|
||||
*
|
||||
* @param cm_info $cm course module data
|
||||
* @param int $from the time to check updates from
|
||||
* @param array $filter if we need to check only specific updates
|
||||
* @return stdClass an object with the different type of areas indicating if they were updated or not
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
function resource_check_updates_since(cm_info $cm, $from, $filter = array()) {
|
||||
$updates = course_check_module_updates_since($cm, $from, array('content'), $filter);
|
||||
return $updates;
|
||||
}
|
||||
|
@ -1494,3 +1494,35 @@ function scorm_view($scorm, $course, $cm, $context) {
|
||||
$event->add_record_snapshot('scorm', $scorm);
|
||||
$event->trigger();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the module has any update that affects the current user since a given time.
|
||||
*
|
||||
* @param cm_info $cm course module data
|
||||
* @param int $from the time to check updates from
|
||||
* @param array $filter if we need to check only specific updates
|
||||
* @return stdClass an object with the different type of areas indicating if they were updated or not
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
function scorm_check_updates_since(cm_info $cm, $from, $filter = array()) {
|
||||
global $DB, $USER, $CFG;
|
||||
require_once($CFG->dirroot . '/mod/scorm/locallib.php');
|
||||
|
||||
$scorm = $DB->get_record($cm->modname, array('id' => $cm->instance), '*', MUST_EXIST);
|
||||
$updates = new stdClass();
|
||||
list($available, $warnings) = scorm_get_availability_status($scorm, true, $cm->context);
|
||||
if (!$available) {
|
||||
return $updates;
|
||||
}
|
||||
$updates = course_check_module_updates_since($cm, $from, array('package'), $filter);
|
||||
|
||||
$updates->tracks = (object) array('updated' => false);
|
||||
$select = 'scormid = ? AND userid = ? AND timemodified > ?';
|
||||
$params = array($scorm->id, $USER->id, $from);
|
||||
$tracks = $DB->get_records_select('scorm_scoes_track', $select, $params, '', 'id');
|
||||
if (!empty($tracks)) {
|
||||
$updates->tracks->updated = true;
|
||||
$updates->tracks->itemids = array_keys($tracks);
|
||||
}
|
||||
return $updates;
|
||||
}
|
||||
|
@ -1050,3 +1050,32 @@ function survey_get_completion_state($course, $cm, $userid, $type) {
|
||||
return $type;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the module has any update that affects the current user since a given time.
|
||||
*
|
||||
* @param cm_info $cm course module data
|
||||
* @param int $from the time to check updates from
|
||||
* @param array $filter if we need to check only specific updates
|
||||
* @return stdClass an object with the different type of areas indicating if they were updated or not
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
function survey_check_updates_since(cm_info $cm, $from, $filter = array()) {
|
||||
global $DB, $USER;
|
||||
|
||||
$updates = new stdClass();
|
||||
if (!has_capability('mod/survey:participate', $cm->context)) {
|
||||
return $updates;
|
||||
}
|
||||
$updates = course_check_module_updates_since($cm, $from, array(), $filter);
|
||||
|
||||
$updates->answers = (object) array('updated' => false);
|
||||
$select = 'survey = ? AND userid = ? AND time > ?';
|
||||
$params = array($cm->instance, $USER->id, $from);
|
||||
$answers = $DB->get_records_select('survey_answers', $select, $params, '', 'id');
|
||||
if (!empty($answers)) {
|
||||
$updates->answers->updated = true;
|
||||
$updates->answers->itemids = array_keys($answers);
|
||||
}
|
||||
return $updates;
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ information provided here is intended especially for developers.
|
||||
* update_module_button() and core_renderer::update_module_button() have been deprecated and should not be used anymore.
|
||||
Activity modules should not add the edit module button, the link is already available in the Administration block.
|
||||
Themes can choose to display the link in the buttons row consistently for all module types.
|
||||
* New callback check_updates_since available. Check if the module has any update that affects the current user since the given time.
|
||||
Please refer to mod/assign/lib.php, mod/forum/lib.php or mod/quiz/lib.php for sample code.
|
||||
|
||||
=== 3.1 ===
|
||||
|
||||
|
@ -351,3 +351,17 @@ function url_view($url, $course, $cm, $context) {
|
||||
$completion = new completion_info($course);
|
||||
$completion->set_module_viewed($cm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the module has any update that affects the current user since a given time.
|
||||
*
|
||||
* @param cm_info $cm course module data
|
||||
* @param int $from the time to check updates from
|
||||
* @param array $filter if we need to check only specific updates
|
||||
* @return stdClass an object with the different type of areas indicating if they were updated or not
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
function url_check_updates_since(cm_info $cm, $from, $filter = array()) {
|
||||
$updates = course_check_module_updates_since($cm, $from, array('content'), $filter);
|
||||
return $updates;
|
||||
}
|
||||
|
@ -262,6 +262,8 @@ function wiki_supports($feature) {
|
||||
return true;
|
||||
case FEATURE_SHOW_DESCRIPTION:
|
||||
return true;
|
||||
case FEATURE_COMMENT:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return null;
|
||||
@ -737,3 +739,43 @@ function wiki_page_view($wiki, $page, $course, $cm, $context, $uid = null, $othe
|
||||
$completion = new completion_info($course);
|
||||
$completion->set_module_viewed($cm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the module has any update that affects the current user since a given time.
|
||||
*
|
||||
* @param cm_info $cm course module data
|
||||
* @param int $from the time to check updates from
|
||||
* @param array $filter if we need to check only specific updates
|
||||
* @return stdClass an object with the different type of areas indicating if they were updated or not
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
function wiki_check_updates_since(cm_info $cm, $from, $filter = array()) {
|
||||
global $DB, $CFG;
|
||||
require_once($CFG->dirroot . '/mod/wiki/locallib.php');
|
||||
|
||||
$updates = new stdClass();
|
||||
if (!has_capability('mod/wiki:viewpage', $cm->context)) {
|
||||
return $updates;
|
||||
}
|
||||
$updates = course_check_module_updates_since($cm, $from, array('attachments'), $filter);
|
||||
|
||||
// Check only pages updated in subwikis the user can access.
|
||||
$updates->pages = (object) array('updated' => false);
|
||||
$wiki = $DB->get_record($cm->modname, array('id' => $cm->instance), '*', MUST_EXIST);
|
||||
if ($subwikis = wiki_get_visible_subwikis($wiki, $cm, $cm->context)) {
|
||||
$subwikisids = array();
|
||||
foreach ($subwikis as $subwiki) {
|
||||
$subwikisids[] = $subwiki->id;
|
||||
}
|
||||
list($subwikissql, $params) = $DB->get_in_or_equal($subwikisids, SQL_PARAMS_NAMED);
|
||||
$select = 'subwikiid ' . $subwikissql . ' AND (timemodified > :since1 OR timecreated > :since2)';
|
||||
$params['since1'] = $from;
|
||||
$params['since2'] = $from;
|
||||
$pages = $DB->get_records_select('wiki_pages', $select, $params, '', 'id');
|
||||
if (!empty($pages)) {
|
||||
$updates->pages->updated = true;
|
||||
$updates->pages->itemids = array_keys($pages);
|
||||
}
|
||||
}
|
||||
return $updates;
|
||||
}
|
||||
|
@ -1174,6 +1174,40 @@ class rating_manager {
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ratings created since a given time.
|
||||
*
|
||||
* @param stdClass $context context object
|
||||
* @param string $component component name
|
||||
* @param int $since the time to check
|
||||
* @return array list of ratings db records since the given timelimit
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
public function get_component_ratings_since($context, $component, $since) {
|
||||
global $DB, $USER;
|
||||
|
||||
$ratingssince = array();
|
||||
$where = 'contextid = ? AND component = ? AND (timecreated > ? OR timemodified > ?)';
|
||||
$ratings = $DB->get_records_select('rating', $where, array($context->id, $component, $since, $since));
|
||||
// Check area by area if we have permissions.
|
||||
$permissions = array();
|
||||
$rm = new rating_manager();
|
||||
|
||||
foreach ($ratings as $rating) {
|
||||
// Check if the permission array for the area is cached.
|
||||
if (!isset($permissions[$rating->ratingarea])) {
|
||||
$permissions[$rating->ratingarea] = $rm->get_plugin_permissions_array($context->id, $component,
|
||||
$rating->ratingarea);
|
||||
}
|
||||
|
||||
if (($permissions[$rating->ratingarea]['view'] and $rating->userid == $USER->id) or
|
||||
($permissions[$rating->ratingarea]['viewany'] or $permissions[$rating->ratingarea]['viewall'])) {
|
||||
$ratingssince[$rating->id] = $rating;
|
||||
}
|
||||
}
|
||||
return $ratingssince;
|
||||
}
|
||||
} // End rating_manager class definition.
|
||||
|
||||
/**
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$version = 2016102100.00; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
$version = 2016102100.01; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
// RR = release increments - 00 in DEV branches.
|
||||
// .XX = incremental changes.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user