Just noticed the quiz_availability function isn't looking at the number of times the current user has taken that quiz - before it renders the button. As a result, the take button shows up in Views and elsewhere without actually being available for users as they have already taken that quiz.

I've taken the code out of quiz_start_check() and customized it a bit for the quiz_availability function to get it working.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

sokrplare’s picture

Status: Active » Needs review
FileSize
2.58 KB

Realized I need to check if the time_end is still zero or not, otherwise I get access denied every time.
Also noticed the $query variable was never used :)
Here is the patch with the changes made.

michaelk’s picture

The current patch is fundamentally broken. It incorrectly blocks uses from taking a quiz when they have 1 attempt remaining.

michaelk’s picture

I was using the incorrect patch file. The patch in http://drupal.org/node/1937226#comment-7175824 works well.

Sivaji_Ganesh_Jojodae’s picture

Status: Needs review » Needs work

I reviewed your patch. Thanks for sharing it.

+  if ($quiz->takes > 0) {
+    $taken = db_query("SELECT COUNT(*) AS takes FROM {quiz_node_results} WHERE time_end > 0 AND uid = :uid AND nid = :nid", array(':uid' => $user->uid, ':nid' => $quiz->nid))->fetchField();
+    $allowed_times = format_plural($quiz->takes, '1 time', '@count times');
+    $taken_times   = format_plural($taken, '1 time', '@count times');
 
+    // The user has already taken this quiz.
+    if ($taken) {
+      if ($user_is_admin) {
+        return t('You have taken this quiz already. You are marked as an owner or administrator for this quiz, so you can take this quiz as many times as you would like.');
+      }
+      // If the user has already taken this quiz too many times, stop the user.
+      elseif ($taken >= $quiz->takes) {
+        return t('You have already taken this quiz @really. You may not take it again.', array('@really' => $taken_times));
+      }
+    }

Actually these set of lines are already there in quiz_start_check(), not sure if redundant check and redundant lines are needed. Perhaps those lines need to be removed from quiz_start_check() and should be retained in quiz_availability(). Because in quiz_take_quiz(), call to quiz_availability() is made a few lines after quiz_start_check(). I would need some more time to test this. In the meantime would like to hear early feedback.

michaelk’s picture

I did notice one small issue with the patch from https://drupal.org/node/1937226#comment-7175824

$user_is_admin is not defined until after it is checked in the new patched code, and the admin case is denying access instead of displaying the message and giving access when the admin has taken the quiz.

I have attached a patch that addresses these issues.

bohemier’s picture

This patch needs to be redone against current dev version. But essentially, it works fine.

We should consider committing it as the current version is broken for quizzes that cannot be taken anymore - It shows the Take button as well as the Take menu when it should not.

thanks!

bohemier’s picture

It also fixes this issue since the take quiz links are correctly hidden when not available: https://drupal.org/node/2152295

czigor’s picture

Issue summary: View changes
Status: Needs work » Needs review
FileSize
351 bytes

Here's my go at the problem.

The uncommented line was commented out in 693a36cd59401c0745fe0c9de8571c406a3af28b the commit message of which says:"Fixed php notices in take page when no questions added to quiz." Removing the comment slashes did not induce any php notices for a quiz without questions so I guess it should be OK.

czigor’s picture

The patch also solves #2152295: Undefined index :quiz_26.

czigor’s picture

Status: Needs review » Needs work

Patch is not good. If the line is not commented out, one cannot take quizzes with unlimited number of views.

czigor’s picture

Status: Needs work » Needs review
FileSize
1.72 KB

Digging deeper into the logic of the beginning of quiz_take_quiz(). Although there are two points I don't really understand I came up with a patch.
These points are:

  1. _quiz_take_quiz_init() sets {quiz_node_result}.time_end to 0 by calling quiz_create_rid(). Why is _quiz_delete_old_in_progress() removing entries with for {quiz_node_result}.time_end == 1 then? (_quiz_active_result_id() is also checking for time_end == 0.)
  2. I have no idea what the quiz_start_check($quiz, $rid) && (_quiz_take_quiz_init($quiz) === FALSE) condition was meant to do.
djdevin’s picture

@czigor, are you still using your patch? There's no automated tests on 4.x so if you can verify it works, I'll add it to 4.x and mark it as a todo for 5.x.

czigor’s picture

Yes, I am using the patch.

falcon’s picture

Status: Needs review » Needs work

Seems we need a patch here that merges all the patches and makes sure that it doesn't produce redundant code.

yce’s picture

Hi! I've recreated the patch for the latest dev version.

djdevin’s picture