diff --git a/classes/question/bank/studentquiz_bank_view.php b/classes/question/bank/studentquiz_bank_view.php
index 7b76bcb9..34620521 100755
--- a/classes/question/bank/studentquiz_bank_view.php
+++ b/classes/question/bank/studentquiz_bank_view.php
@@ -491,10 +491,17 @@ public function create_new_question_form($categoryid, $canadd) {
$qtypecontainer = \html_writer::div(
print_choose_qtype_to_add_form(array(), $allowedtypes, true
), '', array('id' => 'qtypechoicecontainer'));
- $output .= \html_writer::div(
- $OUTPUT->render(new \single_button($url, $caption, 'get', true)) .
- $qtypecontainer, 'createnewquestion'
- );
+ $questionsubmissionbutton = new \single_button($url, $caption, 'get', true);
+
+ list($message, $questionsubmissionallow) = mod_studentquiz_check_availability($this->studentquiz->opensubmissionfrom,
+ $this->studentquiz->closesubmissionfrom, 'submission');
+
+ $questionsubmissionbutton->disabled = !$questionsubmissionallow;
+ $output .= \html_writer::div($OUTPUT->render($questionsubmissionbutton) . $qtypecontainer, 'createnewquestion');
+
+ if (!empty($message)) {
+ $output .= $this->renderer->render_availability_message($message, 'mod_studentquiz_submission_info');
+ }
} else {
$output .= get_string('nopermissionadd', 'question');
}
diff --git a/db/install.xml b/db/install.xml
index 499cd31f..655d7f5d 100644
--- a/db/install.xml
+++ b/db/install.xml
@@ -24,6 +24,10 @@
+
+
+
+
diff --git a/db/upgrade.php b/db/upgrade.php
index ec002c92..e15fcde0 100644
--- a/db/upgrade.php
+++ b/db/upgrade.php
@@ -451,5 +451,19 @@ function xmldb_studentquiz_upgrade($oldversion) {
upgrade_mod_savepoint(true, 2018121800, 'studentquiz');
}
+ if ($oldversion < 2018122500) {
+ $table = new xmldb_table('studentquiz');
+ $fieldnames = ['opensubmissionfrom', 'closesubmissionfrom', 'openansweringfrom', 'closeansweringfrom'];
+
+ foreach ($fieldnames as $fieldname) {
+ $field = new xmldb_field($fieldname, XMLDB_TYPE_INTEGER, 10, null, XMLDB_NOTNULL, null, '0');
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ }
+ }
+
+ upgrade_mod_savepoint(true, 2018122500, 'studentquiz');
+ }
+
return true;
}
diff --git a/lang/en/studentquiz.php b/lang/en/studentquiz.php
index b4859a3b..5f3574d5 100644
--- a/lang/en/studentquiz.php
+++ b/lang/en/studentquiz.php
@@ -92,6 +92,12 @@
$string['progress_bar_caption'] = 'Your progress in this StudentQuiz activity';
$string['no_questions_filter'] = 'None of the questions matched your filter criteria. Reset the filter to see all.';
$string['no_questions_add'] = 'There are no questions in this StudentQuiz. Feel free to add some questions.';
+$string['before_submission_start_date'] = 'Open for question submission from {$a}.';
+$string['before_submission_end_date'] = 'This StudentQuiz closes for question submission on {$a}.';
+$string['after_submission_end_date'] = 'This StudentQuiz closed for question submission on {$a}.';
+$string['before_answering_start_date'] = 'Open for answering from {$a}.';
+$string['before_answering_end_date'] = 'This StudentQuiz closes for answering on {$a}.';
+$string['after_answering_end_date'] = 'This StudentQuiz closed for answering on {$a}.';
// Blocks.
$string['statistic_block_title'] = 'My Progress';
@@ -167,10 +173,16 @@
$string['settings_allowedqtypes'] = 'Allowed question types';
$string['settings_allowedqtypes_help'] = 'Here you specify the type of questions that are allowed';
$string['settings_qtypes_default_new_activity'] = 'The following are default for a new activity';
+$string['settings_availability_open_submission_from'] = 'Open for question submission from';
+$string['settings_availability_close_submission_from'] = 'Closed for question submission from';
+$string['settings_availability_open_answering_from'] = 'Open for answering from';
+$string['settings_availability_close_answering_from'] = 'Close for answering from';
// Error messages.
$string['needtoallowatleastoneqtype'] = 'You need to allow at least one question type';
$string['please_enrole_message'] = 'Please enroll in this course to see your personal progress';
+$string['submissionendbeforestart'] = 'Submissions deadline can not be specified before the open for submissions date';
+$string['answeringndbeforestart'] = 'Answering deadline can not be specified before the open for answering date';
// Admin settings.
$string['rankingsettingsheader'] = 'Ranking settings';
diff --git a/locallib.php b/locallib.php
index 30071fc9..8fd1e6a8 100644
--- a/locallib.php
+++ b/locallib.php
@@ -1301,3 +1301,32 @@ function mod_studentquiz_fix_wrong_parent_in_question_categories() {
}
}
}
+
+/**
+ * Check that StudentQuiz is allowing answering or not.
+ *
+ * @param int $openform Open date
+ * @param int $closefrom Close date
+ * @param string $type submission or answering
+ * @return array Message and Allow or not
+ */
+function mod_studentquiz_check_availability($openform, $closefrom, $type) {
+ $message = '';
+ $availabilityallow = true;
+
+ if (time() < $openform) {
+ $availabilityallow = false;
+ $message = get_string('before_' . $type . '_start_date', 'studentquiz',
+ userdate($openform, get_string('strftimedatetimeshort', 'langconfig')));
+ } else if (time() < $closefrom) {
+ $message = get_string('before_' . $type . '_end_date', 'studentquiz',
+ userdate($closefrom, get_string('strftimedatetimeshort', 'langconfig')));
+ }
+ if ($closefrom && time() >= $closefrom) {
+ $availabilityallow = false;
+ $message = get_string('after_' . $type . '_end_date', 'studentquiz',
+ userdate($closefrom, get_string('strftimedatetimeshort', 'langconfig')));
+ }
+
+ return [$message, $availabilityallow];
+}
diff --git a/mod_form.php b/mod_form.php
index 19953b2f..bc037374 100644
--- a/mod_form.php
+++ b/mod_form.php
@@ -150,6 +150,17 @@ public function definition() {
$mform->disabledIf('allowedqtypes', "allowedqtypes[ALL]", 'checked');
$mform->addHelpButton('allowedqtypes', 'settings_allowedqtypes', 'studentquiz');
+ // Availability.
+ $mform->addElement('header', 'availability', get_string('availability', 'moodle'));
+ $mform->addElement('date_time_selector', 'opensubmissionfrom',
+ get_string('settings_availability_open_submission_from', 'studentquiz'), ['optional' => true]);
+ $mform->addElement('date_time_selector', 'closesubmissionfrom',
+ get_string('settings_availability_close_submission_from', 'studentquiz'), ['optional' => true]);
+ $mform->addElement('date_time_selector', 'openansweringfrom',
+ get_string('settings_availability_open_answering_from', 'studentquiz'), ['optional' => true]);
+ $mform->addElement('date_time_selector', 'closeansweringfrom',
+ get_string('settings_availability_close_answering_from', 'studentquiz'), ['optional' => true]);
+
// Add standard elements, common to all modules.
$this->standard_coursemodule_elements();
@@ -183,6 +194,14 @@ public function validation($data, $files) {
if (!isset($data['allowedqtypes'])) {
$errors['allowedqtypes'] = get_string('needtoallowatleastoneqtype', 'studentquiz');
}
+ if ($data['opensubmissionfrom'] > 0 && $data['closesubmissionfrom'] > 0 &&
+ $data['opensubmissionfrom'] >= $data['closesubmissionfrom']) {
+ $errors['closesubmissionfrom'] = get_string('submissionendbeforestart', 'studentquiz');
+ }
+ if ($data['openansweringfrom'] > 0 && $data['closeansweringfrom'] > 0 &&
+ $data['openansweringfrom'] >= $data['closeansweringfrom']) {
+ $errors['closeansweringfrom'] = get_string('answeringndbeforestart', 'studentquiz');
+ }
return $errors;
}
}
diff --git a/pix/info.svg b/pix/info.svg
new file mode 100644
index 00000000..69bd1018
--- /dev/null
+++ b/pix/info.svg
@@ -0,0 +1,18 @@
+
+
+
diff --git a/renderer.php b/renderer.php
index 6c55d74c..fbd9b4e7 100755
--- a/renderer.php
+++ b/renderer.php
@@ -1095,13 +1095,23 @@ public function render_control_buttons($catcontext, $hasquestionincategory, $add
$output .= html_writer::tag('strong', ' ' . get_string('withselected', 'question') . ':');
$output .= html_writer::empty_tag('br');
+ $studentquiz = mod_studentquiz_load_studentquiz($this->page->url->get_param('cmid'), $this->page->context->id);
+ list($message, $answeringallow) = mod_studentquiz_check_availability(
+ $studentquiz->openansweringfrom, $studentquiz->closeansweringfrom, 'answering');
+
if ($hasquestionincategory) {
- $output .= html_writer::empty_tag('input', [
- 'class' => 'btn btn-primary form-submit',
- 'type' => 'submit',
- 'name' => 'startquiz',
- 'value' => get_string('start_quiz_button', 'studentquiz')
- ]);
+ $params = [
+ 'class' => 'btn btn-primary form-submit',
+ 'type' => 'submit',
+ 'name' => 'startquiz',
+ 'value' => get_string('start_quiz_button', 'studentquiz')
+ ];
+
+ if (!$answeringallow) {
+ $params['disabled'] = 'disabled';
+ }
+
+ $output .= html_writer::empty_tag('input', $params);
}
if ($caneditall) {
@@ -1132,6 +1142,11 @@ public function render_control_buttons($catcontext, $hasquestionincategory, $add
ob_end_clean();
}
+ if (!empty($message)) {
+ $output .= $this->render_availability_message($message, 'mod_studentquiz_answering_info');
+ }
+
+
$output .= html_writer::end_div();
return $output;
@@ -1238,6 +1253,24 @@ private function generate_hidden_input($name, $value) {
return $output;
}
+ /**
+ * Render the availability message
+ *
+ * @param string $message Message to show
+ * @param string $class Class of the message
+ * @return string HTML string
+ */
+ public function render_availability_message($message, $class) {
+ $output = '';
+
+ if (!empty($message)) {
+ $icon = new \pix_icon('info', get_string('info'), 'studentquiz');
+ $output = \html_writer::div($this->output->render($icon) . $message, $class);
+ }
+
+ return $output;
+ }
+
}
class mod_studentquiz_attempt_renderer extends mod_studentquiz_renderer {
diff --git a/tests/behat/behat_mod_studentquiz.php b/tests/behat/behat_mod_studentquiz.php
new file mode 100644
index 00000000..e58685ff
--- /dev/null
+++ b/tests/behat/behat_mod_studentquiz.php
@@ -0,0 +1,72 @@
+.
+
+/**
+ * Steps definitions related to mod_studentquiz.
+ *
+ * @package mod_studentquiz
+ * @category test
+ * @copyright 2019 HSR (http://www.hsr.ch)
+ * @author 2019 Huong Nguyen
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once(__DIR__ . '/../../../../lib/behat/behat_base.php');
+
+/**
+ * Steps definitions related to mod_studentquiz.
+ *
+ * @package mod_studentquiz
+ * @category test
+ * @copyright 2019 HSR (http://www.hsr.ch)
+ * @author 2019 Huong Nguyen
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class behat_mod_studentquiz extends behat_base {
+
+ /**
+ * @Given /^I set the availability field "(?P(?:[^"]|\\")*)" to "(?P(?:[^"]|\\")*)" days from now$/
+ * @param string $field Field name.
+ * @param string $days Number of days from now.
+ */
+ public function i_set_availability_field_to($field, $days) {
+ $date = strtotime($days . ' day');
+ $day = date('j', $date);
+ $month = date('F', $date);
+ $year = date('Y', $date);
+ $this->set_field_value('id_' . $field . '_day', $day);
+ $this->set_field_value('id_' . $field . '_month', $month);
+ $this->set_field_value('id_' . $field . '_year', $year);
+ }
+
+ /**
+ * Generic field setter.
+ *
+ * Internal API method, a generic *I set "VALUE" to "FIELD" field*
+ * could be created based on it.
+ *
+ * @param string $fieldlocator The pointer to the field, it will depend on the field type.
+ * @param string $value
+ * @return void
+ */
+ protected function set_field_value($fieldlocator, $value) {
+ // We delegate to behat_form_field class, it will
+ // guess the type properly as it is a select tag.
+ $field = behat_field_manager::get_form_field_from_label($fieldlocator, $this);
+ $field->set_value($value);
+ }
+
+}
diff --git a/tests/behat/question_submission_answering_phases.feature b/tests/behat/question_submission_answering_phases.feature
new file mode 100644
index 00000000..2eed19ee
--- /dev/null
+++ b/tests/behat/question_submission_answering_phases.feature
@@ -0,0 +1,183 @@
+@mod @mod_studentquiz
+Feature: Question submission and answering will follow the availability setting
+ In order to allow users to submission questions or answering questions only in a limited period
+ As a teacher
+ I need availability setting for question submission and question answering
+
+ Background:
+ Given the following "courses" exist:
+ | fullname | shortname | category |
+ | Course 1 | C1 | 0 |
+ And the following "activities" exist:
+ | activity | name | intro | course | idnumber |
+ | studentquiz | StudentQuiz Test | StudentQuiz description | C1 | studentquiz1 |
+ And the following "questions" exist:
+ | questioncategory | qtype | name |
+ | Default for StudentQuiz Test | truefalse | Question 1 |
+ | Default for StudentQuiz Test | truefalse | Question 2 |
+ | Default for StudentQuiz Test | truefalse | Question 3 |
+
+ @javascript
+ Scenario: New availability settings should exist
+ Given I log in as "admin"
+ And I am on "Course 1" course homepage
+ And I turn editing mode on
+ And I add a "StudentQuiz" to section "1"
+ When I expand all fieldsets
+ Then I should see "Open for question submission from"
+ And I should see "Closed for question submission from"
+ And I should see "Open for answering from"
+ And I should see "Close for answering from"
+
+ @javascript
+ Scenario: Availability settings validation
+ Given I log in as "admin"
+ And I am on "Course 1" course homepage
+ And I turn editing mode on
+ And I add a "StudentQuiz" to section "1"
+ And I expand all fieldsets
+ And I set the field "id_name" to "StudentQuiz Test Availability"
+
+ # Submissions deadline can not be specified before the open for submissions date
+ And I set the field "id_opensubmissionfrom_enabled" to "1"
+ And I set the field "id_closesubmissionfrom_enabled" to "1"
+ And I set the availability field "closesubmissionfrom" to "-1" days from now
+ When I press "Save and display"
+ Then I should see "Submissions deadline can not be specified before the open for submissions date"
+
+ # Answering deadline can not be specified before the open for answering date
+ And I set the field "id_opensubmissionfrom_enabled" to "0"
+ And I set the field "id_closesubmissionfrom_enabled" to "0"
+ And I set the field "id_openansweringfrom_enabled" to "1"
+ And I set the field "id_closeansweringfrom_enabled" to "1"
+ And I set the availability field "closeansweringfrom" to "-1" days from now
+ When I press "Save and display"
+ Then I should see "Answering deadline can not be specified before the open for answering date"
+
+ @javascript
+ Scenario: Availability settings for question submission
+ Given I log in as "admin"
+ And I am on "Course 1" course homepage
+ When I follow "StudentQuiz Test"
+ Then the "Create new question" "button" should be enabled
+
+ # Enable only for Open for question submission (Future)
+ And I navigate to "Edit settings" in current page administration
+ And I expand all fieldsets
+ And I set the field "id_opensubmissionfrom_enabled" to "1"
+ And I set the availability field "opensubmissionfrom" to "+5" days from now
+ When I press "Save and display"
+ Then the "Create new question" "button" should be disabled
+ And I should see "Open for question submission from"
+
+ # Enable only for Open for question submission (Past)
+ And I navigate to "Edit settings" in current page administration
+ And I expand all fieldsets
+ And I set the availability field "opensubmissionfrom" to "-5" days from now
+ When I press "Save and display"
+ Then the "Create new question" "button" should be enabled
+ And I should not see "Open for question submission from"
+
+ # Enable only for Close for question submission (Past)
+ And I navigate to "Edit settings" in current page administration
+ And I expand all fieldsets
+ And I set the field "id_opensubmissionfrom_enabled" to "0"
+ And I set the field "id_closesubmissionfrom_enabled" to "1"
+ And I set the availability field "closesubmissionfrom" to "-5" days from now
+ When I press "Save and display"
+ Then the "Create new question" "button" should be disabled
+ And I should see "This StudentQuiz closed for question submission on"
+
+ # Enable only for Close for question submission (Future)
+ And I navigate to "Edit settings" in current page administration
+ And I expand all fieldsets
+ And I set the availability field "closesubmissionfrom" to "+5" days from now
+ When I press "Save and display"
+ Then the "Create new question" "button" should be enabled
+ And I should see "This StudentQuiz closes for question submission on"
+
+ # Enable both Open and Close for question submission (Open in the Past)
+ And I navigate to "Edit settings" in current page administration
+ And I expand all fieldsets
+ And I set the field "id_opensubmissionfrom_enabled" to "1"
+ And I set the field "id_closesubmissionfrom_enabled" to "1"
+ And I set the availability field "opensubmissionfrom" to "-5" days from now
+ And I set the availability field "closesubmissionfrom" to "+5" days from now
+ When I press "Save and display"
+ Then the "Create new question" "button" should be enabled
+ And I should see "This StudentQuiz closes for question submission on"
+
+ # Enable both Open and Close for question submission (Open in the Future)
+ And I navigate to "Edit settings" in current page administration
+ And I expand all fieldsets
+ And I set the field "id_opensubmissionfrom_enabled" to "1"
+ And I set the field "id_closesubmissionfrom_enabled" to "1"
+ And I set the availability field "opensubmissionfrom" to "+5" days from now
+ And I set the availability field "closesubmissionfrom" to "+10" days from now
+ When I press "Save and display"
+ Then the "Create new question" "button" should be disabled
+ And I should see "Open for question submission from"
+
+ @javascript
+ Scenario: Availability settings for question answering
+ Given I log in as "admin"
+ And I am on "Course 1" course homepage
+ When I follow "StudentQuiz Test"
+ Then the "Start Quiz" "button" should be enabled
+
+ # Enable only for Open for question answering (Future)
+ And I navigate to "Edit settings" in current page administration
+ And I expand all fieldsets
+ And I set the field "id_openansweringfrom_enabled" to "1"
+ And I set the availability field "openansweringfrom" to "+5" days from now
+ When I press "Save and display"
+ Then the "Start Quiz" "button" should be disabled
+ And I should see "Open for answering from"
+
+ # Enable only for Open for question answering (Past)
+ And I navigate to "Edit settings" in current page administration
+ And I expand all fieldsets
+ And I set the availability field "openansweringfrom" to "-5" days from now
+ When I press "Save and display"
+ Then the "Start Quiz" "button" should be enabled
+ And I should not see "Open for answering from"
+
+ # Enable only for Close for question answering (Past)
+ And I navigate to "Edit settings" in current page administration
+ And I expand all fieldsets
+ And I set the field "id_openansweringfrom_enabled" to "0"
+ And I set the field "id_closeansweringfrom_enabled" to "1"
+ And I set the availability field "closeansweringfrom" to "-5" days from now
+ When I press "Save and display"
+ Then the "Start Quiz" "button" should be disabled
+ And I should see "This StudentQuiz closed for answering on"
+
+ # Enable only for Close for question answering (Future)
+ And I navigate to "Edit settings" in current page administration
+ And I expand all fieldsets
+ And I set the availability field "closeansweringfrom" to "+5" days from now
+ When I press "Save and display"
+ Then the "Start Quiz" "button" should be enabled
+ And I should see "This StudentQuiz closes for answering on"
+
+ # Enable both Open and Close for question answering (Open in the Past)
+ And I navigate to "Edit settings" in current page administration
+ And I expand all fieldsets
+ And I set the field "id_openansweringfrom_enabled" to "1"
+ And I set the field "id_closeansweringfrom_enabled" to "1"
+ And I set the availability field "openansweringfrom" to "-5" days from now
+ And I set the availability field "closeansweringfrom" to "+5" days from now
+ When I press "Save and display"
+ Then the "Start Quiz" "button" should be enabled
+ And I should see "This StudentQuiz closes for answering on"
+
+ # Enable both Open and Close for question answering (Open in the Future)
+ And I navigate to "Edit settings" in current page administration
+ And I expand all fieldsets
+ And I set the field "id_openansweringfrom_enabled" to "1"
+ And I set the field "id_closeansweringfrom_enabled" to "1"
+ And I set the availability field "openansweringfrom" to "+5" days from now
+ And I set the availability field "closeansweringfrom" to "+10" days from now
+ When I press "Save and display"
+ Then the "Start Quiz" "button" should be disabled
+ And I should see "Open for answering from"
diff --git a/version.php b/version.php
index a952f442..1c314b10 100644
--- a/version.php
+++ b/version.php
@@ -28,7 +28,7 @@
defined('MOODLE_INTERNAL') || die();
$plugin->component = 'mod_studentquiz';
-$plugin->version = 2018121800;
+$plugin->version = 2018122500;
$plugin->release = 'v3.2.1';
$plugin->requires = 2017111306; // Version MOODLE_31, 3.1.0.
$plugin->maturity = MATURITY_STABLE;