diff --git a/CHANGES.md b/CHANGES.md index 90a1408..c94fd53 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,6 @@ +Changes in version 2017-07-19 (2017071902) +- Fix: Completion support + Changes in version 2017-07-18 (2017071801) - New: icon.png and icon.svg diff --git a/db/install.xml b/db/install.xml index a17e49e..d293144 100755 --- a/db/install.xml +++ b/db/install.xml @@ -46,6 +46,8 @@ + + diff --git a/db/upgrade.php b/db/upgrade.php index 9b52428..784b9fd 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -1582,6 +1582,8 @@ function xmldb_game_upgrade($oldversion) { // Launch change of type for field thisfield. $dbman->change_field_type($table, $field); + + upgrade_mod_savepoint(true, $ver, 'game'); } if ($oldversion < ($ver = 2017062801)) { @@ -1597,6 +1599,7 @@ function xmldb_game_upgrade($oldversion) { } else { $dbman->add_field($table, $field); } + } if ($oldversion < ($ver = 2017062801)) { @@ -1642,11 +1645,15 @@ function xmldb_game_upgrade($oldversion) { } else { $dbman->add_field($table, $field); } + + upgrade_mod_savepoint(true, $ver, 'game'); } if ($oldversion < ($ver = 2017070301)) { $sql = "UPDATE {$CFG->prefix}game SET glossarycategoryid=0 WHERE glossarycategoryid < 0"; $DB->execute( $sql); + + upgrade_mod_savepoint(true, $ver, 'game'); } if ($oldversion < ($ver = 2017070403)) { @@ -1674,6 +1681,35 @@ function xmldb_game_upgrade($oldversion) { } $DB->update_record( 'game_snakes_database', $updrec); } + + upgrade_mod_savepoint(true, $ver, 'game'); + } + + if ($oldversion < ($ver = 2017071901)) { + + // Define field completionattemptsexhausted to be added to quiz. + $table = new xmldb_table('game'); + $field = new xmldb_field('completionattemptsexhausted', XMLDB_TYPE_INTEGER, '1', null, null, null, '0'); + + // Conditionally launch add field completionattemptsexhausted. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + upgrade_mod_savepoint(true, $ver, 'game'); + } + + if ($oldversion < ($ver = 2017071902)) { + // Define field completionpass to be added to quiz. + $table = new xmldb_table('game'); + $field = new xmldb_field('completionpass', XMLDB_TYPE_INTEGER, '1', null, null, null, 0, 'completionattemptsexhausted'); + + // Conditionally launch add field completionpass. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + upgrade_mod_savepoint(true, $ver, 'game'); } return true; diff --git a/lib.php b/lib.php index f26604d..4789729 100644 --- a/lib.php +++ b/lib.php @@ -1352,8 +1352,6 @@ function game_reset_userdata($data) { function game_get_completion_state($course, $cm, $userid, $type) { global $CFG, $DB; - require_once($CFG->dirroot . '/mod/game/locallib.php'); - if (($cm->completion == 0) or ($cm->completion == 1)) { // Completion option is not enabled so just return $type. return $type; @@ -1368,9 +1366,25 @@ function game_get_completion_state($course, $cm, $userid, $type) { print_error('invalidcoursemodule'); } - $grade = $DB->get_record_select('game_grades', "userid=$userid AND gameid = $cm->instance", null, 'id,score'); + // Check for passing grade. + if ($game->completionpass) { + require_once($CFG->libdir . '/gradelib.php'); + $item = grade_item::fetch(array('courseid' => $course->id, 'itemtype' => 'mod', + 'itemmodule' => 'game', 'iteminstance' => $cm->instance, 'outcomeid' => null)); + if ($item) { + $grades = grade_grade::fetch_users_grades($item, array($userid), false); + if (!empty($grades[$userid])) { + return $grades[$userid]->is_passed($item); + } + } + } + + return false; + + //$sql = "SELECT MAX(score) as score FROM {$CFG->prefix}game_grades WHERE gameid=$cm->instance AND userid=$userid"; + //$grade = $DB->get_record_sql( $sql); - return $grade && $grade->score > 0; + //return $grade && $grade->score > 0; } /** @@ -1441,3 +1455,38 @@ function game_pix_url( $filename, $module='') { return $OUTPUT->pix_url($filename, $module); } } + +/** + * Callback which returns human-readable strings describing the active completion custom rules for the module instance. + * + * @param cm_info|stdClass $cm object with fields ->completion and ->customdata['customcompletionrules'] + * @return array $descriptions the array of descriptions for the custom rules. + */ +function mod_game_get_completion_active_rule_descriptions($cm) { + // Values will be present in cm_info, and we assume these are up to date. + if (empty($cm->customdata['customcompletionrules']) + || $cm->completion != COMPLETION_TRACKING_AUTOMATIC) { + return []; + } + + $descriptions = []; + foreach ($cm->customdata['customcompletionrules'] as $key => $val) { + switch ($key) { + case 'completionattemptsexhausted': + if (empty($val)) { + continue; + } + $descriptions[] = get_string('completionattemptsexhausteddesc', 'quiz'); + break; + case 'completionpass': + if (empty($val)) { + continue; + } + $descriptions[] = get_string('completionpassdesc', 'quiz', format_time($val)); + break; + default: + break; + } + } + return $descriptions; +} diff --git a/mod_form.php b/mod_form.php index 4207069..1842d36 100644 --- a/mod_form.php +++ b/mod_form.php @@ -162,9 +162,12 @@ class mod_game_mod_form extends moodleform_mod { $mform->addElement('selectyesno', 'disablesummarize', get_string('disablesummarize', 'game')); // Grade options. - $mform->addElement('header', 'gradeoptions', get_string('grades', 'grades')); + //$mform->addElement('header', 'gradeoptions', get_string('grades', 'grades')); + $this->standard_grading_coursemodule_elements(); + $mform->removeElement('grade'); $mform->addElement('text', 'grade', get_string( 'grademax', 'grades'), array('size' => 4)); $mform->setType('grade', PARAM_INT); + $gradingtypeoptions = array(); $gradingtypeoptions[ GAME_GRADEHIGHEST] = get_string('gradehighest', 'game'); $gradingtypeoptions[ GAME_GRADEAVERAGE] = get_string('gradeaverage', 'game'); @@ -520,6 +523,19 @@ class mod_game_mod_form extends moodleform_mod { } } + if (array_key_exists('completion', $data) && $data['completion'] == COMPLETION_TRACKING_AUTOMATIC) { + $completionpass = isset($data['completionpass']) ? $data['completionpass'] : $this->current->completionpass; + + // Show an error if require passing grade was selected and the grade to pass was set to 0. + if ($completionpass && (empty($data['gradepass']) || grade_floatval($data['gradepass']) == 0)) { + if (isset($data['completionpass'])) { + $errors['completionpassgroup'] = get_string('gradetopassnotset', 'quiz'); + } else { + $errors['gradepass'] = get_string('gradetopassmustbeset', 'quiz'); + } + } + } + return $errors; } @@ -602,4 +618,37 @@ class mod_game_mod_form extends moodleform_mod { parent::set_data($defaultvalues); } + + /** + * Display module-specific activity completion rules. + * Part of the API defined by moodleform_mod + * @return array Array of string IDs of added items, empty array if none + */ + public function add_completion_rules() { + $mform = $this->_form; + $items = array(); + + $group = array(); + $group[] = $mform->createElement('advcheckbox', 'completionpass', null, get_string('completionpass', 'quiz'), + array('group' => 'cpass')); + + $group[] = $mform->createElement('advcheckbox', 'completionattemptsexhausted', null, + get_string('completionattemptsexhausted', 'quiz'), + array('group' => 'cattempts')); + $mform->disabledIf('completionattemptsexhausted', 'completionpass', 'notchecked'); + $mform->addGroup($group, 'completionpassgroup', get_string('completionpass', 'quiz'), '   ', false); + $mform->addHelpButton('completionpassgroup', 'completionpass', 'quiz'); + $items[] = 'completionpassgroup'; + return $items; + } + + /** + * Called during validation. Indicates whether a module-specific completion rule is selected. + * + * @param array $data Input data (not yet validated) + * @return bool True if one or more rules is enabled, false if none are. + */ + public function completion_rule_enabled($data) { + return !empty($data['completionattemptsexhausted']) || !empty($data['completionpass']); + } } diff --git a/version.php b/version.php index c1aa9f2..5091471 100644 --- a/version.php +++ b/version.php @@ -35,10 +35,10 @@ if (!isset( $plugin)) { } $plugin->component = 'mod_game'; // Full name of the plugin (used for diagnostics). -$plugin->version = 2017071801; // The current module version (Date: YYYYMMDDXX). +$plugin->version = 2017071902; // The current module version (Date: YYYYMMDDXX). $plugin->requires = 2010112400; // Requires Moodle 2.0. $plugin->cron = 0; // Period for cron to check this module (secs). -$plugin->release = '2017-07-18'; +$plugin->release = '2017-07-19'; $plugin->maturity = MATURITY_STABLE; if ($useplugin != 2) {