]> git.mjollnir.org Git - moodle.git/commitdiff
question bank: MDL-17302 refactor question bank display code into a class.
authortjhunt <tjhunt>
Mon, 19 Jan 2009 05:30:01 +0000 (05:30 +0000)
committertjhunt <tjhunt>
Mon, 19 Jan 2009 05:30:01 +0000 (05:30 +0000)
Step 1. Just convert the existing functions quiz_question_showbank and question_showbank and friends into methods of a class and subclass.

More to come.

mod/quiz/edit.php
mod/quiz/editlib.php
question/edit.php
question/editlib.php

index 3a87d7000c74ca7c50d3297de0cb28ba8b5d10d2..5421b827c212e3e5731a943f2abd829d65a49f1e 100644 (file)
@@ -1,4 +1,28 @@
 <?php // $Id$
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.org                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards Martin Dougiamas and others                //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
 /**
  * Page to edit quizzes
  *
  * delete       Removes a question from the quiz
  * savechanges  Saves the order and grades for questions in the quiz
  *
- * @author Martin Dougiamas and many others. This has recently been extensively
- *         rewritten by Gustav Delius and other members of the Serving Mathematics project
- *         {@link http://maths.york.ac.uk/serving_maths}. The UI and some functionality
- *         was rewritten as a part of the Quiz UI Redesign project in Summer 2008
- *         {@link http://docs.moodle.org/en/Development:Quiz_UI_redesign}.
  * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
  * @package quiz
- */
+ *//** */
+
 require_once("../../config.php");
 require_once($CFG->dirroot.'/mod/quiz/editlib.php');
 require_once($CFG->dirroot."/question/category_class.php");
@@ -134,6 +154,7 @@ if ($quiz_qbanktool > -1) {
 } else {
     $quiz_qbanktool = get_user_preferences("quiz_qbanktool_open",0);
 }
+$questionbank = new quiz_question_bank_view();
 
 //will be set further down in the code
 $quiz_has_attempts=false;
@@ -543,13 +564,13 @@ if ($significantchangemade) {
     redirect($thispageurl->out());
 }
 
-question_showbank_actions($thispageurl, $cm);
+$questionbank->process_actions($thispageurl, $cm);
 
 /// all commands have been dealt with, now print the page
 
 if (isset($quiz->instance) and $DB->record_exists_select('quiz_attempts',
         "quiz = ? AND preview = '0'", array($quiz->instance))){
-    $quiz_has_attempts=true;
+    $questionbank->set_quiz_has_attempts(true);
 }
 
 // Print the header.
@@ -610,14 +631,12 @@ echo '<span id="questionbank"></span>';
 echo '<div class="container">';
 echo '<div id="module" class="module">';
 echo '<div class="bd">';
-$cmoptions = new stdClass;
-$cmoptions->hasattempts=$quiz_has_attempts;
-quiz_question_showbank('editq', $contexts, $thispageurl, $cm,
+$questionbank->display('editq', $contexts, $thispageurl, $cm,
         $pagevars['qpage'],
         $pagevars['qperpage'], $pagevars['qsortorder'],
         $pagevars['qsortorderdecoded'],
         $pagevars['cat'], $pagevars['recurse'], $pagevars['showhidden'],
-        $pagevars['showquestiontext'],$cmoptions);
+        $pagevars['showquestiontext']);
 echo '</div> <!-- end .bd -->';
 echo '</div> <!-- end .module -->';
 echo '</div> <!-- end .container -->';
index 4cf30b66f8ce9561fdaf631401f4d1662302ed69..4bdd5289964293448d12224496c9a48a5507ffe4 100644 (file)
@@ -1,13 +1,34 @@
 <?php // $Id$
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.org                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards Martin Dougiamas and others                //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
 /**
  * Functions used by edit.php to edit quizzes
  *
- * @author Martin Dougiamas and many others. This has recently been extensively
- *         rewritten by members of the Serving Mathematics project
- *         {@link http://maths.york.ac.uk/serving_maths}
  * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
  * @package quiz
- */
+ *//** */
 
 require_once("locallib.php");
 
@@ -43,7 +64,6 @@ function quiz_delete_quiz_question($id, &$quiz) {
     return true;
 }
 
-
 /**
 * Add a question to a quiz
 *
@@ -229,7 +249,7 @@ function quiz_print_question_list($quiz, $pageurl, $allowdelete=true,
 
     $a = '<input name="moveselectedonpagetop" type="text" size="2" '.
         $pagingdisabled.' />';
-        
+
     $reordercontrols2top='<div class="moveselectedonpage">'.
         get_string("moveselectedonpage","quiz", $a) .
         '<input type="submit" name="savechanges" value="'.
@@ -427,7 +447,7 @@ function quiz_print_question_list($quiz, $pageurl, $allowdelete=true,
 <?php if(strcmp($question->qtype,'random')===0){
     echo '<a href="'.$questionurl->out().'" class="configurerandomquestion">'.get_string("configurerandomquestion","quiz").'</a>';
 }
-            
+
 ?>
 </div>
 </form>
@@ -759,7 +779,7 @@ function quiz_print_randomquestion(&$question, &$pageurl, &$quiz,$quiz_qbanktool
     $a = new stdClass;
     $a->arrow = $THEME->rarrow;
     $strshowcategorycontents=get_string('showcategorycontents','quiz', $a);
-    
+
     echo '<div class="randomquestioncategory">';
     echo '<a href="'.
          $pageurl->out(false,array("qbanktool"=>1,
@@ -768,7 +788,6 @@ function quiz_print_randomquestion(&$question, &$pageurl, &$quiz,$quiz_qbanktool
     echo '<span class="questionpreview">'.
         quiz_question_preview_button($quiz, $question).
         '</span>';
-    
 
     echo "</div>";
 
@@ -806,7 +825,7 @@ function quiz_print_randomquestion(&$question, &$pageurl, &$quiz,$quiz_qbanktool
         if ($questioncount>$randomquestionlistsize){
             echo "... ";
         }
-        
+
         $a = new stdClass;
         $a->arrow = $THEME->rarrow;
         $strshowcategorycontents=get_string("showcategorycontents","quiz",$a);
@@ -815,7 +834,7 @@ function quiz_print_randomquestion(&$question, &$pageurl, &$quiz,$quiz_qbanktool
         echo ' <a href="'.
          $pageurl->out(false,array("qbanktool"=>1,"cat"=>$category->id.','.$category->contextid)).
          '">'.$strshowcategorycontents.'</a>';
-        
+
         echo "</li>";
         echo "</ul>";
     }
@@ -934,7 +953,7 @@ function quiz_print_randomquestion_reordertool(&$question, &$pageurl, &$quiz){
             $reordercheckboxlabelclose.'<!--</a>-->';
     echo '<span class="questionpreview">';
     echo quiz_question_preview_button($quiz, $question,false);
-    
+
     echo '</span>';
     echo "</div>";
 
@@ -989,452 +1008,459 @@ function quiz_question_tostring(&$question,$showicon=false,$showquestiontext=tru
         }
 }
 
+/**
+ * Subclass to customise the view of the question bank for the quiz editing screen.
+ */
+class quiz_question_bank_view extends question_bank_view {
+    protected $quizhasattempts = false;
 
+    public function __construct() {
 
+    }
 
+    /**
+     * Let the question bank display know whether the quiz has been attempted,
+     * hence whether some bits of UI, like the add this question to the quiz icon,
+     * should be displayed.
+     * @param boolean $quizhasattempts whether the quiz has attempts.
+     */
+    public function set_quiz_has_attempts($quizhasattempts) {
+        $this->quizhasattempts = $quizhasattempts;
+    }
 
-/**
- * Shows the question bank editing interface.
- * A changed copy of the function at question/editlib.php; to be refactored.
- *
- * The function also processes a number of actions:
- *
- * Actions affecting the question pool:
- * move           Moves a question to a different category
- * deleteselected Deletes the selected questions from the category
- * Other actions:
- * category      Chooses the category
- * displayoptions Sets display options
- *
- * @author Martin Dougiamas and many others. This has recently been extensively
- *         rewritten by Gustav Delius and other members of the Serving Mathematics project
- *         {@link http://maths.york.ac.uk/serving_maths}. Partially 
- *         rewritten by Olli Savolainen as a part of the Quiz UI Redesign 
- *         project in Summer 2008
- *         {@link http://docs.moodle.org/en/Development:Quiz_UI_redesign}.
- * @param moodle_url $pageurl object representing this pages url.
- */
-function quiz_question_showbank($tabname, $contexts, $pageurl, $cm,
-        $page, $perpage, $sortorder, $sortorderdecoded, $cat, $recurse,
-        $showhidden, $showquestiontext, $cmoptions){
-    global $COURSE,$DB;
-
-    if (optional_param('deleteselected', false, PARAM_BOOL)){ // teacher still has to confirm
-        // make a list of all the questions that are selected
-        $rawquestions = $_REQUEST; // This code is called by both POST forms and GET links, so cannot use data_submitted.
-        $questionlist = '';  // comma separated list of ids of questions to be deleted
-        $questionnames = ''; // string with names of questions separated by <br /> with
-                             // an asterix in front of those that are in use
-        $inuse = false;      // set to true if at least one of the questions is in use
-        foreach ($rawquestions as $key => $value) {    // Parse input for question ids
-            if (preg_match('!^q([0-9]+)$!', $key, $matches)) {
-                $key = $matches[1];
-                $questionlist .= $key.',';
-                question_require_capability_on($key, 'edit');
-                if ($DB->record_exists('quiz_question_instances', array('question'=>$key))) {
-                    $questionnames .= '* ';
-                    $inuse = true;
+    /**
+     * Shows the question bank editing interface.
+     * A changed copy of the function at question/editlib.php; to be refactored.
+     *
+     * The function also processes a number of actions:
+     *
+     * Actions affecting the question pool:
+     * move           Moves a question to a different category
+     * deleteselected Deletes the selected questions from the category
+     * Other actions:
+     * category      Chooses the category
+     * displayoptions Sets display options
+     */
+    function display($tabname, $contexts, $pageurl, $cm, $page, $perpage, $sortorder,
+            $sortorderdecoded, $cat, $recurse, $showhidden, $showquestiontext){
+        global $COURSE,$DB;
+
+        if (optional_param('deleteselected', false, PARAM_BOOL)){ // teacher still has to confirm
+            // make a list of all the questions that are selected
+            $rawquestions = $_REQUEST; // This code is called by both POST forms and GET links, so cannot use data_submitted.
+            $questionlist = '';  // comma separated list of ids of questions to be deleted
+            $questionnames = ''; // string with names of questions separated by <br /> with
+                                 // an asterix in front of those that are in use
+            $inuse = false;      // set to true if at least one of the questions is in use
+            foreach ($rawquestions as $key => $value) {    // Parse input for question ids
+                if (preg_match('!^q([0-9]+)$!', $key, $matches)) {
+                    $key = $matches[1];
+                    $questionlist .= $key.',';
+                    question_require_capability_on($key, 'edit');
+                    if ($DB->record_exists('quiz_question_instances', array('question'=>$key))) {
+                        $questionnames .= '* ';
+                        $inuse = true;
+                    }
+                    $questionnames .= $DB->get_field('question', 'name', array('id'=>$key)).
+                            '<br />';
                 }
-                $questionnames .= $DB->get_field('question', 'name', array('id'=>$key)).
-                        '<br />';
             }
-        }
-        if (!$questionlist) { // no questions were selected
-            redirect($pageurl->out());
-        }
-        $questionlist = rtrim($questionlist, ',');
+            if (!$questionlist) { // no questions were selected
+                redirect($pageurl->out());
+            }
+            $questionlist = rtrim($questionlist, ',');
+
+            // Add an explanation about questions in use
+            if ($inuse) {
+                $questionnames .= '<br />'.get_string('questionsinuse', 'quiz');
+            }
+            notice_yesno(get_string("deletequestionscheck", "quiz", $questionnames),
+                        $pageurl->out_action(array('deleteselected'=>$questionlist,
+                                'confirm'=>md5($questionlist))),
+                        $pageurl->out_action());
+        }else{
+            //actual question bank
+            // starts with category selection form
+            list($categoryid, $contextid)=  explode(',', $cat);
+
+            if (!$categoryid) {
+                print_box_start('generalbox questionbank');
+                $this->display_category_form($contexts->having_one_edit_tab_cap($tabname), $pageurl, $cat, $recurse, $showhidden, $showquestiontext);
+                echo "<p style=\"text-align:center;\"><b>";
+                print_string("selectcategoryabove", "quiz");
+                echo "</b></p>";
+                print_box_end();
+                return;
+            }
+
+            if (!$category = $DB->get_record('question_categories',
+                    array('id' => $categoryid, 'contextid' => $contextid))) {
+                        print_box_start('generalbox questionbank');
+                notify('Category not found!');
+                print_box_end();
+                return;
+            }
+            $formatoptions = new stdClass;
+            $formatoptions->noclean = true;
+            $strcategory = get_string('category', 'quiz');
+            echo '<div class="categoryinfo"><div class="categorynamefieldcontainer">'.
+                    $strcategory;
+            echo ': <span class="categorynamefield">';
+            echo shorten_text(strip_tags(format_text($category->name, FORMAT_MOODLE,
+                    $formatoptions, $COURSE->id)),60);
+            echo '</span></div><div class="categoryinfofieldcontainer"><span class="categoryinfofield">';
+            echo shorten_text(strip_tags(format_text($category->info, FORMAT_MOODLE,
+                    $formatoptions, $COURSE->id)),200);
+            echo '</span></div></div>';
+
+            print_box_start('generalbox questionbank');
 
-        // Add an explanation about questions in use
-        if ($inuse) {
-            $questionnames .= '<br />'.get_string('questionsinuse', 'quiz');
+            $this->display_category_form($contexts->having_one_edit_tab_cap($tabname),
+                    $pageurl, $cat, $recurse, $showhidden, $showquestiontext);
+            // continues with list of questions
+
+            $this->display_question_list($contexts->having_one_edit_tab_cap($tabname),
+                    $pageurl,
+                    $cat,
+                    isset($cm) ? $cm : null,
+                    $recurse,
+                    $page,
+                    $perpage,
+                    $showhidden,
+                    $sortorder,
+                    $sortorderdecoded,
+                    $showquestiontext,
+                    $contexts->having_cap('moodle/question:add'));
+
+            echo '<hr/><form method="get" action="edit.php" id="displayoptions">';
+            echo "<fieldset class='invisiblefieldset'>";
+            echo $pageurl->hidden_params_out(array('recurse', 'showhidden',
+                    'showquestiontext'));
+            $this->display_category_form_checkbox('recurse', $recurse);
+            $this->display_category_form_checkbox('showhidden', $showhidden);
+            echo '<noscript><div class="centerpara"><input type="submit" value="'.
+                    get_string('go') .'" />';
+            echo '</div></noscript></fieldset></form>';
+
+            print_box_end();
         }
-        notice_yesno(get_string("deletequestionscheck", "quiz", $questionnames),
-                    $pageurl->out_action(array('deleteselected'=>$questionlist,
-                            'confirm'=>md5($questionlist))),
-                    $pageurl->out_action());
-    }else{
-        //actual question bank
-        // starts with category selection form
-        list($categoryid, $contextid)=  explode(',', $cat);
+
+    }
+    /**
+     * prints a form to choose categories
+     * A changed copy of the function at question/editlib.php; to be refactored.
+     *
+     */
+    function display_category_form($contexts, $pageurl, $current, $recurse=1,
+            $showhidden=false, $showquestiontext=false) {
+        global $CFG;
+
+    /// Get all the existing categories now
+        $catmenu = question_category_options($contexts, false, 0, true);
+
+        $strcategory = get_string('category', 'quiz');
+        $strselectcategory = get_string('selectcategory', 'quiz');
+        $strshow = get_string('show', 'quiz');
+        $streditcats = get_string('editcategories', 'quiz');
+
+        popup_form ('edit.php?'.$pageurl->get_query_string().'&amp;category=',
+                $catmenu, 'catmenu', $current, '', '', '', false, 'self',
+                $strselectcategory.":");
+    }
+
+    /**
+    * Prints the table of questions in a category with interactions
+    * A changed copy of the function at question/editlib.php; to be refactored.
+    *
+    * @param object $course   The course object
+    * @param int $categoryid  The id of the question category to be displayed
+    * @param int $cm      The course module record if we are in the context of a particular module, 0 otherwise
+    * @param int $recurse     This is 1 if subcategories should be included, 0 otherwise
+    * @param int $page        The number of the page to be displayed
+    * @param int $perpage     Number of questions to show per page
+    * @param boolean $showhidden   True if also hidden questions should be displayed
+    * @param boolean $showquestiontext whether the text of each question should be shown in the list
+    */
+    function display_question_list($contexts, $pageurl, $categoryandcontext,
+            $cm = null, $recurse=1, $page=0, $perpage=100, $showhidden=false,
+            $sortorder='typename', $sortorderdecoded='qtype, name ASC',
+            $showquestiontext = false, $addcontexts = array()) {
+        global $USER, $CFG, $THEME, $COURSE, $DB;
+        list($categoryid, $contextid)=  explode(',', $categoryandcontext);
+
+        $qtypemenu = question_type_menu();
+
+        $strcategory = get_string("category", "quiz");
+        $strquestion = get_string("question", "quiz");
+        $straddquestions = get_string("addquestions", "quiz");
+        $strimportquestions = get_string("importquestions", "quiz");
+        $strexportquestions = get_string("exportquestions", "quiz");
+        $strnoquestions = get_string("noquestions", "quiz");
+        $strselect = get_string("select", "quiz");
+        $strselectall = get_string("selectall", "quiz");
+        $strselectnone = get_string("selectnone", "quiz");
+        $strcreatenewquestion = get_string("createnewquestion", "quiz");
+        $strquestion = get_string("question", "quiz");
+        $strdelete = get_string("delete");
+        $stredit = get_string("edit");
+        $strmove = get_string('moveqtoanothercontext', 'question');
+        $strview = get_string("view");
+        $straction = get_string("action");
+        $strrestore = get_string('restore');
+
+        $strtype = get_string("type", "quiz");
+        $strcreatemultiple = get_string("createmultiple", "quiz");
+        $strpreview = get_string("preview","quiz");
 
         if (!$categoryid) {
-            print_box_start('generalbox questionbank');
-            quiz_question_category_form($contexts->having_one_edit_tab_cap($tabname), $pageurl, $cat, $recurse, $showhidden, $showquestiontext);
             echo "<p style=\"text-align:center;\"><b>";
             print_string("selectcategoryabove", "quiz");
             echo "</b></p>";
-            print_box_end();
             return;
         }
 
         if (!$category = $DB->get_record('question_categories',
                 array('id' => $categoryid, 'contextid' => $contextid))) {
-                    print_box_start('generalbox questionbank');
             notify('Category not found!');
-            print_box_end();
             return;
         }
-        $formatoptions = new stdClass;
-        $formatoptions->noclean = true;
-        $strcategory = get_string('category', 'quiz');
-        echo '<div class="categoryinfo"><div class="categorynamefieldcontainer">'.
-                $strcategory;
-        echo ': <span class="categorynamefield">';
-        echo shorten_text(strip_tags(format_text($category->name, FORMAT_MOODLE,
-                $formatoptions, $COURSE->id)),60);
-        echo '</span></div><div class="categoryinfofieldcontainer"><span class="categoryinfofield">';
-        echo shorten_text(strip_tags(format_text($category->info, FORMAT_MOODLE,
-                $formatoptions, $COURSE->id)),200);
-        echo '</span></div></div>';
-
-        print_box_start('generalbox questionbank');
-
-        quiz_question_category_form($contexts->having_one_edit_tab_cap($tabname),
-                $pageurl, $cat, $recurse, $showhidden, $showquestiontext);
-        // continues with list of questions
-
-        quiz_question_list($contexts->having_one_edit_tab_cap($tabname),
-                $pageurl,
-                $cat,
-                isset($cm) ? $cm : null,
-                $recurse,
-                $page,
-                $perpage,
-                $showhidden,
-                $sortorder,
-                $sortorderdecoded,
-                $showquestiontext,
-                $contexts->having_cap('moodle/question:add'),
-                $cmoptions);
-
-        echo '<hr/><form method="get" action="edit.php" id="displayoptions">';
-        echo "<fieldset class='invisiblefieldset'>";
-        echo $pageurl->hidden_params_out(array('recurse', 'showhidden',
-                'showquestiontext'));
-        question_category_form_checkbox('recurse', $recurse);
-        question_category_form_checkbox('showhidden', $showhidden);
-        echo '<noscript><div class="centerpara"><input type="submit" value="'.
-                get_string('go') .'" />';
-        echo '</div></noscript></fieldset></form>';
-
-        print_box_end();
-    }
-
-}
-/**
- * prints a form to choose categories
- * A changed copy of the function at question/editlib.php; to be refactored.
- *
- */
-function quiz_question_category_form($contexts, $pageurl, $current, $recurse=1,
-        $showhidden=false, $showquestiontext=false) {
-    global $CFG;
-
-/// Get all the existing categories now
-    $catmenu = question_category_options($contexts, false, 0, true);
-
-    $strcategory = get_string('category', 'quiz');
-    $strselectcategory = get_string('selectcategory', 'quiz');
-    $strshow = get_string('show', 'quiz');
-    $streditcats = get_string('editcategories', 'quiz');
-
-    popup_form ('edit.php?'.$pageurl->get_query_string().'&amp;category=',
-            $catmenu, 'catmenu', $current, '', '', '', false, 'self',
-            $strselectcategory.":");
-}
-
-
-
-/**
-* Prints the table of questions in a category with interactions
-* A changed copy of the function at question/editlib.php; to be refactored.
-*
-* @param object $course   The course object
-* @param int $categoryid  The id of the question category to be displayed
-* @param int $cm      The course module record if we are in the context of a particular module, 0 otherwise
-* @param int $recurse     This is 1 if subcategories should be included, 0 otherwise
-* @param int $page        The number of the page to be displayed
-* @param int $perpage     Number of questions to show per page
-* @param boolean $showhidden   True if also hidden questions should be displayed
-* @param boolean $showquestiontext whether the text of each question should be shown in the list
-* @param object $cmoptions Options to be passed on to the callbacks called from this function
-*/
-function quiz_question_list($contexts, $pageurl, $categoryandcontext,
-        $cm = null, $recurse=1, $page=0, $perpage=100, $showhidden=false,
-        $sortorder='typename', $sortorderdecoded='qtype, name ASC',
-        $showquestiontext = false, $addcontexts = array(), $cmoptions) {
-    global $USER, $CFG, $THEME, $COURSE, $DB;
-    list($categoryid, $contextid)=  explode(',', $categoryandcontext);
-
-    $qtypemenu = question_type_menu();
-
-    $strcategory = get_string("category", "quiz");
-    $strquestion = get_string("question", "quiz");
-    $straddquestions = get_string("addquestions", "quiz");
-    $strimportquestions = get_string("importquestions", "quiz");
-    $strexportquestions = get_string("exportquestions", "quiz");
-    $strnoquestions = get_string("noquestions", "quiz");
-    $strselect = get_string("select", "quiz");
-    $strselectall = get_string("selectall", "quiz");
-    $strselectnone = get_string("selectnone", "quiz");
-    $strcreatenewquestion = get_string("createnewquestion", "quiz");
-    $strquestion = get_string("question", "quiz");
-    $strdelete = get_string("delete");
-    $stredit = get_string("edit");
-    $strmove = get_string('moveqtoanothercontext', 'question');
-    $strview = get_string("view");
-    $straction = get_string("action");
-    $strrestore = get_string('restore');
-
-    $strtype = get_string("type", "quiz");
-    $strcreatemultiple = get_string("createmultiple", "quiz");
-    $strpreview = get_string("preview","quiz");
-
-    if (!$categoryid) {
-        echo "<p style=\"text-align:center;\"><b>";
-        print_string("selectcategoryabove", "quiz");
-        echo "</b></p>";
-        return;
-    }
-
-    if (!$category = $DB->get_record('question_categories',
-            array('id' => $categoryid, 'contextid' => $contextid))) {
-        notify('Category not found!');
-        return;
-    }
 
-    $catcontext = get_context_instance_by_id($contextid);
-    $canadd = has_capability('moodle/question:add', $catcontext);
-    //check for capabilities on all questions in category, will also apply to sub cats.
-    $caneditall =has_capability('moodle/question:editall', $catcontext);
-    $canuseall =has_capability('moodle/question:useall', $catcontext);
-    $canmoveall =has_capability('moodle/question:moveall', $catcontext);
+        $catcontext = get_context_instance_by_id($contextid);
+        $canadd = has_capability('moodle/question:add', $catcontext);
+        //check for capabilities on all questions in category, will also apply to sub cats.
+        $caneditall =has_capability('moodle/question:editall', $catcontext);
+        $canuseall =has_capability('moodle/question:useall', $catcontext);
+        $canmoveall =has_capability('moodle/question:moveall', $catcontext);
 
-    if ($cm AND $cm->modname == 'quiz') {
-        $quizid = $cm->instance;
-    } else {
-        $quizid = 0;
-    }
-    //create the url of the new question page to forward to. return url is given
-    //as a parameter and automatically urlencoded.
+        if ($cm AND $cm->modname == 'quiz') {
+            $quizid = $cm->instance;
+        } else {
+            $quizid = 0;
+        }
+        //create the url of the new question page to forward to. return url is given
+        //as a parameter and automatically urlencoded.
 
 
 
-    $returnurl = $pageurl->out();
-    $questionurl = new moodle_url("$CFG->wwwroot/question/question.php",
-                                array('returnurl' => $returnurl));
-    if ($cm!==null){
-        $questionurl->param('cmid', $cm->id);
-    } else {
-        $questionurl->param('courseid', $COURSE->id);
-    }
-    $questionmoveurl = new moodle_url("$CFG->wwwroot/question/contextmoveq.php",
-                                array('returnurl' => $returnurl));
-    if ($cm!==null){
-        $questionmoveurl->param('cmid', $cm->id);
-    } else {
-        $questionmoveurl->param('courseid', $COURSE->id);
-    }
+        $returnurl = $pageurl->out();
+        $questionurl = new moodle_url("$CFG->wwwroot/question/question.php",
+                                    array('returnurl' => $returnurl));
+        if ($cm!==null){
+            $questionurl->param('cmid', $cm->id);
+        } else {
+            $questionurl->param('courseid', $COURSE->id);
+        }
+        $questionmoveurl = new moodle_url("$CFG->wwwroot/question/contextmoveq.php",
+                                    array('returnurl' => $returnurl));
+        if ($cm!==null){
+            $questionmoveurl->param('cmid', $cm->id);
+        } else {
+            $questionmoveurl->param('courseid', $COURSE->id);
+        }
 
 
-    $categorylist = ($recurse) ? question_categorylist($category->id) : $category->id;
+        $categorylist = ($recurse) ? question_categorylist($category->id) : $category->id;
 
-    // hide-feature
-    $showhidden = $showhidden ? '' : " AND hidden = '0'";
-    echo '<div class="createnewquestion">';
-    if ($canadd) {
-        popup_form ($questionurl->out(false, array('category' => $category->id)).
-                '&amp;qtype=', $qtypemenu, "addquestion_$page", "", "choose", "",
-                "", false, "self", "<strong>$strcreatenewquestion</strong>");
-        helpbutton("questiontypes", $strcreatenewquestion, "quiz");
-    }
-    else {
-        print_string('nopermissionadd', 'question');
-    }
-    echo '</div>';
-
-
-        $categorylist_array =  explode(',', $categorylist);
+        // hide-feature
+        $showhidden = $showhidden ? '' : " AND hidden = '0'";
+        echo '<div class="createnewquestion">';
+        if ($canadd) {
+            popup_form ($questionurl->out(false, array('category' => $category->id)).
+                    '&amp;qtype=', $qtypemenu, "addquestion_$page", "", "choose", "",
+                    "", false, "self", "<strong>$strcreatenewquestion</strong>");
+            helpbutton("questiontypes", $strcreatenewquestion, "quiz");
+        }
+        else {
+            print_string('nopermissionadd', 'question');
+        }
+        echo '</div>';
 
-    list($usql, $params) = $DB->get_in_or_equal($categorylist_array);
-    if (!$totalnumber = $DB->count_records_select('question',
-            "category $usql AND parent = '0' $showhidden", $params)) {
-        echo '<div class="categoryquestionscontainer noquestionsincategory">';
-        print_string("noquestions", "quiz");
-        echo "</div>";
-        return;
-    }
 
-    if (!$questions = $DB->get_records_select('question',
-                "category $usql AND parent = '0' $showhidden", $params, $sortorderdecoded,
-                '*', $page*$perpage, $perpage)) {
+            $categorylist_array =  explode(',', $categorylist);
 
-        // There are no questions on the requested page.
-        $page = 0;
-        if (!$questionsatall = $DB->get_records_select('question',
-                "category $usql AND parent = '0' $showhidden", $params, $sortorderdecoded,
-                '*', 0, $perpage)) {
-            // There are no questions at all
+        list($usql, $params) = $DB->get_in_or_equal($categorylist_array);
+        if (!$totalnumber = $DB->count_records_select('question',
+                "category $usql AND parent = '0' $showhidden", $params)) {
             echo '<div class="categoryquestionscontainer noquestionsincategory">';
             print_string("noquestions", "quiz");
             echo "</div>";
             return;
         }
-    }
 
+        if (!$questions = $DB->get_records_select('question',
+                    "category $usql AND parent = '0' $showhidden", $params, $sortorderdecoded,
+                    '*', $page*$perpage, $perpage)) {
+
+            // There are no questions on the requested page.
+            $page = 0;
+            if (!$questionsatall = $DB->get_records_select('question',
+                    "category $usql AND parent = '0' $showhidden", $params, $sortorderdecoded,
+                    '*', 0, $perpage)) {
+                // There are no questions at all
+                echo '<div class="categoryquestionscontainer noquestionsincategory">';
+                print_string("noquestions", "quiz");
+                echo "</div>";
+                return;
+            }
+        }
 
 
-    echo '<div class="categorysortopotionscontainer">';
-    echo question_sort_options($pageurl, $sortorder);
-    echo '</div>';
-    echo '<div class="categorypagingbarcontainer">';
-    print_paging_bar($totalnumber, $page, $perpage, $pageurl, 'qpage');
-    echo '</div>';
 
-    echo '<form method="post" action="edit.php">';
-    echo '<fieldset class="invisiblefieldset" style="display: block;">';
-    echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
-    echo $pageurl->hidden_params_out();
-    echo '<div class="categoryquestionscontainer">';
-    echo '<table id="categoryquestions" style="width: 100%"><colgroup><col id="qaction"></col><col id="qname"></col><col id="qextraactions"></col></colgroup><tr>';
-    echo "<th style=\"white-space:nowrap;\" class=\"header\" scope=\"col\">$straction</th>";
+        echo '<div class="categorysortopotionscontainer">';
+        $this->display_question_sort_options($pageurl, $sortorder);
+        echo '</div>';
+        echo '<div class="categorypagingbarcontainer">';
+        print_paging_bar($totalnumber, $page, $perpage, $pageurl, 'qpage');
+        echo '</div>';
 
-    echo "<th style=\"white-space:nowrap; text-align: left;\" class=\"header\" scope=\"col\">$strquestion</th>";
-    echo "<th style=\"white-space:nowrap; text-align: left;\" class=\"header\" scope=\"col\"></th>";
-    echo "</tr>\n";
-    foreach ($questions as $question) {
-        $nameclass = '';
-        $textclass = '';
-        if ($question->hidden) {
-            $nameclass = 'dimmed_text';
-            $textclass = 'dimmed_text';
-        }
-        if ($showquestiontext) {
-            $nameclass .= ' header';
-        }
-        if ($nameclass) {
-            $nameclass = 'class="' . $nameclass . '"';
-        }
-        if ($textclass) {
-            $textclass = 'class="' . $textclass . '"';
-        }
+        echo '<form method="post" action="edit.php">';
+        echo '<fieldset class="invisiblefieldset" style="display: block;">';
+        echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
+        echo $pageurl->hidden_params_out();
+        echo '<div class="categoryquestionscontainer">';
+        echo '<table id="categoryquestions" style="width: 100%"><colgroup><col id="qaction"></col><col id="qname"></col><col id="qextraactions"></col></colgroup><tr>';
+        echo "<th style=\"white-space:nowrap;\" class=\"header\" scope=\"col\">$straction</th>";
 
-        echo "<tr>\n<td style=\"white-space:nowrap;\" $nameclass>\n";
+        echo "<th style=\"white-space:nowrap; text-align: left;\" class=\"header\" scope=\"col\">$strquestion</th>";
+        echo "<th style=\"white-space:nowrap; text-align: left;\" class=\"header\" scope=\"col\"></th>";
+        echo "</tr>\n";
+        foreach ($questions as $question) {
+            $nameclass = '';
+            $textclass = '';
+            if ($question->hidden) {
+                $nameclass = 'dimmed_text';
+                $textclass = 'dimmed_text';
+            }
+            if ($showquestiontext) {
+                $nameclass .= ' header';
+            }
+            if ($nameclass) {
+                $nameclass = 'class="' . $nameclass . '"';
+            }
+            if ($textclass) {
+                $textclass = 'class="' . $textclass . '"';
+            }
 
-        $canuseq = question_has_capability_on($question, 'use',
-                $question->category);
-        if (function_exists('module_specific_actions')) {
-            echo module_specific_actions($pageurl, $question->id, $cm->id,
-            $canuseq,$cmoptions);
-        }
+            echo "<tr>\n<td style=\"white-space:nowrap;\" $nameclass>\n";
 
-        if ($caneditall || $canmoveall || $canuseall){
-            echo "<input title=\"$strselect\" type=\"checkbox\" name=\"q$question->id\" id=\"checkq$question->id\" value=\"1\" />";
-        }
-        echo "</td>\n";
-
-        echo "<td $nameclass><div>";
-        $questionstring=quiz_question_tostring($question,false,true,true);
-        echo "<label for=\"checkq$question->id\">";
-        print_question_icon($question);
-        echo " $questionstring</label>";
-
-
-
-        echo "</div></td>\n";
-        echo "<td>";
-        // edit, hide, delete question, using question capabilities, not quiz capabilieies
-        if (question_has_capability_on($question, 'edit', $question->category) ||
-                question_has_capability_on($question, 'move',
-                $question->category)) {
-            echo "<a title=\"$stredit\" href=\"".$questionurl->out(false,
-                    array('id'=>$question->id))."\"> <img
-                    src=\"$CFG->pixpath/t/edit.gif\" alt=\"$stredit\" /></a>";
-        } elseif (question_has_capability_on($question, 'view',
-                $question->category)){
-
-            echo "<a title=\"$strview\" href=\"".$questionurl->out(false,
-                    array('id'=>$question->id))."\"><img
-                    src=\"$CFG->pixpath/i/info.gif\" alt=\"$strview\" /></a>";
-        }
-        // preview
-        if ($canuseq) {
-            $quizorcourseid = $quizid?('&amp;quizid=' . $quizid):('&amp;courseid=' .$COURSE->id);
-            link_to_popup_window('/question/preview.php?id=' . $question->id .
-                    $quizorcourseid, 'questionpreview',
-                    "<img src=\"$CFG->pixpath/t/preview.gif\" class=\"iconsmall\" alt=\"$strpreview\" />",
-                    0, 0, $strpreview, QUESTION_PREVIEW_POPUP_OPTIONS);
-        }
-        echo "</td>";
+            $canuseq = question_has_capability_on($question, 'use',
+                    $question->category);
+            if (function_exists('module_specific_actions')) {
+                $cmoptions = new stdClass;
+                $cmoptions->hasattempts = $this->quizhasattempts;
+                echo module_specific_actions($pageurl, $question->id, $cm->id,
+                $canuseq, $cmoptions);
+            }
 
-        echo "</tr>\n";
-        if($showquestiontext){
-            echo '<tr><td colspan="3" ' . $textclass . '>';
-            $formatoptions = new stdClass;
-            $formatoptions->noclean = true;
-            $formatoptions->para = false;
-            echo format_text($question->questiontext,
-                    $question->questiontextformat,
-                    $formatoptions, $COURSE->id);
-            echo "</td></tr>\n";
-        }
-    }
-    echo "</table></div>\n";
+            if ($caneditall || $canmoveall || $canuseall){
+                echo "<input title=\"$strselect\" type=\"checkbox\" name=\"q$question->id\" id=\"checkq$question->id\" value=\"1\" />";
+            }
+            echo "</td>\n";
 
+            echo "<td $nameclass><div>";
+            $questionstring=quiz_question_tostring($question,false,true,true);
+            echo "<label for=\"checkq$question->id\">";
+            print_question_icon($question);
+            echo " $questionstring</label>";
 
 
 
-    echo '<div class="categorypagingbarcontainer pagingbottom">';
-    $paging = print_paging_bar($totalnumber, $page, $perpage,
-            $pageurl, 'qpage', false, true);
-    if ($totalnumber > DEFAULT_QUESTIONS_PER_PAGE) {
-        if ($perpage == DEFAULT_QUESTIONS_PER_PAGE) {
-            $showall = '<a href="edit.php?'.$pageurl->get_query_string(array('qperpage'=>1000)).'">'.get_string('showall', 'moodle', $totalnumber).'</a>';
-        } else {
-            $showall = '<a href="edit.php?'.$pageurl->get_query_string(array('qperpage'=>DEFAULT_QUESTIONS_PER_PAGE)).'">'.get_string('showperpage', 'moodle', DEFAULT_QUESTIONS_PER_PAGE).'</a>';
-        }
-        if ($paging) {
-            $paging = substr($paging, 0, strrpos($paging, '</div>'));
-            $paging .= "<br />$showall</div>";
-        } else {
-            $paging = "<div class='paging'>$showall</div>";
+            echo "</div></td>\n";
+            echo "<td>";
+            // edit, hide, delete question, using question capabilities, not quiz capabilieies
+            if (question_has_capability_on($question, 'edit', $question->category) ||
+                    question_has_capability_on($question, 'move',
+                    $question->category)) {
+                echo "<a title=\"$stredit\" href=\"".$questionurl->out(false,
+                        array('id'=>$question->id))."\"> <img
+                        src=\"$CFG->pixpath/t/edit.gif\" alt=\"$stredit\" /></a>";
+            } elseif (question_has_capability_on($question, 'view',
+                    $question->category)){
+
+                echo "<a title=\"$strview\" href=\"".$questionurl->out(false,
+                        array('id'=>$question->id))."\"><img
+                        src=\"$CFG->pixpath/i/info.gif\" alt=\"$strview\" /></a>";
+            }
+            // preview
+            if ($canuseq) {
+                $quizorcourseid = $quizid?('&amp;quizid=' . $quizid):('&amp;courseid=' .$COURSE->id);
+                link_to_popup_window('/question/preview.php?id=' . $question->id .
+                        $quizorcourseid, 'questionpreview',
+                        "<img src=\"$CFG->pixpath/t/preview.gif\" class=\"iconsmall\" alt=\"$strpreview\" />",
+                        0, 0, $strpreview, QUESTION_PREVIEW_POPUP_OPTIONS);
+            }
+            echo "</td>";
+
+            echo "</tr>\n";
+            if($showquestiontext){
+                echo '<tr><td colspan="3" ' . $textclass . '>';
+                $formatoptions = new stdClass;
+                $formatoptions->noclean = true;
+                $formatoptions->para = false;
+                echo format_text($question->questiontext,
+                        $question->questiontextformat,
+                        $formatoptions, $COURSE->id);
+                echo "</td></tr>\n";
+            }
         }
-    }
-    echo $paging;
-    echo '</div>';
-    echo '<div class="categoryselectallcontainer">';
-    if ($caneditall || $canmoveall || $canuseall){
-        echo '<a href="javascript:select_all_in(\'TABLE\',null,\'categoryquestions\');">'.$strselectall.'</a> /'.
-         ' <a href="javascript:deselect_all_in(\'TABLE\',null,\'categoryquestions\');">'.$strselectnone.'</a>';
-        echo '<br />';
-    }
-    echo "</div>\n";
-    echo '<div class="modulespecificbuttonscontainer">';
-    if ($caneditall || $canmoveall || $canuseall){
-        echo '<strong>&nbsp;'.get_string('withselected', 'quiz').':</strong><br />';
-        if (function_exists('module_specific_buttons')) {
-            echo module_specific_buttons($cm->id,$cmoptions);
+        echo "</table></div>\n";
+
+
+
+
+        echo '<div class="categorypagingbarcontainer pagingbottom">';
+        $paging = print_paging_bar($totalnumber, $page, $perpage,
+                $pageurl, 'qpage', false, true);
+        if ($totalnumber > DEFAULT_QUESTIONS_PER_PAGE) {
+            if ($perpage == DEFAULT_QUESTIONS_PER_PAGE) {
+                $showall = '<a href="edit.php?'.$pageurl->get_query_string(array('qperpage'=>1000)).'">'.get_string('showall', 'moodle', $totalnumber).'</a>';
+            } else {
+                $showall = '<a href="edit.php?'.$pageurl->get_query_string(array('qperpage'=>DEFAULT_QUESTIONS_PER_PAGE)).'">'.get_string('showperpage', 'moodle', DEFAULT_QUESTIONS_PER_PAGE).'</a>';
+            }
+            if ($paging) {
+                $paging = substr($paging, 0, strrpos($paging, '</div>'));
+                $paging .= "<br />$showall</div>";
+            } else {
+                $paging = "<div class='paging'>$showall</div>";
+            }
         }
-        // print delete and move selected question
-        if ($caneditall) {
-            echo '<input type="submit" name="deleteselected" value="'.
-                    $strdelete."\" />\n";
+        echo $paging;
+        echo '</div>';
+        echo '<div class="categoryselectallcontainer">';
+        if ($caneditall || $canmoveall || $canuseall){
+            echo '<a href="javascript:select_all_in(\'TABLE\',null,\'categoryquestions\');">'.$strselectall.'</a> /'.
+             ' <a href="javascript:deselect_all_in(\'TABLE\',null,\'categoryquestions\');">'.$strselectnone.'</a>';
+            echo '<br />';
         }
-        if (function_exists('module_specific_controls') && $canuseall) {
-            $modulespecific=module_specific_controls($totalnumber, $recurse, $category,
-                    $cm->id,$cmoptions);
-            if(!empty($modulespecific)){
-                echo "<hr />$modulespecific";
+        echo "</div>\n";
+        echo '<div class="modulespecificbuttonscontainer">';
+        if ($caneditall || $canmoveall || $canuseall){
+            echo '<strong>&nbsp;'.get_string('withselected', 'quiz').':</strong><br />';
+            if (function_exists('module_specific_buttons')) {
+                echo module_specific_buttons($cm->id,$cmoptions);
+            }
+            // print delete and move selected question
+            if ($caneditall) {
+                echo '<input type="submit" name="deleteselected" value="'.
+                        $strdelete."\" />\n";
+            }
+            if (function_exists('module_specific_controls') && $canuseall) {
+                $cmoptions = new stdClass;
+                $cmoptions->hasattempts = $this->quizhasattempts;
+                $modulespecific=module_specific_controls($totalnumber, $recurse, $category,
+                        $cm->id,$cmoptions);
+                if(!empty($modulespecific)){
+                    echo "<hr />$modulespecific";
+                }
             }
         }
-    }
-    echo "</div>\n";
+        echo "</div>\n";
 
-    echo '</fieldset>';
-    echo "</form>\n";
+        echo '</fieldset>';
+        echo "</form>\n";
+    }
 }
 
-
 /**
  * Add an arbitrary element to array at a specified index, pushing the rest
  * back.
@@ -1451,6 +1477,7 @@ function array_add_at($array,$value,$at){
     $result=array_merge($beginpart,$endpart);
     return $result;
 }
+
 /**
  * Prints the form for setting a quiz' overall grade
  * 
@@ -1478,12 +1505,12 @@ function quiz_print_grading_form($quiz, $pageurl, $tabindex){
     echo "</div></form>\n";
     return $tabindex+1;
 }
+
 /**
  * Print the status bar
  *
  * @param object $quiz The quiz object of the quiz in question
  */
-
 function quiz_print_status_bar($quiz){
     global $CFG;
     $numberofquestions=quiz_number_of_questions_in_quiz($quiz->questions);
index ab82c42fdcd4d3e7ffe426405db755772e7a200f..53804e0916ed56dc3a162f719063266807ac102d 100644 (file)
@@ -1,22 +1,43 @@
 <?php // $Id$
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.org                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards Martin Dougiamas and others                //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
 /**
 * Page to edit the question bank
 *
-* TODO: add logging
-*
-* @author Martin Dougiamas and many others. This has recently been extensively
-*         rewritten by Gustav Delius and other members of the Serving Mathematics project
-*         {@link http://maths.york.ac.uk/serving_maths}
 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
 * @package questionbank
-*/
+*//** */
 
     require_once("../config.php");
     require_once("editlib.php");
 
     list($thispageurl, $contexts, $cmid, $cm, $module, $pagevars) = question_edit_setup('questions');
+    $questionbank = new question_bank_view();
+    $questionbank->process_actions($thispageurl, $cm);
 
-    question_showbank_actions($thispageurl, $cm);
+    // TODO log this page view.
 
     $context = $contexts->lowest();
     $streditingquestions = get_string('editquestions', "quiz");
         include('tabs.php');
     }
 
-
     echo '<table class="boxaligncenter" border="0" cellpadding="2" cellspacing="0">';
     echo '<tr><td valign="top">';
 
-    question_showbank('questions', $contexts, $thispageurl, $cm, $pagevars['qpage'], $pagevars['qperpage'], $pagevars['qsortorder'], $pagevars['qsortorderdecoded'],
-                    $pagevars['cat'], $pagevars['recurse'], $pagevars['showhidden'], $pagevars['showquestiontext']);
+    $questionbank->display('questions', $contexts, $thispageurl, $cm, $pagevars['qpage'],
+            $pagevars['qperpage'], $pagevars['qsortorder'], $pagevars['qsortorderdecoded'],
+            $pagevars['cat'], $pagevars['recurse'], $pagevars['showhidden'], $pagevars['showquestiontext']);
 
     echo '</td></tr>';
     echo '</table>';
index 006e92d300d1c5078e988b6b8c4f6ea6ba0ada36..96ff9698da39a838cf5aef3d255bd13f130257bd 100644 (file)
@@ -1,20 +1,40 @@
 <?php // $Id$
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.org                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards Martin Dougiamas and others                //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
 /**
  * Functions used to show question editing interface
  *
- *
- * @author Martin Dougiamas and many others. This has recently been extensively
- *         rewritten by members of the Serving Mathematics project
- *         {@link http://maths.york.ac.uk/serving_maths}
  * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
  * @package questionbank
- */
+ *//** */
 
 require_once($CFG->libdir.'/questionlib.php');
 
 define('DEFAULT_QUESTIONS_PER_PAGE', 20);
 
-function get_module_from_cmid($cmid){
+function get_module_from_cmid($cmid) {
     global $CFG, $DB;
     if (!$cmrec = $DB->get_record_sql("SELECT cm.*, md.name as modname
                                FROM {course_modules} cm,
@@ -106,491 +126,517 @@ function question_can_delete_cat($todelete) {
         require_capability('moodle/question:managecategory', get_context_instance_by_id($contextid));
     }
 }
+
 /**
- * prints a form to choose categories
+ * This class prints a view of the question bank, including
+ *  + Some controls to allow users to to select what is displayed.
+ *  + A list of questions as a table.
+ *  + Further controls to do things with the questions.
+ *
+ * This class gives a basic view, and provides plenty of hooks where subclasses
+ * can override parts of the display.
+ *
+ * The list of questions presented as a table is generated by creating a list of
+ * question_bank_column objects, one for each 'column' to be displayed. These
+ * manage
+ *  + outputting the contents of that column, given a $question object, but also
+ *  + generating the right fragments of SQL to ensure the necessary data is present,
+ *    and sorted in the right order.
+ *  + outputting table headers.
  */
-function question_category_form($contexts, $pageurl, $current, $recurse=1, $showhidden=false, $showquestiontext=false) {
-    global $CFG;
+class question_bank_view {
+    public function __construct() {
+
+    }
 
+    /**
+     * Shows the question bank editing interface.
+     *
+     * The function also processes a number of actions:
+     *
+     * Actions affecting the question pool:
+     * move           Moves a question to a different category
+     * deleteselected Deletes the selected questions from the category
+     * Other actions:
+     * category      Chooses the category
+     * displayoptions Sets display options
+     *
+     * @param moodle_url $pageurl object representing this pages url.
+     */
+    function display($tabname, $contexts, $pageurl, $cm, $page, $perpage, $sortorder,
+            $sortorderdecoded, $cat, $recurse, $showhidden, $showquestiontext){
+        global $COURSE, $DB;
+
+        if (optional_param('deleteselected', false, PARAM_BOOL)){ // teacher still has to confirm
+            // make a list of all the questions that are selected
+            $rawquestions = $_REQUEST; // This code is called by both POST forms and GET links, so cannot use data_submitted.
+            $questionlist = '';  // comma separated list of ids of questions to be deleted
+            $questionnames = ''; // string with names of questions separated by <br /> with
+                                 // an asterix in front of those that are in use
+            $inuse = false;      // set to true if at least one of the questions is in use
+            foreach ($rawquestions as $key => $value) {    // Parse input for question ids
+                if (preg_match('!^q([0-9]+)$!', $key, $matches)) {
+                    $key = $matches[1];
+                    $questionlist .= $key.',';
+                    question_require_capability_on($key, 'edit');
+                    if ($DB->record_exists('quiz_question_instances', array('question' => $key))) {
+                        $questionnames .= '* ';
+                        $inuse = true;
+                    }
+                    $questionnames .= $DB->get_field('question', 'name', array('id' => $key)).'<br />';
+                }
+            }
+            if (!$questionlist) { // no questions were selected
+                redirect($pageurl->out());
+            }
+            $questionlist = rtrim($questionlist, ',');
 
-/// Get all the existing categories now
-    $catmenu = question_category_options($contexts, false, 0, true);
+            // Add an explanation about questions in use
+            if ($inuse) {
+                $questionnames .= '<br />'.get_string('questionsinuse', 'quiz');
+            }
+            notice_yesno(get_string("deletequestionscheck", "quiz", $questionnames),
+                        $pageurl->out_action(array('deleteselected'=>$questionlist, 'confirm'=>md5($questionlist))),
+                        $pageurl->out_action());
 
-    $strcategory = get_string('category', 'quiz');
-    $strshow = get_string('show', 'quiz');
-    $streditcats = get_string('editcategories', 'quiz');
+            echo '</td></tr>';
+            echo '</table>';
+            print_footer($COURSE);
+            exit;
+        }
 
-    popup_form ('edit.php?'.$pageurl->get_query_string().'&amp;category=', $catmenu, 'catmenu', $current, '', '', '', false, 'self', "<strong>$strcategory</strong>");
 
-    echo '<form method="get" action="edit.php" id="displayoptions">';
-    echo "<fieldset class='invisiblefieldset'>";
-    echo $pageurl->hidden_params_out(array('recurse', 'showhidden', 'showquestiontext'));
-    question_category_form_checkbox('recurse', $recurse);
-    question_category_form_checkbox('showhidden', $showhidden);
-    question_category_form_checkbox('showquestiontext', $showquestiontext);
-    echo '<noscript><div class="centerpara"><input type="submit" value="'. get_string('go') .'" />';
-    echo '</div></noscript></fieldset></form>';
-}
+        // starts with category selection form
+        print_box_start('generalbox questionbank');
+        print_heading(get_string('questionbank', 'question'), '', 2);
+        $this->display_category_form($contexts->having_one_edit_tab_cap($tabname), $pageurl, $cat, $recurse, $showhidden, $showquestiontext);
 
-/**
- * Private funciton to help the preceeding function.
- */
-function question_category_form_checkbox($name, $checked) {
-    echo '<div><input type="hidden" id="' . $name . '_off" name="' . $name . '" value="0" />';
-    echo '<input type="checkbox" id="' . $name . '_on" name="' . $name . '" value="1"';
-    if ($checked) {
-        echo ' checked="checked"';
-    }
-    echo ' onchange="getElementById(\'displayoptions\').submit(); return true;" />';
-    echo '<label for="' . $name . '_on">';
-    print_string($name, 'quiz');
-    echo "</label></div>\n";
-}
+        // continues with list of questions
+        $this->display_question_list($contexts->having_one_edit_tab_cap($tabname), $pageurl, $cat, isset($cm) ? $cm : null,
+                $recurse, $page, $perpage, $showhidden, $sortorder, $sortorderdecoded, $showquestiontext,
+                $contexts->having_cap('moodle/question:add'));
 
-/**
-* Prints the table of questions in a category with interactions
-*
-* @param object $course   The course object
-* @param int $categoryid  The id of the question category to be displayed
-* @param int $cm      The course module record if we are in the context of a particular module, 0 otherwise
-* @param int $recurse     This is 1 if subcategories should be included, 0 otherwise
-* @param int $page        The number of the page to be displayed
-* @param int $perpage     Number of questions to show per page
-* @param boolean $showhidden   True if also hidden questions should be displayed
-* @param boolean $showquestiontext whether the text of each question should be shown in the list
-*/
-function question_list($contexts, $pageurl, $categoryandcontext, $cm = null,
-        $recurse=1, $page=0, $perpage=100, $showhidden=false, $sortorder='typename', $sortorderdecoded='qtype, name ASC',
-        $showquestiontext = false, $addcontexts = array()) {
-    global $USER, $CFG, $THEME, $COURSE, $DB;
-
-    list($categoryid, $contextid)=  explode(',', $categoryandcontext);
-
-    $qtypemenu = question_type_menu();
-
-    $strcategory = get_string("category", "quiz");
-    $strquestion = get_string("question", "quiz");
-    $straddquestions = get_string("addquestions", "quiz");
-    $strimportquestions = get_string("importquestions", "quiz");
-    $strexportquestions = get_string("exportquestions", "quiz");
-    $strnoquestions = get_string("noquestionsincategory", "quiz");
-    $strselect = get_string("select", "quiz");
-    $strselectall = get_string("selectall", "quiz");
-    $strselectnone = get_string("selectnone", "quiz");
-    $strcreatenewquestion = get_string("createnewquestion", "quiz");
-    $strquestionname = get_string("questionname", "quiz");
-    $strdelete = get_string("delete");
-    $stredit = get_string("edit");
-    $strmove = get_string('moveqtoanothercontext', 'question');
-    $strview = get_string("view");
-    $straction = get_string("action");
-    $strrestore = get_string('restore');
-
-    $strtype = get_string("type", "quiz");
-    $strcreatemultiple = get_string("createmultiple", "quiz");
-    $strpreview = get_string("preview","quiz");
-
-    if (!$categoryid) {
-        echo "<p style=\"text-align:center;\"><b>";
-        print_string("selectcategoryabove", "quiz");
-        echo "</b></p>";
-        return;
-    }
-
-    if (!$category = $DB->get_record('question_categories', array('id' => $categoryid, 'contextid' => $contextid))) {
-        notify('Category not found!');
-        return;
-    }
-    $catcontext = get_context_instance_by_id($contextid);
-    $canadd = has_capability('moodle/question:add', $catcontext);
-    //check for capabilities on all questions in category, will also apply to sub cats.
-    $caneditall =has_capability('moodle/question:editall', $catcontext);
-    $canuseall =has_capability('moodle/question:useall', $catcontext);
-    $canmoveall =has_capability('moodle/question:moveall', $catcontext);
-
-    if ($cm AND $cm->modname == 'quiz') {
-        $quizid = $cm->instance;
-    } else {
-        $quizid = 0;
-    }
-    $returnurl = $pageurl->out();
-    $questionurl = new moodle_url("$CFG->wwwroot/question/question.php",
-                                array('returnurl' => $returnurl));
-    if ($cm!==null){
-        $questionurl->param('cmid', $cm->id);
-    } else {
-        $questionurl->param('courseid', $COURSE->id);
-    }
-    $questionmoveurl = new moodle_url("$CFG->wwwroot/question/contextmoveq.php",
-                                array('returnurl' => $returnurl));
-    if ($cm!==null){
-        $questionmoveurl->param('cmid', $cm->id);
-    } else {
-        $questionmoveurl->param('courseid', $COURSE->id);
+        print_box_end();
     }
-    echo '<div class="boxaligncenter">';
-    $formatoptions = new stdClass;
-    $formatoptions->noclean = true;
-    echo format_text($category->info, FORMAT_MOODLE, $formatoptions, $COURSE->id);
 
-    echo '<table><tr>';
+    /**
+     * prints a form to choose categories
+     */
+    function display_category_form($contexts, $pageurl, $current, $recurse=1, $showhidden=false, $showquestiontext=false) {
+        global $CFG;
+
 
-    if ($canadd) {
-        echo '<td valign="top" align="right">';
-        popup_form ($questionurl->out(false, array('category' => $category->id)).'&amp;qtype=', $qtypemenu, "addquestion", "", "choose", "", "", false, "self", "<strong>$strcreatenewquestion</strong>");
-        echo '</td><td valign="top" align="right">';
-        helpbutton("questiontypes", $strcreatenewquestion, "quiz");
-        echo '</td>';
-    }
-    else {
-        echo '<td>';
-        print_string('nopermissionadd', 'question');
-        echo '</td>';
-    }
+    /// Get all the existing categories now
+        $catmenu = question_category_options($contexts, false, 0, true);
 
-    echo '</tr></table>';
-    echo '</div>';
+        $strcategory = get_string('category', 'quiz');
+        $strshow = get_string('show', 'quiz');
+        $streditcats = get_string('editcategories', 'quiz');
 
-    $categorylist = ($recurse) ? question_categorylist($category->id) : $category->id;
+        popup_form('edit.php?'.$pageurl->get_query_string().'&amp;category=', $catmenu, 'catmenu', $current, '', '', '', false, 'self', "<strong>$strcategory</strong>");
 
-    // hide-feature
-    $showhidden = $showhidden ? '' : " AND hidden = '0'";
-    $categorylist_array =  explode(',', $categorylist);
-    list($usql, $params) = $DB->get_in_or_equal($categorylist_array);
-    if (!$totalnumber = $DB->count_records_select('question', "category $usql AND parent = '0' $showhidden", $params)) {
-        echo "<p style=\"text-align:center;\">";
-        echo $strnoquestions;
-        echo "</p>";
-        return;
+        echo '<form method="get" action="edit.php" id="displayoptions">';
+        echo "<fieldset class='invisiblefieldset'>";
+        echo $pageurl->hidden_params_out(array('recurse', 'showhidden', 'showquestiontext'));
+        $this->display_category_form_checkbox('recurse', $recurse);
+        $this->display_category_form_checkbox('showhidden', $showhidden);
+        $this->display_category_form_checkbox('showquestiontext', $showquestiontext);
+        echo '<noscript><div class="centerpara"><input type="submit" value="'. get_string('go') .'" />';
+        echo '</div></noscript></fieldset></form>';
     }
 
-    if (!$questions = $DB->get_records_select('question', "category $usql AND parent = '0' $showhidden", $params, $sortorderdecoded, '*', $page*$perpage, $perpage)) {
-        // There are no questions on the requested page.
-        $page = 0;
-        if (!$questions = $DB->get_records_select('question', "category $usql AND parent = '0' $showhidden", $params, $sortorderdecoded, '*', 0, $perpage)) {
-            // There are no questions at all
-            echo "<p style=\"text-align:center;\">";
-            echo $strnoquestions;
-            echo "</p>";
-            return;
+    /**
+     * Private funciton to help the preceeding function.
+     */
+    protected function display_category_form_checkbox($name, $checked) {
+        echo '<div><input type="hidden" id="' . $name . '_off" name="' . $name . '" value="0" />';
+        echo '<input type="checkbox" id="' . $name . '_on" name="' . $name . '" value="1"';
+        if ($checked) {
+            echo ' checked="checked"';
         }
+        echo ' onchange="getElementById(\'displayoptions\').submit(); return true;" />';
+        echo '<label for="' . $name . '_on">';
+        print_string($name, 'quiz');
+        echo "</label></div>\n";
     }
 
-    print_paging_bar($totalnumber, $page, $perpage, $pageurl, 'qpage');
-    echo question_sort_options($pageurl, $sortorder);
-
-
-    echo '<form method="post" action="edit.php">';
-    echo '<fieldset class="invisiblefieldset" style="display: block;">';
-    echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
-    echo $pageurl->hidden_params_out();
-    echo '<table id="categoryquestions" style="width: 100%"><tr>';
-    echo "<th style=\"white-space:nowrap;\" class=\"header\" scope=\"col\">$straction</th>";
+    /**
+    * Prints the table of questions in a category with interactions
+    *
+    * @param object $course   The course object
+    * @param int $categoryid  The id of the question category to be displayed
+    * @param int $cm      The course module record if we are in the context of a particular module, 0 otherwise
+    * @param int $recurse     This is 1 if subcategories should be included, 0 otherwise
+    * @param int $page        The number of the page to be displayed
+    * @param int $perpage     Number of questions to show per page
+    * @param boolean $showhidden   True if also hidden questions should be displayed
+    * @param boolean $showquestiontext whether the text of each question should be shown in the list
+    */
+    function display_question_list($contexts, $pageurl, $categoryandcontext, $cm = null,
+            $recurse=1, $page=0, $perpage=100, $showhidden=false, $sortorder='typename', $sortorderdecoded='qtype, name ASC',
+            $showquestiontext = false, $addcontexts = array()) {
+        global $USER, $CFG, $THEME, $COURSE, $DB;
+
+        list($categoryid, $contextid)=  explode(',', $categoryandcontext);
+
+        $qtypemenu = question_type_menu();
+
+        $strcategory = get_string("category", "quiz");
+        $strquestion = get_string("question", "quiz");
+        $straddquestions = get_string("addquestions", "quiz");
+        $strimportquestions = get_string("importquestions", "quiz");
+        $strexportquestions = get_string("exportquestions", "quiz");
+        $strnoquestions = get_string("noquestionsincategory", "quiz");
+        $strselect = get_string("select", "quiz");
+        $strselectall = get_string("selectall", "quiz");
+        $strselectnone = get_string("selectnone", "quiz");
+        $strcreatenewquestion = get_string("createnewquestion", "quiz");
+        $strquestionname = get_string("questionname", "quiz");
+        $strdelete = get_string("delete");
+        $stredit = get_string("edit");
+        $strmove = get_string('moveqtoanothercontext', 'question');
+        $strview = get_string("view");
+        $straction = get_string("action");
+        $strrestore = get_string('restore');
+
+        $strtype = get_string("type", "quiz");
+        $strcreatemultiple = get_string("createmultiple", "quiz");
+        $strpreview = get_string("preview","quiz");
+
+        if (!$categoryid) {
+            echo "<p style=\"text-align:center;\"><b>";
+            print_string("selectcategoryabove", "quiz");
+            echo "</b></p>";
+            return;
+        }
 
-    echo "<th style=\"white-space:nowrap; text-align: left;\" class=\"header\" scope=\"col\">$strquestionname</th>
-    <th style=\"white-space:nowrap; text-align: right;\" class=\"header\" scope=\"col\">$strtype</th>";
-    echo "</tr>\n";
-    foreach ($questions as $question) {
-        $nameclass = '';
-        $textclass = '';
-        if ($question->hidden) {
-            $nameclass = 'dimmed_text';
-            $textclass = 'dimmed_text';
+        if (!$category = $DB->get_record('question_categories', array('id' => $categoryid, 'contextid' => $contextid))) {
+            notify('Category not found!');
+            return;
         }
-        if ($showquestiontext) {
-            $nameclass .= ' header';
+        $catcontext = get_context_instance_by_id($contextid);
+        $canadd = has_capability('moodle/question:add', $catcontext);
+        //check for capabilities on all questions in category, will also apply to sub cats.
+        $caneditall =has_capability('moodle/question:editall', $catcontext);
+        $canuseall =has_capability('moodle/question:useall', $catcontext);
+        $canmoveall =has_capability('moodle/question:moveall', $catcontext);
+
+        if ($cm AND $cm->modname == 'quiz') {
+            $quizid = $cm->instance;
+        } else {
+            $quizid = 0;
         }
-        if ($nameclass) {
-            $nameclass = 'class="' . $nameclass . '"';
+        $returnurl = $pageurl->out();
+        $questionurl = new moodle_url("$CFG->wwwroot/question/question.php",
+                                    array('returnurl' => $returnurl));
+        if ($cm!==null){
+            $questionurl->param('cmid', $cm->id);
+        } else {
+            $questionurl->param('courseid', $COURSE->id);
         }
-        if ($textclass) {
-            $textclass = 'class="' . $textclass . '"';
+        $questionmoveurl = new moodle_url("$CFG->wwwroot/question/contextmoveq.php",
+                                    array('returnurl' => $returnurl));
+        if ($cm!==null){
+            $questionmoveurl->param('cmid', $cm->id);
+        } else {
+            $questionmoveurl->param('courseid', $COURSE->id);
         }
+        echo '<div class="boxaligncenter">';
+        $formatoptions = new stdClass;
+        $formatoptions->noclean = true;
+        echo format_text($category->info, FORMAT_MOODLE, $formatoptions, $COURSE->id);
 
-        echo "<tr>\n<td style=\"white-space:nowrap;\" $nameclass>\n";
+        echo '<table><tr>';
 
-        $canuseq = question_has_capability_on($question, 'use', $question->category);
-        if (function_exists('module_specific_actions')) {
-            echo module_specific_actions($pageurl, $question->id, $cm->id, $canuseq);
+        if ($canadd) {
+            echo '<td valign="top" align="right">';
+            popup_form ($questionurl->out(false, array('category' => $category->id)).'&amp;qtype=', $qtypemenu, "addquestion", "", "choose", "", "", false, "self", "<strong>$strcreatenewquestion</strong>");
+            echo '</td><td valign="top" align="right">';
+            helpbutton("questiontypes", $strcreatenewquestion, "quiz");
+            echo '</td>';
         }
-
-        // preview
-        if ($canuseq) {
-            $quizorcourseid = $quizid?('&amp;quizid=' . $quizid):('&amp;courseid=' .$COURSE->id);
-            link_to_popup_window('/question/preview.php?id=' . $question->id . $quizorcourseid, 'questionpreview',
-                    "<img src=\"$CFG->pixpath/t/preview.gif\" class=\"iconsmall\" alt=\"$strpreview\" />",
-                    0, 0, $strpreview, QUESTION_PREVIEW_POPUP_OPTIONS);
-        }
-        // edit, hide, delete question, using question capabilities, not quiz capabilieies
-        if (question_has_capability_on($question, 'edit', $question->category) || question_has_capability_on($question, 'move', $question->category)) {
-            echo "<a title=\"$stredit\" href=\"".$questionurl->out(false, array('id'=>$question->id))."\"><img
-                    src=\"$CFG->pixpath/t/edit.gif\" alt=\"$stredit\" /></a>&nbsp;";
-        } elseif (question_has_capability_on($question, 'view', $question->category)){
-            echo "<a title=\"$strview\" href=\"".$questionurl->out(false, array('id'=>$question->id))."\"><img
-                    src=\"$CFG->pixpath/i/info.gif\" alt=\"$strview\" /></a>&nbsp;";
+        else {
+            echo '<td>';
+            print_string('nopermissionadd', 'question');
+            echo '</td>';
         }
 
-        if (question_has_capability_on($question, 'move', $question->category) && question_has_capability_on($question, 'view', $question->category)) {
-            echo "<a title=\"$strmove\" href=\"".$questionurl->out(false, array('id'=>$question->id, 'movecontext'=>1))."\"><img
-                    src=\"$CFG->pixpath/t/move.gif\" alt=\"$strmove\" /></a>&nbsp;";
+        echo '</tr></table>';
+        echo '</div>';
+
+        $categorylist = ($recurse) ? question_categorylist($category->id) : $category->id;
+
+        // hide-feature
+        $showhidden = $showhidden ? '' : " AND hidden = '0'";
+        $categorylist_array =  explode(',', $categorylist);
+        list($usql, $params) = $DB->get_in_or_equal($categorylist_array);
+        if (!$totalnumber = $DB->count_records_select('question', "category $usql AND parent = '0' $showhidden", $params)) {
+            echo "<p style=\"text-align:center;\">";
+            echo $strnoquestions;
+            echo "</p>";
+            return;
         }
 
-        if (question_has_capability_on($question, 'edit', $question->category)) {
-            // hide-feature
-            if($question->hidden) {
-                echo "<a title=\"$strrestore\" href=\"edit.php?".$pageurl->get_query_string()."&amp;unhide=$question->id&amp;sesskey=".sesskey()."\"><img
-                        src=\"$CFG->pixpath/t/restore.gif\" alt=\"$strrestore\" /></a>";
-            } else {
-                echo "<a title=\"$strdelete\" href=\"edit.php?".$pageurl->get_query_string()."&amp;deleteselected=$question->id&amp;q$question->id=1\"><img
-                        src=\"$CFG->pixpath/t/delete.gif\" alt=\"$strdelete\" /></a>";
+        if (!$questions = $DB->get_records_select('question', "category $usql AND parent = '0' $showhidden", $params, $sortorderdecoded, '*', $page*$perpage, $perpage)) {
+            // There are no questions on the requested page.
+            $page = 0;
+            if (!$questions = $DB->get_records_select('question', "category $usql AND parent = '0' $showhidden", $params, $sortorderdecoded, '*', 0, $perpage)) {
+                // There are no questions at all
+                echo "<p style=\"text-align:center;\">";
+                echo $strnoquestions;
+                echo "</p>";
+                return;
             }
         }
-        if ($caneditall || $canmoveall || $canuseall){
-            echo "&nbsp;<input title=\"$strselect\" type=\"checkbox\" name=\"q$question->id\" value=\"1\" />";
-        }
-        echo "</td>\n";
 
-        echo "<td $nameclass>" . format_string($question->name) . "</td>\n";
-        echo "<td $nameclass style='text-align: right'>\n";
-        print_question_icon($question);
-        echo "</td>\n";
+        print_paging_bar($totalnumber, $page, $perpage, $pageurl, 'qpage');
+        $this->display_question_sort_options($pageurl, $sortorder);
+
+        echo '<form method="post" action="edit.php">';
+        echo '<fieldset class="invisiblefieldset" style="display: block;">';
+        echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
+        echo $pageurl->hidden_params_out();
+        echo '<table id="categoryquestions" style="width: 100%"><tr>';
+        echo "<th style=\"white-space:nowrap;\" class=\"header\" scope=\"col\">$straction</th>";
+
+        echo "<th style=\"white-space:nowrap; text-align: left;\" class=\"header\" scope=\"col\">$strquestionname</th>
+        <th style=\"white-space:nowrap; text-align: right;\" class=\"header\" scope=\"col\">$strtype</th>";
         echo "</tr>\n";
-        if($showquestiontext){
-            echo '<tr><td colspan="3" ' . $textclass . '>';
-            $formatoptions = new stdClass;
-            $formatoptions->noclean = true;
-            $formatoptions->para = false;
-            echo format_text($question->questiontext, $question->questiontextformat,
-                    $formatoptions, $COURSE->id);
-            echo "</td></tr>\n";
-        }
-    }
-    echo "</table>\n";
+        foreach ($questions as $question) {
+            $nameclass = '';
+            $textclass = '';
+            if ($question->hidden) {
+                $nameclass = 'dimmed_text';
+                $textclass = 'dimmed_text';
+            }
+            if ($showquestiontext) {
+                $nameclass .= ' header';
+            }
+            if ($nameclass) {
+                $nameclass = 'class="' . $nameclass . '"';
+            }
+            if ($textclass) {
+                $textclass = 'class="' . $textclass . '"';
+            }
 
-    $paging = print_paging_bar($totalnumber, $page, $perpage, $pageurl, 'qpage', false, true);
-    if ($totalnumber > DEFAULT_QUESTIONS_PER_PAGE) {
-        if ($perpage == DEFAULT_QUESTIONS_PER_PAGE) {
-            $showall = '<a href="edit.php?'.$pageurl->get_query_string(array('qperpage'=>1000)).'">'.get_string('showall', 'moodle', $totalnumber).'</a>';
-        } else {
-            $showall = '<a href="edit.php?'.$pageurl->get_query_string(array('qperpage'=>DEFAULT_QUESTIONS_PER_PAGE)).'">'.get_string('showperpage', 'moodle', DEFAULT_QUESTIONS_PER_PAGE).'</a>';
-        }
-        if ($paging) {
-            $paging = substr($paging, 0, strrpos($paging, '</div>'));
-            $paging .= "<br />$showall</div>";
-        } else {
-            $paging = "<div class='paging'>$showall</div>";
-        }
-    }
-    echo $paging;
+            echo "<tr>\n<td style=\"white-space:nowrap;\" $nameclass>\n";
 
-    if ($caneditall || $canmoveall || $canuseall){
-        echo '<a href="javascript:select_all_in(\'TABLE\',null,\'categoryquestions\');">'.$strselectall.'</a> /'.
-         ' <a href="javascript:deselect_all_in(\'TABLE\',null,\'categoryquestions\');">'.$strselectnone.'</a>';
-        echo '<br />';
-        echo '<strong>&nbsp;'.get_string('withselected', 'quiz').':</strong><br />';
+            $canuseq = question_has_capability_on($question, 'use', $question->category);
+            if (function_exists('module_specific_actions')) {
+                echo module_specific_actions($pageurl, $question->id, $cm->id, $canuseq);
+            }
 
-        if (function_exists('module_specific_buttons')) {
-            echo module_specific_buttons($cm->id);
-        }
-        // print delete and move selected question
-        if ($caneditall) {
-            echo '<input type="submit" name="deleteselected" value="'.$strdelete."\" />\n";
-        }
-        if ($canmoveall && count($addcontexts)) {
-            echo '<input type="submit" name="move" value="'.get_string('moveto', 'quiz')."\" />\n";
-            question_category_select_menu($addcontexts, false, 0, "$category->id,$category->contextid");
-        }
+            // preview
+            if ($canuseq) {
+                $quizorcourseid = $quizid?('&amp;quizid=' . $quizid):('&amp;courseid=' .$COURSE->id);
+                link_to_popup_window('/question/preview.php?id=' . $question->id . $quizorcourseid, 'questionpreview',
+                        "<img src=\"$CFG->pixpath/t/preview.gif\" class=\"iconsmall\" alt=\"$strpreview\" />",
+                        0, 0, $strpreview, QUESTION_PREVIEW_POPUP_OPTIONS);
+            }
+            // edit, hide, delete question, using question capabilities, not quiz capabilieies
+            if (question_has_capability_on($question, 'edit', $question->category) || question_has_capability_on($question, 'move', $question->category)) {
+                echo "<a title=\"$stredit\" href=\"".$questionurl->out(false, array('id'=>$question->id))."\"><img
+                        src=\"$CFG->pixpath/t/edit.gif\" alt=\"$stredit\" /></a>&nbsp;";
+            } elseif (question_has_capability_on($question, 'view', $question->category)){
+                echo "<a title=\"$strview\" href=\"".$questionurl->out(false, array('id'=>$question->id))."\"><img
+                        src=\"$CFG->pixpath/i/info.gif\" alt=\"$strview\" /></a>&nbsp;";
+            }
 
-        if (function_exists('module_specific_controls') && $canuseall) {
-            echo module_specific_controls($totalnumber, $recurse, $category, $cm->id);
+            if (question_has_capability_on($question, 'move', $question->category) && question_has_capability_on($question, 'view', $question->category)) {
+                echo "<a title=\"$strmove\" href=\"".$questionurl->out(false, array('id'=>$question->id, 'movecontext'=>1))."\"><img
+                        src=\"$CFG->pixpath/t/move.gif\" alt=\"$strmove\" /></a>&nbsp;";
+            }
+
+            if (question_has_capability_on($question, 'edit', $question->category)) {
+                // hide-feature
+                if($question->hidden) {
+                    echo "<a title=\"$strrestore\" href=\"edit.php?".$pageurl->get_query_string()."&amp;unhide=$question->id&amp;sesskey=".sesskey()."\"><img
+                            src=\"$CFG->pixpath/t/restore.gif\" alt=\"$strrestore\" /></a>";
+                } else {
+                    echo "<a title=\"$strdelete\" href=\"edit.php?".$pageurl->get_query_string()."&amp;deleteselected=$question->id&amp;q$question->id=1\"><img
+                            src=\"$CFG->pixpath/t/delete.gif\" alt=\"$strdelete\" /></a>";
+                }
+            }
+            if ($caneditall || $canmoveall || $canuseall){
+                echo "&nbsp;<input title=\"$strselect\" type=\"checkbox\" name=\"q$question->id\" value=\"1\" />";
+            }
+            echo "</td>\n";
+
+            echo "<td $nameclass>" . format_string($question->name) . "</td>\n";
+            echo "<td $nameclass style='text-align: right'>\n";
+            print_question_icon($question);
+            echo "</td>\n";
+            echo "</tr>\n";
+            if($showquestiontext){
+                echo '<tr><td colspan="3" ' . $textclass . '>';
+                $formatoptions = new stdClass;
+                $formatoptions->noclean = true;
+                $formatoptions->para = false;
+                echo format_text($question->questiontext, $question->questiontextformat,
+                        $formatoptions, $COURSE->id);
+                echo "</td></tr>\n";
+            }
         }
-    }
-    echo '</fieldset>';
-    echo "</form>\n";
-}
-function question_sort_options($pageurl, $sortorder){
-    global $USER;
-    //sort options
-    $html = "<div class=\"mdl-align questionsortoptions\">";
-    // POST method should only be used for parameters that change data
-    // or if POST method has to be used, the user must be redirected immediately to
-    // non-POSTed page to not break the back button
-    $html .= '<form method="get" action="edit.php">';
-    $html .= '<fieldset class="invisiblefieldset" style="display: block;">';
-    $html .= '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
-    $html .= $pageurl->hidden_params_out(array('qsortorder'));
-    //choose_from_menu concatenates the form name with
-    //"menu" so the label is for menuqsortorder
-    $sortoptions = array('alpha' => get_string("qname", "quiz"),
-                         'typealpha' => get_string("qtypename", "quiz"),
-                         'age' => get_string("age", "quiz"));
-    $a =  choose_from_menu ($sortoptions, 'qsortorder', $sortorder, false, 'this.form.submit();', '0', true);
-    $html .= '<label for="menuqsortorder">'.get_string('sortquestionsbyx', 'quiz', $a).'</label>';
-    $html .=  '<noscript><div><input type="submit" value="'.get_string("sortsubmit", "quiz").'" /></div></noscript>';
-    $html .= '</fieldset>';
-    $html .= "</form>\n";
-    $html .= "</div>\n";
-    return $html;
-}
+        echo "</table>\n";
 
-function question_showbank_actions($pageurl, $cm){
-    global $CFG, $COURSE, $DB;
-    /// Now, check for commands on this page and modify variables as necessary
-    if (optional_param('move', false, PARAM_BOOL) and confirm_sesskey()) { /// Move selected questions to new category
-        $category = required_param('category', PARAM_SEQUENCE);
-        list($tocategoryid, $contextid) = explode(',', $category);
-        if (! $tocategory = $DB->get_record('question_categories', array('id' => $tocategoryid, 'contextid' => $contextid))) {
-            print_error('cannotfindcate', 'question');
+        $paging = print_paging_bar($totalnumber, $page, $perpage, $pageurl, 'qpage', false, true);
+        if ($totalnumber > DEFAULT_QUESTIONS_PER_PAGE) {
+            if ($perpage == DEFAULT_QUESTIONS_PER_PAGE) {
+                $showall = '<a href="edit.php?'.$pageurl->get_query_string(array('qperpage'=>1000)).'">'.get_string('showall', 'moodle', $totalnumber).'</a>';
+            } else {
+                $showall = '<a href="edit.php?'.$pageurl->get_query_string(array('qperpage'=>DEFAULT_QUESTIONS_PER_PAGE)).'">'.get_string('showperpage', 'moodle', DEFAULT_QUESTIONS_PER_PAGE).'</a>';
+            }
+            if ($paging) {
+                $paging = substr($paging, 0, strrpos($paging, '</div>'));
+                $paging .= "<br />$showall</div>";
+            } else {
+                $paging = "<div class='paging'>$showall</div>";
+            }
         }
-        $tocontext = get_context_instance_by_id($contextid);
-        require_capability('moodle/question:add', $tocontext);
-        $rawdata = (array) data_submitted();
-        $questionids = array();
-        foreach ($rawdata as $key => $value) {    // Parse input for question ids
-            if (preg_match('!^q([0-9]+)$!', $key, $matches)) {
-                $key = $matches[1];
-                $questionids[] = $key;
+        echo $paging;
+
+        if ($caneditall || $canmoveall || $canuseall){
+            echo '<a href="javascript:select_all_in(\'TABLE\',null,\'categoryquestions\');">'.$strselectall.'</a> /'.
+             ' <a href="javascript:deselect_all_in(\'TABLE\',null,\'categoryquestions\');">'.$strselectnone.'</a>';
+            echo '<br />';
+            echo '<strong>&nbsp;'.get_string('withselected', 'quiz').':</strong><br />';
+
+            if (function_exists('module_specific_buttons')) {
+                echo module_specific_buttons($cm->id);
+            }
+            // print delete and move selected question
+            if ($caneditall) {
+                echo '<input type="submit" name="deleteselected" value="'.$strdelete."\" />\n";
+            }
+            if ($canmoveall && count($addcontexts)) {
+                echo '<input type="submit" name="move" value="'.get_string('moveto', 'quiz')."\" />\n";
+                question_category_select_menu($addcontexts, false, 0, "$category->id,$category->contextid");
+            }
+
+            if (function_exists('module_specific_controls') && $canuseall) {
+                echo module_specific_controls($totalnumber, $recurse, $category, $cm->id);
             }
         }
-        if ($questionids){
-            list($usql, $params) = $DB->get_in_or_equal($questionids);
-            $sql = "SELECT q.*, c.contextid FROM {question} q, {question_categories} c WHERE q.id $usql AND c.id = q.category";
-            if (!$questions = $DB->get_records_sql($sql, $params)){
-                print_error('questiondoesnotexist', 'question', $pageurl->out());
+        echo '</fieldset>';
+        echo "</form>\n";
+    }
+
+    function display_question_sort_options($pageurl, $sortorder){
+        global $USER;
+        //sort options
+        $html = "<div class=\"mdl-align questionsortoptions\">";
+        // POST method should only be used for parameters that change data
+        // or if POST method has to be used, the user must be redirected immediately to
+        // non-POSTed page to not break the back button
+        $html .= '<form method="get" action="edit.php">';
+        $html .= '<fieldset class="invisiblefieldset" style="display: block;">';
+        $html .= '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
+        $html .= $pageurl->hidden_params_out(array('qsortorder'));
+        //choose_from_menu concatenates the form name with
+        //"menu" so the label is for menuqsortorder
+        $sortoptions = array('alpha' => get_string("qname", "quiz"),
+                             'typealpha' => get_string("qtypename", "quiz"),
+                             'age' => get_string("age", "quiz"));
+        $a =  choose_from_menu($sortoptions, 'qsortorder', $sortorder, false, 'this.form.submit();', '0', true);
+        $html .= '<label for="menuqsortorder">'.get_string('sortquestionsbyx', 'quiz', $a).'</label>';
+        $html .=  '<noscript><div><input type="submit" value="'.get_string("sortsubmit", "quiz").'" /></div></noscript>';
+        $html .= '</fieldset>';
+        $html .= "</form>\n";
+        $html .= "</div>\n";
+        echo $html;
+    }
+
+    function process_actions($pageurl, $cm){
+        global $CFG, $COURSE, $DB;
+        /// Now, check for commands on this page and modify variables as necessary
+        if (optional_param('move', false, PARAM_BOOL) and confirm_sesskey()) { /// Move selected questions to new category
+            $category = required_param('category', PARAM_SEQUENCE);
+            list($tocategoryid, $contextid) = explode(',', $category);
+            if (! $tocategory = $DB->get_record('question_categories', array('id' => $tocategoryid, 'contextid' => $contextid))) {
+                print_error('cannotfindcate', 'question');
             }
-            $checkforfiles = false;
-            foreach ($questions as $question){
-                //check capabilities
-                question_require_capability_on($question, 'move');
-                $fromcontext = get_context_instance_by_id($question->contextid);
-                if (get_filesdir_from_context($fromcontext) != get_filesdir_from_context($tocontext)){
-                    $checkforfiles = true;
+            $tocontext = get_context_instance_by_id($contextid);
+            require_capability('moodle/question:add', $tocontext);
+            $rawdata = (array) data_submitted();
+            $questionids = array();
+            foreach ($rawdata as $key => $value) {    // Parse input for question ids
+                if (preg_match('!^q([0-9]+)$!', $key, $matches)) {
+                    $key = $matches[1];
+                    $questionids[] = $key;
                 }
             }
-            $returnurl = $pageurl->out(false, array('category'=>"$tocategoryid,$contextid"));
-            if (!$checkforfiles){
-                if (!question_move_questions_to_category(implode(',', $questionids), $tocategory->id)) {
-                    print_error('errormovingquestions', 'question', $returnurl, $questionids);
+            if ($questionids){
+                list($usql, $params) = $DB->get_in_or_equal($questionids);
+                $sql = "SELECT q.*, c.contextid FROM {question} q, {question_categories} c WHERE q.id $usql AND c.id = q.category";
+                if (!$questions = $DB->get_records_sql($sql, $params)){
+                    print_error('questiondoesnotexist', 'question', $pageurl->out());
                 }
-                redirect($returnurl);
-            } else {
-                $movecontexturl  = new moodle_url($CFG->wwwroot.'/question/contextmoveq.php',
-                                                array('returnurl' => $returnurl,
-                                                        'ids'=>$questionidlist,
-                                                        'tocatid'=> $tocategoryid));
-                if ($cm){
-                    $movecontexturl->param('cmid', $cm->id);
+                $checkforfiles = false;
+                foreach ($questions as $question){
+                    //check capabilities
+                    question_require_capability_on($question, 'move');
+                    $fromcontext = get_context_instance_by_id($question->contextid);
+                    if (get_filesdir_from_context($fromcontext) != get_filesdir_from_context($tocontext)){
+                        $checkforfiles = true;
+                    }
+                }
+                $returnurl = $pageurl->out(false, array('category'=>"$tocategoryid,$contextid"));
+                if (!$checkforfiles){
+                    if (!question_move_questions_to_category(implode(',', $questionids), $tocategory->id)) {
+                        print_error('errormovingquestions', 'question', $returnurl, $questionids);
+                    }
+                    redirect($returnurl);
                 } else {
-                    $movecontexturl->param('courseid', $COURSE->id);
+                    $movecontexturl  = new moodle_url($CFG->wwwroot.'/question/contextmoveq.php',
+                                                    array('returnurl' => $returnurl,
+                                                            'ids'=>$questionidlist,
+                                                            'tocatid'=> $tocategoryid));
+                    if ($cm){
+                        $movecontexturl->param('cmid', $cm->id);
+                    } else {
+                        $movecontexturl->param('courseid', $COURSE->id);
+                    }
+                    redirect($movecontexturl->out());
                 }
-                redirect($movecontexturl->out());
             }
         }
-    }
 
-    if (optional_param('deleteselected', false, PARAM_BOOL)) { // delete selected questions from the category
-        if (($confirm = optional_param('confirm', '', PARAM_ALPHANUM)) and confirm_sesskey()) { // teacher has already confirmed the action
-            $deleteselected = required_param('deleteselected');
-            if ($confirm == md5($deleteselected)) {
-                if ($questionlist = explode(',', $deleteselected)) {
-                    // for each question either hide it if it is in use or delete it
-                    foreach ($questionlist as $questionid) {
-                        question_require_capability_on($questionid, 'edit');
-                        if ($DB->record_exists('quiz_question_instances', array('question' => $questionid))) {
-                            if (!$DB->set_field('question', 'hidden', 1, array('id' => $questionid))) {
-                                question_require_capability_on($questionid, 'edit');
-                                print_error('cannothidequestion', 'question');
+        if (optional_param('deleteselected', false, PARAM_BOOL)) { // delete selected questions from the category
+            if (($confirm = optional_param('confirm', '', PARAM_ALPHANUM)) and confirm_sesskey()) { // teacher has already confirmed the action
+                $deleteselected = required_param('deleteselected');
+                if ($confirm == md5($deleteselected)) {
+                    if ($questionlist = explode(',', $deleteselected)) {
+                        // for each question either hide it if it is in use or delete it
+                        foreach ($questionlist as $questionid) {
+                            question_require_capability_on($questionid, 'edit');
+                            if ($DB->record_exists('quiz_question_instances', array('question' => $questionid))) {
+                                if (!$DB->set_field('question', 'hidden', 1, array('id' => $questionid))) {
+                                    question_require_capability_on($questionid, 'edit');
+                                    print_error('cannothidequestion', 'question');
+                                }
+                            } else {
+                                delete_question($questionid);
                             }
-                        } else {
-                            delete_question($questionid);
                         }
                     }
+                    redirect($pageurl->out());
+                } else {
+                    print_error('invalidconfirm', 'question');
                 }
-                redirect($pageurl->out());
-            } else {
-                print_error('invalidconfirm', 'question');
             }
         }
-    }
 
-    // Unhide a question
-    if(($unhide = optional_param('unhide', '', PARAM_INT)) and confirm_sesskey()) {
-        question_require_capability_on($unhide, 'edit');
-        if(!$DB->set_field('question', 'hidden', 0, array('id', $unhide))) {
-            print_error('cannotunhidequestion', 'question');
-        }
-        redirect($pageurl->out());
-    }
-}
-
-/**
- * Shows the question bank editing interface.
- *
- * The function also processes a number of actions:
- *
- * Actions affecting the question pool:
- * move           Moves a question to a different category
- * deleteselected Deletes the selected questions from the category
- * Other actions:
- * category      Chooses the category
- * displayoptions Sets display options
- *
- * @param moodle_url $pageurl object representing this pages url.
- */
-function question_showbank($tabname, $contexts, $pageurl, $cm, $page, $perpage, $sortorder, $sortorderdecoded, $cat, $recurse, $showhidden, $showquestiontext){
-    global $COURSE, $DB;
-
-    if (optional_param('deleteselected', false, PARAM_BOOL)){ // teacher still has to confirm
-        // make a list of all the questions that are selected
-        $rawquestions = $_REQUEST; // This code is called by both POST forms and GET links, so cannot use data_submitted.
-        $questionlist = '';  // comma separated list of ids of questions to be deleted
-        $questionnames = ''; // string with names of questions separated by <br /> with
-                             // an asterix in front of those that are in use
-        $inuse = false;      // set to true if at least one of the questions is in use
-        foreach ($rawquestions as $key => $value) {    // Parse input for question ids
-            if (preg_match('!^q([0-9]+)$!', $key, $matches)) {
-                $key = $matches[1];
-                $questionlist .= $key.',';
-                question_require_capability_on($key, 'edit');
-                if ($DB->record_exists('quiz_question_instances', array('question' => $key))) {
-                    $questionnames .= '* ';
-                    $inuse = true;
-                }
-                $questionnames .= $DB->get_field('question', 'name', array('id' => $key)).'<br />';
+        // Unhide a question
+        if(($unhide = optional_param('unhide', '', PARAM_INT)) and confirm_sesskey()) {
+            question_require_capability_on($unhide, 'edit');
+            if(!$DB->set_field('question', 'hidden', 0, array('id', $unhide))) {
+                print_error('cannotunhidequestion', 'question');
             }
-        }
-        if (!$questionlist) { // no questions were selected
             redirect($pageurl->out());
         }
-        $questionlist = rtrim($questionlist, ',');
-
-        // Add an explanation about questions in use
-        if ($inuse) {
-            $questionnames .= '<br />'.get_string('questionsinuse', 'quiz');
-        }
-        notice_yesno(get_string("deletequestionscheck", "quiz", $questionnames),
-                    $pageurl->out_action(array('deleteselected'=>$questionlist, 'confirm'=>md5($questionlist))),
-                    $pageurl->out_action());
-
-        echo '</td></tr>';
-        echo '</table>';
-        print_footer($COURSE);
-        exit;
     }
-
-
-    // starts with category selection form
-    print_box_start('generalbox questionbank');
-    print_heading(get_string('questionbank', 'question'), '', 2);
-    question_category_form($contexts->having_one_edit_tab_cap($tabname), $pageurl, $cat, $recurse, $showhidden, $showquestiontext);
-
-    // continues with list of questions
-    question_list($contexts->having_one_edit_tab_cap($tabname), $pageurl, $cat, isset($cm) ? $cm : null,
-            $recurse, $page, $perpage, $showhidden, $sortorder, $sortorderdecoded, $showquestiontext,
-            $contexts->having_cap('moodle/question:add'));
-
-    print_box_end();
 }
+
 /**
  * Common setup for all pages for editing questions.
  * @param string $edittab code for this edit tab