MDL-51569 mod_choice: Check choice availability prior to do any action
authorJuan Leyva <juanleyvadelgado@gmail.com>
Sat, 24 Oct 2015 15:03:35 +0000 (17:03 +0200)
committerDan Poltawski <dan@moodle.com>
Wed, 4 Nov 2015 11:08:32 +0000 (11:08 +0000)
mod/choice/lib.php
mod/choice/tests/lib_test.php
mod/choice/view.php

index 43c3db6..7a62bc3 100644 (file)
@@ -1007,3 +1007,29 @@ function choice_view($choice, $course, $cm, $context) {
     $completion = new completion_info($course);
     $completion->set_module_viewed($cm);
 }
+
+/**
+ * Check if a choice is available for the current user.
+ *
+ * @param  stdClass  $choice            choice record
+ * @return array                       status (available or not and possible warnings)
+ */
+function choice_get_availability_status($choice) {
+    $available = true;
+    $warnings = array();
+
+    if ($choice->timeclose != 0) {
+        $timenow = time();
+
+        if ($choice->timeopen > $timenow) {
+            $available = false;
+            $warnings['notopenyet'] = userdate($choice->timeopen);
+        } else if ($timenow > $choice->timeclose) {
+            $available = false;
+            $warnings['expired'] = userdate($choice->timeclose);
+        }
+    }
+
+    // Choice is available.
+    return array($available, $warnings);
+}
index 0f58117..341886e 100644 (file)
@@ -172,4 +172,46 @@ class mod_choice_lib_testcase extends externallib_advanced_testcase {
         }
     }
 
+    /**
+     * Test choice_get_availability_status
+     * @return void
+     */
+    public function choice_get_availability_status() {
+        $this->resetAfterTest();
+
+        $this->setAdminUser();
+        // Setup test data.
+        $course = $this->getDataGenerator()->create_course();
+        $choice = $this->getDataGenerator()->create_module('choice', array('course' => $course->id));
+
+        // No time restrictions.
+        list($status, $warnings) = choice_get_availability_status($choice, false);
+        $this->assertEquals(true, $status);
+        $this->assertCount(0, $warnings);
+
+        // With time restrictions, still open.
+        $choice->timeopen = time() - DAYSECS;
+        $choice->timeclose = time() + DAYSECS;
+        list($status, $warnings) = choice_get_availability_status($choice, false);
+        $this->assertEquals(true, $status);
+        $this->assertCount(0, $warnings);
+
+        // Choice not open yet.
+        $choice->timeopen = time() + DAYSECS;
+        $choice->timeclose = $choice->timeopen + DAYSECS;
+        list($status, $warnings) = choice_get_availability_status($choice, false);
+        $this->assertEquals(false, $status);
+        $this->assertCount(1, $warnings);
+        $this->assertEquals('notopenyet', $warnings[0]);
+
+        // Choice closed.
+        $choice->timeopen = time() - DAYSECS;
+        $choice->timeclose = time() - 1;
+        list($status, $warnings) = choice_get_availability_status($choice, false);
+        $this->assertEquals(false, $status);
+        $this->assertCount(1, $warnings);
+        $this->assertEquals('expired', $warnings[0]);
+
+    }
+
 }
index d40beba..98d4840 100644 (file)
@@ -34,7 +34,10 @@ $strchoices = get_string('modulenameplural', 'choice');
 
 $context = context_module::instance($cm->id);
 
-if ($action == 'delchoice' and confirm_sesskey() and is_enrolled($context, NULL, 'mod/choice:choose') and $choice->allowupdate) {
+list($choiceavailable, $warnings) = choice_get_availability_status($choice);
+
+if ($action == 'delchoice' and confirm_sesskey() and is_enrolled($context, NULL, 'mod/choice:choose') and $choice->allowupdate
+        and $choiceavailable) {
     $answercount = $DB->count_records('choice_answers', array('choiceid' => $choice->id, 'userid' => $USER->id));
     if ($answercount > 0) {
         $DB->delete_records('choice_answers', array('choiceid' => $choice->id, 'userid' => $USER->id));
@@ -67,6 +70,11 @@ if (data_submitted() && is_enrolled($context, NULL, 'mod/choice:choose') && conf
         $answer = optional_param('answer', '', PARAM_INT);
     }
 
+    if (!$choiceavailable) {
+        $reason = current(array_keys($warnings));
+        throw new moodle_exception($reason, 'choice', '', $warnings[$reason]);
+    }
+
     if ($answer) {
         choice_user_submit_response($answer, $choice, $USER->id, $course, $cm);
         redirect(new moodle_url('/mod/choice/view.php',