Skip to content

Commit

Permalink
MDL-53870 mod_quiz: New settings for quiz attempts in the mobile app
Browse files Browse the repository at this point in the history
  • Loading branch information
jleyva committed Sep 28, 2016
1 parent 26162ef commit 8a972ab
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 7 deletions.
18 changes: 18 additions & 0 deletions mod/quiz/attemptlib.php
Original file line number Diff line number Diff line change
Expand Up @@ -2320,6 +2320,24 @@ public function fire_attempt_reviewed_event() {
$event->trigger();
}

/**
* Update the timemodifiedoffline attempt field.
* This function should be used only when web services are being used.
*
* @param int $time time stamp
* @return boolean false if the field is not updated becase web services aren't being used.
* @since Moodle 3.2
*/
public function set_offline_modified_time($time) {
global $DB;

// Update the timemodifiedoffline field only if web services are being used.
if (WS_SERVER) {
$attemptobj->attempt->timemodifiedoffline = $time;
}
return false;
}

}


Expand Down
5 changes: 3 additions & 2 deletions mod/quiz/backup/moodle2/backup_quiz_stepslib.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ protected function define_structure() {
'questionsperpage', 'navmethod', 'shuffleanswers',
'sumgrades', 'grade', 'timecreated',
'timemodified', 'password', 'subnet', 'browsersecurity',
'delay1', 'delay2', 'showuserpicture', 'showblocks', 'completionattemptsexhausted', 'completionpass'));
'delay1', 'delay2', 'showuserpicture', 'showblocks', 'completionattemptsexhausted', 'completionpass',
'allowofflineattempts'));

// Define elements for access rule subplugin settings.
$this->add_subplugin_structure('quizaccess', $quiz, true);
Expand Down Expand Up @@ -84,7 +85,7 @@ protected function define_structure() {

$attempt = new backup_nested_element('attempt', array('id'), array(
'userid', 'attemptnum', 'uniqueid', 'layout', 'currentpage', 'preview',
'state', 'timestart', 'timefinish', 'timemodified', 'timecheckstate', 'sumgrades'));
'state', 'timestart', 'timefinish', 'timemodified', 'timemodifiedoffline', 'timecheckstate', 'sumgrades'));

// This module is using questions, so produce the related question states and sessions
// attaching them to the $attempt element based in 'uniqueid' matching.
Expand Down
1 change: 1 addition & 0 deletions mod/quiz/backup/moodle2/restore_quiz_stepslib.php
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,7 @@ protected function process_quiz_attempt($data) {
$data->timestart = $this->apply_date_offset($data->timestart);
$data->timefinish = $this->apply_date_offset($data->timefinish);
$data->timemodified = $this->apply_date_offset($data->timemodified);

if (!empty($data->timecheckstate)) {
$data->timecheckstate = $this->apply_date_offset($data->timecheckstate);
} else {
Expand Down
14 changes: 12 additions & 2 deletions mod/quiz/classes/external.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ public static function get_quizzes_by_courses($courseids = array()) {
'reviewoverallfeedback', 'questionsperpage', 'navmethod', 'sumgrades', 'grade',
'browsersecurity', 'delay1', 'delay2', 'showuserpicture', 'showblocks',
'completionattemptsexhausted', 'completionpass', 'overduehandling',
'graceperiod', 'preferredbehaviour', 'canredoquestions');
'graceperiod', 'preferredbehaviour', 'canredoquestions',
'allowofflineattempts');
$viewablefields = array_merge($viewablefields, $additionalfields);
}

Expand Down Expand Up @@ -258,6 +259,8 @@ function.', VALUE_OPTIONAL),
exhausted the maximum number of attempts',
VALUE_OPTIONAL),
'completionpass' => new external_value(PARAM_INT, 'Whether to require passing grade', VALUE_OPTIONAL),
'allowofflineattempts' => new external_value(PARAM_INT, 'Whether to allow the quiz to be attempted
offline in the mobile app', VALUE_OPTIONAL),
'autosaveperiod' => new external_value(PARAM_INT, 'Auto-save delay', VALUE_OPTIONAL),
'hasfeedback' => new external_value(PARAM_INT, 'Whether the quiz has any non-blank feedback text',
VALUE_OPTIONAL),
Expand Down Expand Up @@ -445,6 +448,7 @@ private static function attempt_structure() {
'timefinish' => new external_value(PARAM_INT, 'Time when the attempt was submitted.
0 if the attempt has not been submitted yet.', VALUE_OPTIONAL),
'timemodified' => new external_value(PARAM_INT, 'Last modified time.', VALUE_OPTIONAL),
'timemodifiedoffline' => new external_value(PARAM_INT, 'Last modified time via webservices.', VALUE_OPTIONAL),
'timecheckstate' => new external_value(PARAM_INT, 'Next time quiz cron should check attempt for
state changes. NULL means never check.', VALUE_OPTIONAL),
'sumgrades' => new external_value(PARAM_FLOAT, 'Total marks for this attempt.', VALUE_OPTIONAL),
Expand Down Expand Up @@ -748,7 +752,8 @@ public static function start_attempt($quizid, $preflightdata = array(), $forcene
throw new moodle_quiz_exception($quizobj, 'attemptstillinprogress');
}
}
$attempt = quiz_prepare_and_start_new_attempt($quizobj, $attemptnumber, $lastattempt);
$offlineattempt = WS_SERVER ? true : false;
$attempt = quiz_prepare_and_start_new_attempt($quizobj, $attemptnumber, $lastattempt, $offlineattempt);
}

$result = array();
Expand Down Expand Up @@ -1136,6 +1141,8 @@ public static function save_attempt($attemptid, $data, $preflightdata = array())
$_POST[$element['name']] = $element['value'];
}
$timenow = time();
// Update the timemodifiedoffline field.
$attemptobj->set_offline_modified_time($timenow);
$attemptobj->process_auto_save($timenow);
$transaction->allow_commit();

Expand Down Expand Up @@ -1231,7 +1238,10 @@ public static function process_attempt($attemptid, $data, $finishattempt = false
$timeup = $params['timeup'];

$result = array();
// Update the timemodifiedoffline field.
$attemptobj->set_offline_modified_time($timenow);
$result['state'] = $attemptobj->process_attempt($timenow, $finishattempt, $timeup, 0);

$result['warnings'] = $warnings;
return $result;
}
Expand Down
2 changes: 2 additions & 0 deletions mod/quiz/db/install.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
<FIELD NAME="showblocks" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Whether blocks should be shown on the attempt.php and review.php pages."/>
<FIELD NAME="completionattemptsexhausted" TYPE="int" LENGTH="1" NOTNULL="false" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="completionpass" TYPE="int" LENGTH="1" NOTNULL="false" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="allowofflineattempts" TYPE="int" LENGTH="1" NOTNULL="false" DEFAULT="0" SEQUENCE="false" COMMENT="Whether to allow the quiz to be attempted offline in the mobile app"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
Expand Down Expand Up @@ -136,6 +137,7 @@
<FIELD NAME="timestart" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Time when the attempt was started."/>
<FIELD NAME="timefinish" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Time when the attempt was submitted. 0 if the attempt has not been submitted yet."/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Last modified time."/>
<FIELD NAME="timemodifiedoffline" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Last modified time via web services."/>
<FIELD NAME="timecheckstate" TYPE="int" LENGTH="10" NOTNULL="false" DEFAULT="0" SEQUENCE="false" COMMENT="Next time quiz cron should check attempt for state changes. NULL means never check."/>
<FIELD NAME="sumgrades" TYPE="number" LENGTH="10" NOTNULL="false" SEQUENCE="false" DECIMALS="5" COMMENT="Total marks for this attempt."/>
</FIELDS>
Expand Down
27 changes: 27 additions & 0 deletions mod/quiz/db/upgrade.php
Original file line number Diff line number Diff line change
Expand Up @@ -193,5 +193,32 @@ function xmldb_quiz_upgrade($oldversion) {
// Moodle v3.1.0 release upgrade line.
// Put any upgrade step following this.

if ($oldversion < 2016092000) {
// Define new fields to be added to quiz.
$table = new xmldb_table('quiz');

$field = new xmldb_field('allowofflineattempts', XMLDB_TYPE_INTEGER, '1', null, null, null, 0, 'completionpass');
// Conditionally launch add field allowofflineattempts.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
// Quiz savepoint reached.
upgrade_mod_savepoint(true, 2016092000, 'quiz');
}

if ($oldversion < 2016092001) {
// New field for quiz_attemps.
$table = new xmldb_table('quiz_attempts');

$field = new xmldb_field('timemodifiedoffline', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 0, 'timemodified');
// Conditionally launch add field timemodifiedoffline.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}

// Quiz savepoint reached.
upgrade_mod_savepoint(true, 2016092001, 'quiz');
}

return true;
}
8 changes: 7 additions & 1 deletion mod/quiz/locallib.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ function quiz_create_attempt(quiz $quizobj, $attemptnumber, $lastattempt, $timen
$attempt->timestart = $timenow;
$attempt->timefinish = 0;
$attempt->timemodified = $timenow;
$attempt->timemodifiedoffline = 0;
$attempt->state = quiz_attempt::IN_PROGRESS;
$attempt->currentpage = 0;
$attempt->sumgrades = null;
Expand Down Expand Up @@ -2259,10 +2260,11 @@ function quiz_validate_new_attempt(quiz $quizobj, quiz_access_manager $accessman
* @param quiz $quizobj quiz object
* @param int $attemptnumber the attempt number
* @param object $lastattempt last attempt object
* @param bool $offlineattempt whether is an offline attempt or not
* @return object the new attempt
* @since Moodle 3.1
*/
function quiz_prepare_and_start_new_attempt(quiz $quizobj, $attemptnumber, $lastattempt) {
function quiz_prepare_and_start_new_attempt(quiz $quizobj, $attemptnumber, $lastattempt, $offlineattempt = false) {
global $DB, $USER;

// Delete any previous preview attempts belonging to this user.
Expand All @@ -2283,6 +2285,10 @@ function quiz_prepare_and_start_new_attempt(quiz $quizobj, $attemptnumber, $last

$transaction = $DB->start_delegated_transaction();

// Init the timemodifiedoffline for offline attempts.
if ($offlineattempt) {
$attempt->timemodifiedoffline = $attempt->timemodified;
}
$attempt = quiz_attempt_save_started($quizobj, $quba, $attempt);

$transaction->allow_commit();
Expand Down
3 changes: 2 additions & 1 deletion mod/quiz/tests/external_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ public function test_mod_quiz_get_quizzes_by_courses() {
'reviewoverallfeedback', 'questionsperpage', 'navmethod', 'sumgrades', 'grade',
'browsersecurity', 'delay1', 'delay2', 'showuserpicture', 'showblocks',
'completionattemptsexhausted', 'completionpass', 'autosaveperiod', 'hasquestions',
'hasfeedback', 'overduehandling', 'graceperiod', 'preferredbehaviour', 'canredoquestions');
'hasfeedback', 'overduehandling', 'graceperiod', 'preferredbehaviour', 'canredoquestions',
'allowofflineattempts');
$managerfields = array('shuffleanswers', 'timecreated', 'timemodified', 'password', 'subnet');

// Add expected coursemodule and other data.
Expand Down
2 changes: 1 addition & 1 deletion mod/quiz/version.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

defined('MOODLE_INTERNAL') || die();

$plugin->version = 2016052300;
$plugin->version = 2016092001;
$plugin->requires = 2016051900;
$plugin->component = 'mod_quiz';
$plugin->cron = 60;

0 comments on commit 8a972ab

Please sign in to comment.