diff --git a/admin/cli/quiztableadditions.php b/admin/cli/quiztableadditions.php new file mode 100644 index 0000000..7ab9f87 --- /dev/null +++ b/admin/cli/quiztableadditions.php @@ -0,0 +1,68 @@ +. + +/** + * @package core + * @subpackage cli + * @copyright 2017 Amrata Ramchandani + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +define('CLI_SCRIPT', true); + +require(__DIR__.'/../../config.php'); +require_once($CFG->libdir.'/clilib.php'); + +list($options, $unrecognized) = cli_get_params(array('help' => false), array('h' => 'help')); + +if ($unrecognized) { + $unrecognized = implode("\n ", $unrecognized); + cli_error(get_string('cliunknowoption', 'admin', $unrecognized), 2); +} + +if ($options['help']) { + $help = +"Adds new column 'enableclear' in moodle quiz table +Adds 2 new records in moodle config plugins. +The records are (quiz,enableclear_adv,1) and (quiz,enableclear,0) + +Options: +-h, --help Print out this help + +Example: +\$sudo -u www-data /usr/bin/php admin/cli/quiztableadditions.php +"; + + echo $help; + exit(0); +} + +global $DB; + +$dbman = $DB->get_manager(); + +$table = new xmldb_table('quiz'); +$field = new xmldb_field('enableclear',XMLDB_TYPE_INTEGER,'4'); + +if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); +} + +set_config('enableclear_adv', '1', 'quiz'); +set_config('enableclear', '0', 'quiz'); + +purge_all_caches(); +exit(0); diff --git a/mod/quiz/attempt.php b/mod/quiz/attempt.php index f1c26ab..685a399 100644 --- a/mod/quiz/attempt.php +++ b/mod/quiz/attempt.php @@ -42,6 +42,13 @@ $page = optional_param('page', 0, PARAM_INT); $cmid = optional_param('cmid', null, PARAM_INT); $attemptobj = quiz_create_attempt_handling_errors($attemptid, $cmid); + +// Check for clear button option and insert corresponding JS. +if($attemptobj->get_quiz()->enableclear) { + $PAGE->requires->jquery(); + $PAGE->requires->js( '/mod/quiz/clearbutton.js'); +} + $page = $attemptobj->force_page_number_into_range($page); $PAGE->set_url($attemptobj->attempt_url(null, $page)); diff --git a/mod/quiz/clearbutton.js b/mod/quiz/clearbutton.js new file mode 100644 index 0000000..6f22a99 --- /dev/null +++ b/mod/quiz/clearbutton.js @@ -0,0 +1,31 @@ +jQuery(function($) { + + if ($("input[type]").is(":radio")) { + $(".answer").append(""); + } + + $("input[type='radio']:checked").each(function(e){ + $(this).closest('.answer').find("button").show(); + }); + + + $("input[type=radio]").on('click', function() { + $(this).closest('.answer').find('button[name=clear]').show(); + }); + + $('button[name=clear]').on('click', function() { + $(this).closest('.answer').find(':radio').prop('checked', false); + $(this).closest('.answer').find('button[name=clear]').hide(); + }); + + if ($('.content').parent().hasClass("deferredfeedback")) { + if ($('.answer .r0 input').prop('disabled')) { + $("button[name=clear]").remove(); + } + } else { + if (!($('div.im-controls').length)) { + $("button[name=clear]").remove(); + } + } + +}); diff --git a/mod/quiz/db/install.xml b/mod/quiz/db/install.xml index 8ff8747..edcb5bc 100644 --- a/mod/quiz/db/install.xml +++ b/mod/quiz/db/install.xml @@ -20,6 +20,7 @@ + diff --git a/mod/quiz/lang/en/quiz.php b/mod/quiz/lang/en/quiz.php index 7d566f5..88e36f5 100644 --- a/mod/quiz/lang/en/quiz.php +++ b/mod/quiz/lang/en/quiz.php @@ -188,6 +188,7 @@ $string['configdelay1'] = 'If you set a time delay, then a student has to wait f $string['configdelay1st2nd'] = 'If you set a time delay here, the student cannot start their second attempt until this much time has passed since the end of their first attempt.'; $string['configdelay2'] = 'If you set a time delay here, then a student has to wait for that time before they can attempt their third or later attempts.'; $string['configeachattemptbuildsonthelast'] = 'If multiple attempts are allowed then each new attempt contains the results of the previous attempt.'; +$string['configenableclearbutton'] = 'If enabled, the clear button will be added in the quiz with multichoice questions in order to support an option to clear selected radio buttons'; $string['configgrademethod'] = 'When multiple attempts are allowed, which method should be used to calculate the student\'s final grade for the quiz.'; $string['configintro'] = 'The values you set here define the default values that are used in the settings form when you create a new quiz. You can also configure which quiz settings are considered advanced.'; $string['configmaximumgrade'] = 'The default grade that the quiz grade is scaled to be out of.'; @@ -314,6 +315,8 @@ If you would still like to submit this attempt, please go to {$a->attemptsummary $string['emailoverduesmall'] = 'You did not submit your attempt at {$a->quizname}. Please go to {$a->attemptsummaryurl} before {$a->attemptgraceend} if you would still like to submit.'; $string['emailoverduesubject'] = 'Attempt now overdue: {$a->quizname}'; $string['empty'] = 'Empty'; +$string['enableclearbutton'] = 'Enable clear button for single answer questions'; +$string['enableclearbutton_help'] = 'If enabled, the clear button will be added in the quiz with multichoice questions in order to support an option to clear selected radio buttons'; $string['enabled'] = 'Enabled'; $string['endtest'] = 'Finish attempt ...'; $string['erroraccessingreport'] = 'You cannot access this report'; diff --git a/mod/quiz/mod_form.php b/mod/quiz/mod_form.php index 27eec4a..2121336 100644 --- a/mod/quiz/mod_form.php +++ b/mod/quiz/mod_form.php @@ -216,6 +216,12 @@ class mod_quiz_mod_form extends moodleform_mod { $mform->disabledIf('attemptonlast', 'attempts', 'eq', 1); } + // Enable clear button for single answer questions. + $mform->addElement('selectyesno', 'enableclear', get_string('enableclearbutton', 'quiz')); + $mform->addHelpButton('enableclear', 'enableclearbutton', 'quiz'); + $mform->setAdvanced('enableclear', $quizconfig->enableclear_adv); + $mform->setDefault('enableclear', $quizconfig->enableclear); + // ------------------------------------------------------------------------------- $mform->addElement('header', 'reviewoptionshdr', get_string('reviewoptionsheading', 'quiz')); diff --git a/mod/quiz/settings.php b/mod/quiz/settings.php index ef504ce..29e8146 100644 --- a/mod/quiz/settings.php +++ b/mod/quiz/settings.php @@ -135,6 +135,11 @@ if ($ADMIN->fulltree) { get_string('configeachattemptbuildsonthelast', 'quiz'), array('value' => 0, 'adv' => true))); + // Clear Button for multichoice questions. + $quizsettings->add(new admin_setting_configcheckbox_with_advanced('quiz/enableclear', + get_string('enableclearbutton', 'quiz'), get_string('configenableclearbutton', 'quiz'), + array('value' => 0, 'adv' => true))); + // Review options. $quizsettings->add(new admin_setting_heading('reviewheading', get_string('reviewoptionsheading', 'quiz'), '')); diff --git a/question/engine/questionattempt.php b/question/engine/questionattempt.php index 5473535..025fe39 100644 --- a/question/engine/questionattempt.php +++ b/question/engine/questionattempt.php @@ -408,6 +408,17 @@ class question_attempt { return end($this->steps); } + // Get the last step which has data as answer or _order of a particular question. + public function get_unfinished_step() { + foreach($this -> get_reverse_step_iterator() as $step) { + $name = array('answer', '_order'); + foreach($name as $key) { + if ($step -> has_qt_var($key)) + return $key; + } + } + } + /** * @return boolean whether this question_attempt has autosaved data from * some time in the past. @@ -1263,6 +1274,15 @@ class question_attempt { public function process_action($submitteddata, $timestamp = null, $userid = null, $existingstepid = null) { $pendingstep = new question_attempt_pending_step($submitteddata, $timestamp, $userid, $existingstepid); $this->discard_autosaved_step(); + + /** While clearing the quiz option,we are trying to bring the question attempt step data to '_order' + * and we could find that '_order' data only in initial step i.e step[0] **/ + + if( empty($submitteddata)){ + $step_zero_data = $this->steps[0]->get_all_data(); + $pendingstep->set_data($step_zero_data); + } + if ($this->behaviour->process_action($pendingstep) == self::KEEP) { $this->add_step($pendingstep); if ($pendingstep->response_summary_changed()) { diff --git a/question/engine/questionattemptstep.php b/question/engine/questionattemptstep.php index c0bb6fd..2e76c1f 100644 --- a/question/engine/questionattemptstep.php +++ b/question/engine/questionattemptstep.php @@ -370,6 +370,12 @@ class question_attempt_step { return $this->data; } + // Setting Step Data. + public function set_data($data){ + $this->data = $data; + } + + /** * Set a metadata variable. * diff --git a/question/type/multichoice/question.php b/question/type/multichoice/question.php index 09b9493..459e598 100644 --- a/question/type/multichoice/question.php +++ b/question/type/multichoice/question.php @@ -259,7 +259,8 @@ class qtype_multichoice_single_question extends qtype_multichoice_base { } public function get_response(question_attempt $qa) { - return $qa->get_last_qt_var('answer', -1); + $laststep_name=$qa->get_unfinished_step(); + return $qa->get_last_qt_var($laststep_name, -1); } public function is_choice_selected($response, $value) {