### Eclipse Workspace Patch 1.0
#P quiz-head
Index: quiz.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/quiz/quiz.module,v
retrieving revision 1.103
diff -u -r1.103 quiz.module
--- quiz.module	12 Sep 2007 18:09:04 -0000	1.103
+++ quiz.module	14 Sep 2007 16:21:55 -0000
@@ -1,8 +1,9 @@
 <?php
-/* $Id: quiz.module,v 1.103 2007/09/12 18:09:04 kscheirer Exp $ */
-
-include(drupal_get_path('module', 'quiz') .'/quiz_datetime.inc');
+/* $Id: quiz.module,v 1.102 2007/09/05 22:15:53 kscheirer Exp $ */
 
+if (function_exists('drupal_get_path')) {
+  include(drupal_get_path('module', 'quiz') .'/quiz_datetime.inc');
+}
 /**
  * @file
  * Quiz Module
@@ -30,6 +31,20 @@
 define('QUIZ_FEEDBACK_NEVER',           2);
 
 /**
+  * Implementation of hook_init().
+  */
+function quiz_init() {
+   // ensure we are not serving a cached page
+   if (function_exists('drupal_set_content')) {
+     // we don't do this in hook_menu to ensure the files are already included when
+     // views_menu is executed
+     if (module_exists('views')) {
+       include_once('./'. drupal_get_path('module', 'quiz') .'/quiz_views.inc');
+     }
+   }
+}
+
+/**
  * get an array of feedback options
  * @return array of feedback options
  */
Index: quiz_views.inc
===================================================================
RCS file: quiz_views.inc
diff -N quiz_views.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ quiz_views.inc	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,414 @@
+<?php
+// $Id: views_quiz.inc,v 1.1 2007/08/13 00:47:38 westwesterson Exp $
+
+/**
+ * This include file implements views functionality on behalf of quiz.module
+ */
+
+function quiz_views_tables() {
+    $tables['quiz_user'] = array(
+      'name' => 'users',
+      'provider' => 'internal', // won't show up in external list.
+      // attach quiz user to results
+      'join' => array(
+        'left' => array(
+           'table' => 'quiz_node_results',
+           'field' => 'uid',
+         ),
+         'right' => array(
+           'field' => 'uid',
+         ),
+      ),
+      'fields' => array(
+        'name' => array(
+          'name' => t('Quiz Result: Quiz Taker'),
+          'sortable' => TRUE,
+          //'option' => 'string',
+          'handler' => array(
+            'quiz_views_handler_field_username_text' => t('normal text'),
+            'quiz_views_handler_field_username_link' => t('themed userlink'),
+          ),
+          'uid' => 'uid',
+          'addlfields' => array('uid'),
+          'help' => t('Displays the user who created this quiz result.'),
+        ),
+      ),
+      'sort' => array(
+        'name' => array(
+          'name' => t('Quiz Result: Quiz Taker'),
+          'help' => t('Sort by the user who created the quiz result.'),
+        ),
+      ),
+      'filter' => array(
+        'name' => array(
+          'name' => t('Quiz Result: Quiz Taker'),
+          'operator' => 'views_handler_operator_or',
+          'list' => 'views_handler_filter_username',
+          'value-type' => 'array',
+          'help' => t('This allows you to filter quiz results by a particular user. You might not find this useful if you have a lot of users.'),
+        ),
+      ),
+    );
+  $tables['quiz_node_results'] = array(
+    'name' => 'quiz_node_results',
+    'provider' => 'internal', // won't show up in external list.
+    // attach quiz results to node
+    'join' => array(
+      'left' => array(
+        'table' => 'node',
+        'field' => 'nid',
+       ),
+      'right' => array(
+        'field' => 'nid',
+      ),
+    ),
+    'fields' => array(
+      'result_id' => array(
+        'name' => t('Quiz Result: Result ID'),
+        'sortable' => TRUE,
+        'help' => t('Display the Result ID of the Quiz Result. Optionally you can show as a link, the result id with a link, or without a link'),
+        'handler' => 'quiz_views_handler_field_result_id',
+        'option' => array(
+          '#type' => 'select',
+          '#options' => array(
+            'link' => 'As link',
+            'nolink' => 'Without link',
+            'onlylink' => 'As only a link'
+          ),
+        ),
+      ),
+      'time_start' => array(
+        'name' => t('Quiz Result: Start Time'),
+        'sortable' => TRUE,
+        'handler' => views_handler_field_dates(),
+        'help' => t('Display the start time of a quiz result.'),
+      ),
+      'time_end' => array(
+        'name' => t('Quiz Result: End Time'),
+        'sortable' => TRUE,
+        'handler' => views_handler_field_dates(),
+        'help' => t('Display the end time of a quiz result.'),
+      ),
+      'score' => array(
+        'name' => t('Quiz Result: Score'),
+        'sortable' => TRUE,
+        'handler' => 'quiz_views_handler_field_score',
+        'addlfields' => array('result_id'),
+        'option' => array(
+          '#type' => 'select',
+          '#options' => array(
+            'link' => 'As number with link',
+            'nolink' => 'Without link'
+          ),
+        ),
+        'help' => t('Display the final score of a quiz result.'),
+      ),
+      'avg_score' => array(
+        'name' => t('Quiz Result: AVG Score'),
+        'sortable' => TRUE,
+        'help' => t('A Users average score across all quizzes they have taken'),
+        'notafield' => TRUE,
+        'handler' => 'quiz_views_handler_field_avg_score',
+        'query_handler' => 'quiz_views_handler_query_avg_score',
+        //'validate' => 'quiz_views_handler_avg_score_validate',
+      ),
+    ),
+    'sorts' => array(
+      'score' => array(
+        'name' => t('Quiz Result: Score'),
+        'help' => t('This allows you to sort by the percentage needed to pass the quiz.'),
+      ),
+      'time_start' => array(
+        'name' => t('Quiz Result: Start Time'),
+        'handler' => 'views_handler_sort_date',
+        'option' => views_handler_sort_date_options(),
+        'help' => t('This allows you to sort by the start time of the quiz result.'),
+      ),
+      'time_end' => array(
+        'name' => t('Quiz Result: End Time'),
+        'handler' => 'views_handler_sort_date',
+        'option' => views_handler_sort_date_options(),
+        'help' => t('This allows you to sort by the end time of the quiz result.'),
+      ),
+      'avg_score' => array(
+        'name' => t('Quiz Result: AVG Score'),
+        'help' => t('Sort by overall score (the average across all completed quizzes by a user)'),
+        'handler' => 'quiz_views_handler_sort_avg_score',
+      ),
+    ),
+    'filters' => array(
+      'score' => array(
+        'name' => t('Quiz Result: Score'),
+        'operator' => 'views_handler_operator_gtlt',
+        'option' => 'integer',
+        'help' => t('This allows you to filter by the quiz result score.'),
+      ),
+      'time_start' => array(
+        'name' => t('Quiz Result: Start Time'),
+        'operator' => 'views_handler_operator_gtlt',
+	    'value' => views_handler_filter_date_value_form(),
+	    'handler' => 'views_handler_filter_timestamp',
+        'option' => 'string',
+        'help' => t('This allows you to sort by the start time of the quiz result.'),
+      ),
+      'time_end' => array(
+        'name' => t('Quiz Result: End Time'),
+        'operator' => 'views_handler_operator_gtlt',
+	    'value' => views_handler_filter_date_value_form(),
+	    'handler' => 'views_handler_filter_timestamp',
+        'option' => 'string',
+        'help' => t('This allows you to sort by the end time of the quiz result.'),
+      ),
+    ),
+  );
+  $tables['quiz_node_properties'] = array(
+    'name' => 'quiz_node_properties',
+    'provider' => 'internal', // won't show up in external list.
+    // attach quiz table to node
+    'join' => array(
+      'left' => array(
+        'table' => 'node',
+        'field' => 'nid',
+      ),
+      'right' => array(
+        'field' => 'nid',
+      ),
+    ),
+    'fields' => array(
+      'pass_rate' => array(
+        'name' => t('Quiz: Passing Percentage Rate'),
+        'sortable' => TRUE,
+        'handler' => 'quiz_views_handler_percentage',
+        'help' => t('Display the percentage needed to pass the quiz.'),
+      ),
+      'takes' => array(
+        'name' => t('Quiz: Number of Takes Allowed'),
+        'sortable' => TRUE,
+        'handler' => 'views_handler_field_takes',
+        'help' => t('Display the number of takes allowed on a quiz.'),
+      ),
+      /*
+       * The database has replaced this field with the number of random questions
+       * 
+       * TODO add to database total number of questions per quiz, 
+       * otherwise it takes too many queries if there are a lot of quizzes on a page 
+       * and is a performance issue.
+       */
+      /*'number_of_questions' => array(
+        'name' => t('Quiz: Number of Questions'),
+        'sortable' => TRUE,
+        'handler' => 'views_handler_field_int',
+        'option' => 'string',
+        'help' => t('Display the number of quiz questions.'),
+      ),*/
+      'quiz_open' => array(
+        'name' => t('Quiz: Start Time'),
+        'sortable' => TRUE,
+        'handler' => views_handler_field_dates(),
+        'help' => t('Display the start date of a quiz.'),
+      ),
+      'quiz_closed' => array(
+        'name' => t('Quiz: End Time'),
+        'sortable' => TRUE,
+        'handler' => views_handler_field_dates(),
+        'help' => t('Display the end date of a quiz.'),
+      ),
+      'quiz_always' => array(
+        'name' => t('Quiz: Always Available'),
+        'sortable' => TRUE,
+        'handler' => views_handler_yes_no,
+        'help' => t('Display the end date of a quiz.'),
+      ),      
+    ),
+    'sorts' => array(
+      'pass_rate' => array(
+        'name' => t('Quiz: Passing Rate'),
+        'help' => t('This allows you to sort by the percentage needed to pass the quiz.'),
+      ),
+      'takes' => array(
+        'name' => t('Quiz: Number of Takes Allowed'),
+        'help' => t('This allows you to sort by the number of takes allowed of the quiz.'),
+      ),
+      // changed to number of random questions
+      /*'number_of_questions' => array(
+        'name' => t('Quiz: Number of Questions'),
+        'help' => t('This allows you to sort by the number of questions in the quiz.'),
+      ),*/
+      'quiz_open' => array(
+        'name' => t('Quiz: Start Time'),
+        'handler' => 'views_handler_sort_date',
+        'option' => views_handler_sort_date_options(),
+        'help' => t('This allows you to sort by the Start Date of the quiz.'),
+      ),
+      'quiz_closed' => array(
+        'name' => t('Quiz: End Time'),
+        'handler' => 'views_handler_sort_date',
+        'option' => views_handler_sort_date_options(),
+        'help' => t('This allows you to sort by the end date of the quiz.'),
+      ),
+    ),
+    'filters' => array(
+      'pass_rate' => array(
+        'name' => t('Quiz: Passing Rate'),
+        'operator' => 'views_handler_operator_gtlt',
+        'option' => 'integer',
+        'help' => t('This allows you to filter by the percentage needed to pass the quiz.'),
+      ),
+      // changed to number of random questions
+      /*'number_of_questions' => array(
+        'name' => t('Quiz: Number of Questions'),
+        'operator' => 'views_handler_operator_gtlt',
+        'option' => 'integer',
+        'help' => t('This allows you to filter by the number of questions in the quiz.'),
+      ),*/
+      'takes' => array(
+        'name' => t('Quiz: Number of Takes Allowed'),
+        'operator' => 'views_handler_operator_gtlt',
+        'option' => 'integer',
+        'help' => t('This allows you to filter by the number of takes allowed of the quiz. Enter 0 for unlimited'),
+      ),
+      'quiz_open' => array(
+        'name' => t('Quiz: Start Time'),
+        'operator' => 'views_handler_operator_gtlt',
+	    'value' => views_handler_filter_date_value_form(),
+	    'handler' => 'views_handler_filter_timestamp',
+        'option' => 'string',
+        'help' => t('This allows you to sort by the Start Date of the quiz.'),
+      ),
+      'quiz_closed' => array(
+        'name' => t('Quiz: End Time'),
+        'operator' => 'views_handler_operator_yesno()',
+	    'value' => views_handler_filter_date_value_form(),
+	    'handler' => 'views_handler_filter_timestamp',
+        'option' => 'string',
+        'help' => t('This allows you to sort by the end date of the quiz.'),
+      ),
+      'quiz_always' => array(
+        'name' => t('Quiz: Always Available'),
+        'operator' => 'views_handler_operator_yesno',
+	    'value' => integer,
+	    'handler' => 'views_handler_yes_no',
+        'option' => 'string',
+        'help' => t('This allows you to sort by the end date of the quiz.'),
+      ),
+    ),
+  );
+  return $tables;
+}
+
+/**
+ * Callback for quiz_views_tables(): user name as plaintext.
+ */
+function quiz_views_handler_field_username_text($fieldinfo, $fielddata, $value, $data) {
+  return check_plain($value);
+}
+
+/**
+ * Callback for quiz_views_tables(): user name as a link to the usernode.
+ */
+function quiz_views_handler_field_username_link($fieldinfo, $fielddata, $value, $data) {
+  if ($value) {
+    $obj->name = $value;
+    $uidfield = $fielddata['tablename'] ."_". $fieldinfo['uid'];
+    $obj->uid = $data->$uidfield;
+    return theme('username', $obj);
+  }
+}
+
+/**
+ * Generic handler given a 1 & 0 will output as a yes for 1 and no for 0.
+ */
+function views_handler_yes_no($fieldinfo, $fielddata, $value, $data) {
+  if ($value == '0') {
+    $value = "No";
+  } else $value = "Yes";
+  return $value;
+}
+
+/**
+ * Generic handler given a string will add a percentage sign to the end
+ */
+function quiz_views_handler_percentage($fieldinfo, $fielddata, $value, $data) {
+  return $value .'%';
+}
+/**
+ * Handler for result_id field allowing it to optionally show 
+ * as the result_id with a link, the result_id with no link or
+ * just a link to the result.
+ *
+ * Ideally, there should be some way to theme the word Results
+ */
+function quiz_views_handler_field_result_id($fieldinfo, $fielddata, $value, $data) {
+  if ($fielddata['options'] == 'nolink') {
+    return check_plain($value);
+  }
+  if ($fielddata['options'] == 'onlylink') {
+    return l("Results", "user/quiz/$value/userresults");
+  }
+  return l($value, "user/quiz/$value/userresults");
+}
+
+/*
+ * Handler turning a score into a link to the quiz result
+ * TODO this should link to the userresults page, but result_id wont follow
+ * so for now, there is no link option.
+ */
+function quiz_views_handler_field_score($fieldinfo, $fielddata, $value, $data) {
+  $value .= '%';
+//  if ($fielddata['options'] == 'nolink') {
+    return check_plain($value);
+//  }
+//  return l($value, "user/quiz/$data->result_id/userresults");
+}
+
+/**
+ * Generic handler outputs a number except for 0 which outputs unlimited.
+ */
+function views_handler_field_takes($fieldinfo, $fielddata, $value, $data) {
+  if ($value == 0) $value = 'Unlimited';
+  return $value;
+}
+/*
+ * Argument Implementation not yet ready for primetime (need to do serious coding)
+*/
+function quiz_views_arguments() {
+  $arguments = array(
+     // number of questions no longer exists in the database.
+     /*'number_of_questions' => array(
+       'name' => t('Quiz: Number of Questions'),
+       'handler' => 'views_handler_arg_noq',
+       'help' => t('The Number of Questions Arguement allows you to filter to nodes by the number of questions in the quiz.'),
+     ),*/
+  );
+}
+
+/*function views_handler_arg_noq() {
+  switch($op) {
+    case 'summary':
+    case 'sort':
+    case 'filter':
+    case 'link':
+    case 'title':
+  }
+}*/
+
+function quiz_views_default_views() {
+
+}
+
+function quiz_views_handler_query_avg_score($field, $fieldinfo, &$query) {
+  $query->add_field("AVG(score)", null, "avg_score");
+  $query->add_groupby("quiz_node_results.uid");
+  $query->add_where("score IS NOT NULL");
+  $query->add_where("time_end > 0");
+}
+
+function quiz_views_handler_field_avg_score($fieldinfo, $fielddata, $value, $data) {
+  return number_format($data->avg_score, 2) .'%';
+}
+
+function quiz_views_handler_sort_avg_score($op, &$query, $sortinfo, $sortdata) {
+  $query->add_orderby(NULL, "AVG(score)", $sortdata['sortorder'], 'avg_score');
+}
+
+?>
