It's easy to filter Quizzes by "Finished" or "In progress" because we can deduce the state from the time_end column in the quiz_node_results table.

Filtering by "Not started" is harder - I couldn't figure out how to view all quizzes which a particular user has not started. There is a filter for this - "Quiz Results: Quiz State" which can be set to "Not started" (and #603300: "Quiz Results: Quiz State" filter must be exposed to work correctly) - but it only returns some quizzes which the user hasn't started - not all of them.

This is because includes/views/handlers/quiz_views_handler_filter_user_quiz_state.inc filters the database results this by adding
$this->query->add_where(0, "$this->table_alias.time_end IS NULL");
which works out to look like
WHERE (quiz_node_results.time_end IS NULL)

This means that only Quizzes which have an entry in the quiz_node_results table where time_end is NULL will show up in our view where we want to return all quizzes which are "Not started" by a user.

Does the current implementation of Quiz provide a way to view all quizzes not started by a user?

If not, then we'd have to go about it in a different way. I'm not sure Views is equipped to handle this sort of query, because we'd essentially have to ask it:

  1. Fetch all quizzes
  2. Fetch all quizzes for a particular user which have state "In progress" or "Finished".
  3. Subtract the result set of (2) from the result set of (1).

I've implemented this kind of logic before for a separate application; I created 2 views and then subtracted the second view from the first.

Am I complicating the solution, or is this exactly the sort of thing which is needed?

CommentFileSizeAuthor
#8 quiz-subquery-604106-8.patch1 KBrho_

Comments

burningdog’s picture

Turns out I was indeed complicating it - a single sql query (with a subquery) works fine. There should still be a view for this, but hopefully someone else finds this useful to return all quizzes which a user hasn't Finished (i.e. it will also return Quizzes which are "In progress"):

$sql = 'SELECT nid FROM quiz_node_properties
WHERE nid NOT IN (

SELECT nid FROM quiz_node_results
WHERE uid = %d
AND time_end >0
)';
$result = db_query($sql, $user->uid);
sdboyer’s picture

Assigned: Unassigned » sdboyer

Yeah, I went through hell coming up with that, and a lot of the other, filters.

Interesting approach you suggest. I'll try to see if I can't implement an additional filter, or change the existing one, along those lines. Subqueries can be quite complex to implement in Views, but not impossible, IIRC (it has been several months since I wrote the original Views integration).

burningdog’s picture

Oh wow, I didn't know Views did subqueries - that's awesome! Good luck in implementing it - if I knew anything about implementing views filters, I'd jump in and help you.

Luckily I can get away with my solution as a query and not as a view, as my use case is to present the user with the next quiz which they've not completed.

falcon’s picture

Status: Active » Needs work
falcon’s picture

Version: 6.x-4.0-alpha2 » 6.x-4.x-dev
falcon’s picture

Version: 6.x-4.x-dev » 6.x-5.x-dev
Status: Needs work » Postponed

I'm cleaning up the issue list for quiz 4.x-dev. Please change the status if anyone starts working on this one...

zeezhao’s picture

+1.

@sdboyer - please did you implement this? Interested in a report or view that shows all users that have not started a quiz, in addition to those that have not finished. This should be linked to sending email reminders eventually. Thanks.

rho_’s picture

Version: 6.x-5.x-dev » 6.x-4.x-dev
Status: Postponed » Needs work
StatusFileSize
new1 KB

Ran into this one today. The subquery that Roger posted in #1 works well, but I wanted this within the view so I added it to the quiz_state filter views handler. I've never had to implement a subquery with an add_where so I probably mangled this badly, but thought I would throw what I have going up here to maybe get some movement on this issue. At very least possibly learn how to implement something like this correctly.

The thing that really stood out to me, and kind of made me shudder to implement was how to grab the uid to check against in the subquery (see snippet). It is available in view->args if it is included in the view arguments. I assume it should be if constructing a view like this but I really don't see how else to grab it. Likely there is a different approach to subqueries in views all together, but I am not aware of one.

<?php
$this->query->add_where(0, "$this->table_alias.nid NOT IN (SELECT qnr.nid FROM quiz_node_results AS qnr WHERE uid = ".$this->view->args[0]." AND time_end > 0)");
?>

Attached is a patch that implements this, and works well for me. Just be sure that the uid to check against is the first views arg, otherwise it will default back to the original behavior.

djdevin’s picture

Status: Needs work » Closed (outdated)

This issue is being closed because it was filed against a version that is no longer supported. If the issue still persists in the latest version of Quiz, please open a new issue.