Merge branch 'MDL-40313' of git://github.com/timhunt/moodle
authorDan Poltawski <dan@moodle.com>
Tue, 14 Jan 2014 06:21:06 +0000 (14:21 +0800)
committerDan Poltawski <dan@moodle.com>
Tue, 14 Jan 2014 06:21:06 +0000 (14:21 +0800)
13 files changed:
lang/en/question.php
mod/quiz/editlib.php
question/classes/bank/search/category_condition.php [new file with mode: 0755]
question/classes/bank/search/condition.php [new file with mode: 0755]
question/classes/bank/search/hidden_condition.php [new file with mode: 0755]
question/editlib.php
question/upgrade.txt
question/yui/build/moodle-question-searchform/moodle-question-searchform-debug.js [new file with mode: 0644]
question/yui/build/moodle-question-searchform/moodle-question-searchform-min.js [new file with mode: 0644]
question/yui/build/moodle-question-searchform/moodle-question-searchform.js [new file with mode: 0644]
question/yui/src/searchform/build.json [new file with mode: 0644]
question/yui/src/searchform/js/searchform.js [new file with mode: 0644]
question/yui/src/searchform/meta/searchform.json [new file with mode: 0644]

index 092e50f..d2923b1 100644 (file)
@@ -25,6 +25,7 @@
 $string['addmorechoiceblanks'] = 'Blanks for {no} more choices';
 $string['addcategory'] = 'Add category';
 $string['adminreport'] = 'Report on possible problems in your question database.';
+$string['advancedsearchoptions'] = 'Search options';
 $string['answers'] = 'Answers';
 $string['availableq'] = 'Available?';
 $string['badbase'] = 'Bad base before **: {$a}**';
index 6cebed7..13a4277 100644 (file)
@@ -1111,6 +1111,8 @@ class quiz_question_bank_view extends question_bank_view {
     protected $quizhasattempts = false;
     /** @var object the quiz settings. */
     protected $quiz = false;
+    /** @var int The maximum displayed length of the category info. */
+    const MAX_TEXT_LENGTH = 200;
 
     /**
      * Constructor
@@ -1184,16 +1186,15 @@ class quiz_question_bank_view extends question_bank_view {
             return;
         }
 
-        // Display the current category.
-        if (!$category = $this->get_current_category($cat)) {
-            return;
-        }
-        $this->print_category_info($category);
+        $editcontexts = $this->contexts->having_one_edit_tab_cap($tabname);
+        array_unshift($this->searchconditions,
+                new \core_question\bank\search\hidden_condition(!$showhidden));
+        array_unshift($this->searchconditions,
+                new \core_question\bank\search\category_condition($cat, $recurse,
+                        $editcontexts, $this->baseurl, $this->course, self::MAX_TEXT_LENGTH));
 
         echo $OUTPUT->box_start('generalbox questionbank');
-
-        $this->display_category_form($this->contexts->having_one_edit_tab_cap($tabname),
-                $this->baseurl, $cat);
+        $this->display_options_form($showquestiontext);
 
         // Continues with list of questions.
         $this->display_question_list($this->contexts->having_one_edit_tab_cap($tabname),
@@ -1201,12 +1202,20 @@ class quiz_question_bank_view extends question_bank_view {
                 $perpage, $showhidden, $showquestiontext,
                 $this->contexts->having_cap('moodle/question:add'));
 
-        $this->display_options($recurse, $showhidden, $showquestiontext);
         echo $OUTPUT->box_end();
     }
 
+    /**
+     * prints a form to choose categories
+     * @param string $categoryandcontext 'categoryID,contextID'.
+     * @deprecated since Moodle 2.6 MDL-40313.
+     * @see \core_question\bank\search\category_condition
+     * @todo MDL-41978 This will be deleted in Moodle 2.8
+     */
     protected function print_choose_category_message($categoryandcontext) {
         global $OUTPUT;
+        debugging('print_choose_category_message() is deprecated, ' .
+                'please use \core_question\bank\search\category_condition instead.', DEBUG_DEVELOPER);
         echo $OUTPUT->box_start('generalbox questionbank');
         $this->display_category_form($this->contexts->having_one_edit_tab_cap('edit'),
                 $this->baseurl, $categoryandcontext);
@@ -1216,6 +1225,27 @@ class quiz_question_bank_view extends question_bank_view {
         echo $OUTPUT->box_end();
     }
 
+    /**
+     * Display the form with options for which questions are displayed and how they are displayed.
+     * This differs from parent display_options_form only in that it does not have the checkbox to show the question text.
+     * @param bool $showquestiontext Display the text of the question within the list. (Currently ignored)
+     */
+    protected function display_options_form($showquestiontext) {
+        global $PAGE;
+        echo html_writer::start_tag('form', array('method' => 'get',
+                'action' => new moodle_url('/mod/quiz/edit.php'), 'id' => 'displayoptions'));
+        echo html_writer::start_div();
+        foreach ($this->searchconditions as $searchcondition) {
+            echo $searchcondition->display_options($this);
+        }
+        $this->display_advanced_search_form();
+        $go = html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('go')));
+        echo html_writer::tag('noscript', html_writer::tag('div', $go), array('class' => 'inline'));
+        echo html_writer::end_div();
+        echo html_writer::end_tag('form');
+        $PAGE->requires->yui_module('moodle-question-searchform', 'M.question.searchform.init');
+    }
+
     protected function print_category_info($category) {
         $formatoptions = new stdClass();
         $formatoptions->noclean = true;
@@ -1232,6 +1262,7 @@ class quiz_question_bank_view extends question_bank_view {
     }
 
     protected function display_options($recurse, $showhidden, $showquestiontext) {
+        debugging('display_options() is deprecated, see display_options_form() instead.', DEBUG_DEVELOPER);
         echo '<form method="get" action="edit.php" id="displayoptions">';
         echo "<fieldset class='invisiblefieldset'>";
         echo html_writer::input_hidden_params($this->baseurl,
diff --git a/question/classes/bank/search/category_condition.php b/question/classes/bank/search/category_condition.php
new file mode 100755 (executable)
index 0000000..92acd06
--- /dev/null
@@ -0,0 +1,184 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+
+/**
+ * A search class to control from which category questions are listed.
+ *
+ * @package   core_question
+ * @copyright 2013 Ray Morris
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace core_question\bank\search;
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ *  This class controls from which category questions are listed.
+ *
+ * @copyright 2013 Ray Morris
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class category_condition extends condition {
+    /** @var \stdClass The course record. */
+    protected $course;
+
+    /** @var \stdClass The category record. */
+    protected $category;
+
+    /** @var array of contexts. */
+    protected $contexts;
+
+    /** @var bool Whether to include questions from sub-categories. */
+    protected $recurse;
+
+    /** @var string SQL fragment to add to the where clause. */
+    protected $where;
+
+    /** @var array query param used in where. */
+    protected $params;
+
+    /** @var string categoryID,contextID as used with question_bank_view->display(). */
+    protected $cat;
+
+    /** @var int The maximum displayed length of the category info. */
+    protected $maxinfolength;
+
+    /**
+     * Constructor
+     * @param string     $cat           categoryID,contextID as used with question_bank_view->display()
+     * @param bool       $recurse       Whether to include questions from sub-categories
+     * @param array      $contexts      Context objects as used by question_category_options()
+     * @param \moodle_url $baseurl       The URL the form is submitted to
+     * @param \stdClass   $course        Course record
+     * @param integer    $maxinfolength The maximum displayed length of the category info.
+     */
+    public function __construct($cat = null, $recurse = false, $contexts, $baseurl, $course, $maxinfolength = null) {
+        $this->cat = $cat;
+        $this->recurse = $recurse;
+        $this->contexts = $contexts;
+        $this->baseurl = $baseurl;
+        $this->course = $course;
+        $this->init();
+        $this->maxinfolength = $maxinfolength;
+    }
+
+    /**
+     * Initialize the object so it will be ready to return where() and params()
+     */
+    private function init() {
+        global $DB;
+        if (!$this->category = $this->get_current_category($this->cat)) {
+            return;
+        }
+        if ($this->recurse) {
+            $categoryids = question_categorylist($this->category->id);
+        } else {
+            $categoryids = array($this->category->id);
+        }
+        list($catidtest, $this->params) = $DB->get_in_or_equal($categoryids, SQL_PARAMS_NAMED, 'cat');
+        $this->where = 'q.category ' . $catidtest;
+    }
+
+    public function where() {
+        return  $this->where;
+    }
+
+    public function params() {
+        return $this->params;
+    }
+
+    /**
+     * Called by question_bank_view to display the GUI for selecting a category
+     */
+    public function display_options() {
+        $this->display_category_form($this->contexts, $this->baseurl, $this->cat);
+        $this->print_category_info($this->category);
+    }
+
+    /**
+     * Displays the recursion checkbox GUI.
+     * question_bank_view places this within the section that is hidden by default
+     */
+    public function display_options_adv() {
+        echo \html_writer::start_div();
+        echo \html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'recurse',
+                                               'value' => 0, 'id' => 'recurse_off'));
+        echo \html_writer::checkbox('recurse', '1', $this->recurse, get_string('includesubcategories', 'question'),
+                                       array('id' => 'recurse_on', 'class' => 'searchoptions'));
+        echo \html_writer::end_div() . "\n";
+    }
+
+    /**
+     * Display the drop down to select the category.
+     *
+     * @param array $contexts of contexts that can be accessed from here.
+     * @param \moodle_url $pageurl the URL of this page.
+     * @param string $current 'categoryID,contextID'.
+     */
+    protected function display_category_form($contexts, $pageurl, $current) {
+        global $OUTPUT;
+
+        echo \html_writer::start_div('choosecategory');
+        $catmenu = question_category_options($contexts, false, 0, true);
+        $select = new \single_select($this->baseurl, 'category', $catmenu, $current, null, 'catmenu');
+        $select->set_label(get_string('selectacategory', 'question'));
+        echo $OUTPUT->render($select);
+        echo \html_writer::end_div() . "\n";
+    }
+
+    /**
+     * Look up the category record based on cateogry ID and context
+     * @param string $categoryandcontext categoryID,contextID as used with question_bank_view->display()
+     * @return \stdClass The category record
+     */
+    protected function get_current_category($categoryandcontext) {
+        global $DB, $OUTPUT;
+        list($categoryid, $contextid) = explode(',', $categoryandcontext);
+        if (!$categoryid) {
+            $this->print_choose_category_message($categoryandcontext);
+            return false;
+        }
+
+        if (!$category = $DB->get_record('question_categories',
+                array('id' => $categoryid, 'contextid' => $contextid))) {
+            echo $OUTPUT->box_start('generalbox questionbank');
+            echo $OUTPUT->notification('Category not found!');
+            echo $OUTPUT->box_end();
+            return false;
+        }
+
+        return $category;
+    }
+
+    /**
+     * Print the category description
+     * @param stdClass $category the category information form the database.
+     */
+    protected function print_category_info($category) {
+        $formatoptions = new \stdClass();
+        $formatoptions->noclean = true;
+        $formatoptions->overflowdiv = true;
+        echo \html_writer::start_div('boxaligncenter categoryinfo');
+        if (isset($this->maxinfolength)) {
+            echo shorten_text(format_text($category->info, $category->infoformat, $formatoptions, $this->course->id),
+                                     $this->maxinfolength);
+        } else {
+            echo format_text($category->info, $category->infoformat, $formatoptions, $this->course->id);
+        }
+        echo \html_writer::end_div() . "\n";
+    }
+}
diff --git a/question/classes/bank/search/condition.php b/question/classes/bank/search/condition.php
new file mode 100755 (executable)
index 0000000..34c2a5f
--- /dev/null
@@ -0,0 +1,70 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+
+/**
+ * Defines an abstract class for filtering/searching the question bank.
+ *
+ * @package   core_question
+ * @copyright 2013 Ray Morris
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace core_question\bank\search;
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * An abstract class for filtering/searching questions.
+ *
+ * See also {@link question_bank_view::init_search_conditions()}.
+ * @copyright 2013 Ray Morris
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+abstract class condition {
+    /**
+     * Return an SQL fragment to be ANDed into the WHERE clause to filter which questions are shown.
+     * @return string SQL fragment. Must use named parameters.
+     */
+    public abstract function where();
+
+    /**
+     * Return parameters to be bound to the above WHERE clause fragment.
+     * @return array parameter name => value.
+     */
+    public function params() {
+        return array();
+    }
+
+    /**
+     * Display GUI for selecting criteria for this condition. Displayed when Show More is open.
+     *
+     * Compare display_options(), which displays always, whether Show More is open or not.
+     * @return string HTML form fragment
+     */
+    public function display_options_adv() {
+        return;
+    }
+
+    /**
+     * Display GUI for selecting criteria for this condition. Displayed always, whether Show More is open or not.
+     *
+     * Compare display_options_adv(), which displays when Show More is open.
+     * @return string HTML form fragment
+     */
+    public function display_options() {
+        return;
+    }
+}
diff --git a/question/classes/bank/search/hidden_condition.php b/question/classes/bank/search/hidden_condition.php
new file mode 100755 (executable)
index 0000000..247d64d
--- /dev/null
@@ -0,0 +1,68 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+
+/**
+ * A search class to control whether hidden / deleted questions are hidden in the list.
+ *
+ * @package   core_question
+ * @copyright 2013 Ray Morris
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace core_question\bank\search;
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * This class controls whether hidden / deleted questions are hidden in the list.
+ *
+ * @copyright 2013 Ray Morris
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class hidden_condition extends condition {
+    /** @var bool Whether to include old "deleted" questions. */
+    protected $hide;
+
+    /** @var string SQL fragment to add to the where clause. */
+    protected $where;
+
+    /**
+     * Constructor.
+     * @param bool $hide whether to include old "deleted" questions.
+     */
+    public function __construct($hide = true) {
+        $this->hide = $hide;
+        if ($hide) {
+            $this->where = 'q.hidden = 0';
+        }
+    }
+
+    public function where() {
+        return  $this->where;
+    }
+
+    /**
+     * Print HTML to display the "Also show old questions" checkbox
+     */
+    public function display_options_adv() {
+        echo \html_writer::start_div();
+        echo \html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'showhidden',
+                                                   'value' => '0', 'id' => 'showhidden_off'));
+        echo \html_writer::checkbox('showhidden', '1', (! $this->hide), get_string('showhidden', 'question'),
+                                   array('id' => 'showhidden_on', 'class' => 'searchoptions'));
+        echo \html_writer::end_div() . "\n";
+    }
+}
index 3f39887..55c4e3c 100644 (file)
@@ -24,6 +24,8 @@
  */
 
 
+use core_question\bank\search\category_condition;
+
 defined('MOODLE_INTERNAL') || die();
 
 require_once($CFG->libdir . '/questionlib.php');
@@ -898,6 +900,8 @@ class question_bank_view {
     protected $countsql;
     protected $loadsql;
     protected $sqlparams;
+    /** @var array of \core_question\bank\search\condition objects. */
+    protected $searchconditions = array();
 
     /**
      * Constructor
@@ -935,6 +939,21 @@ class question_bank_view {
         $this->init_column_types();
         $this->init_columns($this->wanted_columns(), $this->heading_column());
         $this->init_sort();
+        $this->init_search_conditions($this->contexts, $this->course, $this->cm);
+    }
+
+    /**
+     * Initialize search conditions from plugins
+     * local_*_get_question_bank_search_conditions() must return an array of
+     * \core_question\bank\search\condition objects.
+     */
+    protected function init_search_conditions() {
+        $searchplugins = get_plugin_list_with_function('local', 'get_question_bank_search_conditions');
+        foreach ($searchplugins as $component => $function) {
+            foreach ($function($this) as $searchobject) {
+                $this->add_searchcondition($searchobject);
+            }
+        }
     }
 
     protected function wanted_columns() {
@@ -1141,7 +1160,27 @@ class question_bank_view {
         return $this->baseurl->out(true, $this->sort_to_params($newsort));
     }
 
+    /**
+     * Create the SQL query to retrieve the indicated questions
+     * @param stdClass $category no longer used.
+     * @param bool $recurse no longer used.
+     * @param bool $showhidden no longer used.
+     * @deprecated since Moodle 2.7 MDL-40313.
+     * @see build_query()
+     * @see \core_question\bank\search\condition
+     * @todo MDL-41978 This will be deleted in Moodle 2.8
+     */
     protected function build_query_sql($category, $recurse, $showhidden) {
+        debugging('build_query_sql() is deprecated, please use question_bank_view::build_query() and ' .
+                '\core_question\bank\search\condition classes instead.', DEBUG_DEVELOPER);
+        self::build_query();
+    }
+
+    /**
+     * Create the SQL query to retrieve the indicated questions, based on
+     * \core_question\bank\search\condition filters.
+     */
+    protected function build_query() {
         global $DB;
 
     /// Get the required tables.
@@ -1175,26 +1214,20 @@ class question_bank_view {
 
     /// Build the where clause.
         $tests = array('q.parent = 0');
-
-        if (!$showhidden) {
-            $tests[] = 'q.hidden = 0';
-        }
-
-        if ($recurse) {
-            $categoryids = question_categorylist($category->id);
-        } else {
-            $categoryids = array($category->id);
+        $this->sqlparams = array();
+        foreach ($this->searchconditions as $searchcondition) {
+            if ($searchcondition->where()) {
+                $tests[] = '((' . $searchcondition->where() .'))';
+            }
+            if ($searchcondition->params()) {
+                $this->sqlparams = array_merge($this->sqlparams, $searchcondition->params());
+            }
         }
-        list($catidtest, $params) = $DB->get_in_or_equal($categoryids, SQL_PARAMS_NAMED, 'cat');
-        $tests[] = 'q.category ' . $catidtest;
-        $this->sqlparams = $params;
-
     /// Build the SQL.
         $sql = ' FROM {question} q ' . implode(' ', $joins);
         $sql .= ' WHERE ' . implode(' AND ', $tests);
         $this->countsql = 'SELECT count(1)' . $sql;
         $this->loadsql = 'SELECT ' . implode(', ', $fields) . $sql . ' ORDER BY ' . implode(', ', $sorts);
-        $this->sqlparams = $params;
     }
 
     protected function get_question_count() {
@@ -1248,23 +1281,18 @@ class question_bank_view {
         if ($this->process_actions_needing_ui()) {
             return;
         }
-
+        $editcontexts = $this->contexts->having_one_edit_tab_cap($tabname);
         // Category selection form
         echo $OUTPUT->heading(get_string('questionbank', 'question'), 2);
-
-        $this->display_category_form($this->contexts->having_one_edit_tab_cap($tabname),
-                $this->baseurl, $cat);
-        $this->display_options($recurse, $showhidden, $showquestiontext);
-
-        if (!$category = $this->get_current_category($cat)) {
-            return;
-        }
-        $this->print_category_info($category);
+        array_unshift($this->searchconditions, new \core_question\bank\search\hidden_condition(!$showhidden));
+        array_unshift($this->searchconditions, new \core_question\bank\search\category_condition(
+                $cat, $recurse, $editcontexts, $this->baseurl, $this->course));
+        $this->display_options_form($showquestiontext);
 
         // continues with list of questions
         $this->display_question_list($this->contexts->having_one_edit_tab_cap($tabname),
                 $this->baseurl, $cat, $this->cm,
-                $recurse, $page, $perpage, $showhidden, $showquestiontext,
+                null, $page, $perpage, $showhidden, $showquestiontext,
                 $this->contexts->having_cap('moodle/question:add'));
     }
 
@@ -1293,6 +1321,13 @@ class question_bank_view {
         return $category;
     }
 
+    /**
+     * prints category information
+     * @param stdClass $category the category row from the database.
+     * @deprecated since Moodle 2.7 MDL-40313.
+     * @see \core_question\bank\search\condition
+     * @todo MDL-41978 This will be deleted in Moodle 2.8
+     */
     protected function print_category_info($category) {
         $formatoptions = new stdClass();
         $formatoptions->noclean = true;
@@ -1303,11 +1338,16 @@ class question_bank_view {
     }
 
     /**
-     * prints a form to choose categories
+     * Prints a form to choose categories
+     * @deprecated since Moodle 2.7 MDL-40313.
+     * @see \core_question\bank\search\condition
+     * @todo MDL-41978 This will be deleted in Moodle 2.8
      */
     protected function display_category_form($contexts, $pageurl, $current) {
-        global $CFG, $OUTPUT;
+        global $OUTPUT;
 
+        debugging('display_category_form() is deprecated, please use ' .
+                '\core_question\bank\search\condition instead.', DEBUG_DEVELOPER);
     /// Get all the existing categories now
         echo '<div class="choosecategory">';
         $catmenu = question_category_options($contexts, false, 0, true);
@@ -1318,21 +1358,31 @@ class question_bank_view {
         echo "</div>\n";
     }
 
+    /**
+     * Display the options form.
+     * @param bool $recurse no longer used.
+     * @param bool $showhidden no longer used.
+     * @param bool $showquestiontext whether to show the question text.
+     * @deprecated since Moodle 2.7 MDL-40313.
+     * @see display_options_form
+     * @todo MDL-41978 This will be deleted in Moodle 2.8
+     * @see \core_question\bank\search\condition
+     */
     protected function display_options($recurse, $showhidden, $showquestiontext) {
-        echo '<form method="get" action="edit.php" id="displayoptions">';
-        echo "<fieldset class='invisiblefieldset'>";
-        echo html_writer::input_hidden_params($this->baseurl, array('recurse', 'showhidden', 'qbshowtext'));
-        $this->display_category_form_checkbox('recurse', $recurse, get_string('includesubcategories', 'question'));
-        $this->display_category_form_checkbox('showhidden', $showhidden, get_string('showhidden', 'question'));
-        $this->display_category_form_checkbox('qbshowtext', $showquestiontext, get_string('showquestiontext', 'question'));
-        echo '<noscript><div class="centerpara"><input type="submit" value="'. get_string('go') .'" />';
-        echo '</div></noscript></fieldset></form>';
+        debugging('display_options() is deprecated, please use display_options_form instead.', DEBUG_DEVELOPER);
+        return $this->display_options_form($showquestiontext);
     }
 
     /**
-     * Print a single option checkbox. Used by the preceeding.
+     * Print a single option checkbox.
+     * @deprecated since Moodle 2.7 MDL-40313.
+     * @see \core_question\bank\search\condition
+     * @see html_writer::checkbox
+     * @todo MDL-41978 This will be deleted in Moodle 2.8
      */
     protected function display_category_form_checkbox($name, $value, $label) {
+        debugging('display_category_form_checkbox() is deprecated, ' .
+                'please use \core_question\bank\search\condition instead.', DEBUG_DEVELOPER);
         echo '<div><input type="hidden" id="' . $name . '_off" name="' . $name . '" value="0" />';
         echo '<input type="checkbox" id="' . $name . '_on" name="' . $name . '" value="1"';
         if ($value) {
@@ -1343,6 +1393,52 @@ class question_bank_view {
         echo "</div>\n";
     }
 
+    /**
+     * Display the form with options for which questions are displayed and how they are displayed.
+     * @param bool $showquestiontext Display the text of the question within the list.
+     */
+    protected function display_options_form($showquestiontext) {
+        global $PAGE;
+
+        echo '<form method="get" action="edit.php" id="displayoptions">';
+        echo "<fieldset class='invisiblefieldset'>";
+        echo html_writer::input_hidden_params($this->baseurl, array('recurse', 'showhidden', 'qbshowtext'));
+
+        foreach ($this->searchconditions as $searchcondition) {
+            echo $searchcondition->display_options($this);
+        }
+        $this->display_showtext_checkbox($showquestiontext);
+        $this->display_advanced_search_form();
+        $PAGE->requires->yui_module('moodle-question-searchform', 'M.question.searchform.init');
+        echo '<noscript><div class="centerpara"><input type="submit" value="'. get_string('go') .'" />';
+        echo '</div></noscript></fieldset></form>';
+    }
+
+    /**
+     * Print the "advanced" UI elements for the form to select which questions. Hidden by default.
+     */
+    protected function display_advanced_search_form() {
+        print_collapsible_region_start('', 'advancedsearch', get_string('advancedsearchoptions', 'question'),
+                                               'question_bank_advanced_search');
+        foreach ($this->searchconditions as $searchcondition) {
+            echo $searchcondition->display_options_adv($this);
+        }
+        print_collapsible_region_end();
+    }
+
+    /**
+     * Display the checkbox UI for toggling the display of the question text in the list.
+     * @param bool $showquestiontext the current or default value for whether to display the text.
+     */
+    protected function display_showtext_checkbox($showquestiontext) {
+        echo '<div>';
+        echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'qbshowtext',
+                                               'value' => 0, 'id' => 'qbshowtext_off'));
+        echo html_writer::checkbox('qbshowtext', '1', $showquestiontext, get_string('showquestiontext', 'question'),
+                                       array('id' => 'qbshowtext_on', 'class' => 'searchoptions'));
+        echo "</div>\n";
+    }
+
     protected function create_new_question_form($category, $canadd) {
         global $CFG;
         echo '<div class="createnewquestion">';
@@ -1356,17 +1452,19 @@ class question_bank_view {
     }
 
     /**
-    * 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 bool $showhidden   True if also hidden questions should be displayed
-    * @param bool $showquestiontext whether the text of each question should be shown in the list
-    */
+     * Prints the table of questions in a category with interactions
+     *
+     * @param array      $contexts    Not used!
+     * @param moodle_url $pageurl     The URL to reload this page.
+     * @param string     $categoryandcontext 'categoryID,contextID'.
+     * @param stdClass   $cm          Not used!
+     * @param bool       $recurse     Whether to include subcategories.
+     * @param int        $page        The number of the page to be displayed
+     * @param int        $perpage     Number of questions to show per page
+     * @param bool       $showhidden  whether deleted questions should be displayed.
+     * @param bool       $showquestiontext whether the text of each question should be shown in the list. Deprecated.
+     * @param array      $addcontexts contexts where the user is allowed to add new questions.
+     */
     protected function display_question_list($contexts, $pageurl, $categoryandcontext,
             $cm = null, $recurse=1, $page=0, $perpage=100, $showhidden=false,
             $showquestiontext = false, $addcontexts = array()) {
@@ -1391,7 +1489,7 @@ class question_bank_view {
 
         $this->create_new_question_form($category, $canadd);
 
-        $this->build_query_sql($category, $recurse, $showhidden);
+        $this->build_query();
         $totalnumber = $this->get_question_count();
         if ($totalnumber == 0) {
             return;
@@ -1409,7 +1507,7 @@ class question_bank_view {
         echo '<form method="post" action="edit.php">';
         echo '<fieldset class="invisiblefieldset" style="display: block;">';
         echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
-        echo html_writer::input_hidden_params($pageurl);
+        echo html_writer::input_hidden_params($this->baseurl);
 
         echo '<div class="categoryquestionscontainer">';
         $this->start_table();
@@ -1625,6 +1723,14 @@ class question_bank_view {
             return true;
         }
     }
+
+    /**
+     * Add another search control to this view.
+     * @param \core_question\bank\search\condition $searchcondition the condition to add.
+     */
+    public function add_searchcondition($searchcondition) {
+        $this->searchconditions[] = $searchcondition;
+    }
 }
 
 /**
index 4b4a9ba..c06c3fb 100644 (file)
@@ -1,5 +1,23 @@
 This files describes API changes for code that uses the question API.
 
+=== 2.7 ===
+
+1)  Changes to class question_bank_view:
+
+    Filters, including $recurse and $showhidden, are now implemented as
+    pluggable \core_question\bank\search\condition classes.
+
+    Therefore $recurse and $showhidden are no longer passed to the following functions:
+        protected function display_options [deprecated, use display_options_form()]
+        protected function build_query_sql [deprecated, use build_query()]
+
+    protected function display_category_form() is deprecated. Use \core_question\bank\search\category_condition
+
+    protected function display_category_form_checkbox deprecated use html_writer::checkbox and separate JavaScript
+
+To add filters, local plugins can now implement the function local_[pluginname]_get_question_bank_search_conditions,
+
+
 === 2.6 ===
 
 1) Modules using the question bank MUST now declare their use of it with the xxx_supports()
diff --git a/question/yui/build/moodle-question-searchform/moodle-question-searchform-debug.js b/question/yui/build/moodle-question-searchform/moodle-question-searchform-debug.js
new file mode 100644 (file)
index 0000000..31daad6
Binary files /dev/null and b/question/yui/build/moodle-question-searchform/moodle-question-searchform-debug.js differ
diff --git a/question/yui/build/moodle-question-searchform/moodle-question-searchform-min.js b/question/yui/build/moodle-question-searchform/moodle-question-searchform-min.js
new file mode 100644 (file)
index 0000000..d471408
Binary files /dev/null and b/question/yui/build/moodle-question-searchform/moodle-question-searchform-min.js differ
diff --git a/question/yui/build/moodle-question-searchform/moodle-question-searchform.js b/question/yui/build/moodle-question-searchform/moodle-question-searchform.js
new file mode 100644 (file)
index 0000000..77dbe0d
Binary files /dev/null and b/question/yui/build/moodle-question-searchform/moodle-question-searchform.js differ
diff --git a/question/yui/src/searchform/build.json b/question/yui/src/searchform/build.json
new file mode 100644 (file)
index 0000000..e40e0e9
--- /dev/null
@@ -0,0 +1,10 @@
+{
+  "name": "moodle-question-searchform",
+  "builds": {
+    "moodle-question-searchform": {
+      "jsfiles": [
+        "searchform.js"
+      ]
+    }
+  }
+}
diff --git a/question/yui/src/searchform/js/searchform.js b/question/yui/src/searchform/js/searchform.js
new file mode 100644 (file)
index 0000000..80e8ad8
--- /dev/null
@@ -0,0 +1,17 @@
+
+    var SELECTORS = {
+            OPTIONS: '.searchoptions'
+        },
+        NS;
+
+    M.question = M.question || {};
+    NS = M.question.searchform = {};
+
+    NS.init = function() {
+        Y.delegate('change', this.option_changed, Y.config.doc, SELECTORS.OPTIONS, this);
+    };
+
+    NS.option_changed = function(e) {
+            e.target.getDOMNode().form.submit();
+    };
+
diff --git a/question/yui/src/searchform/meta/searchform.json b/question/yui/src/searchform/meta/searchform.json
new file mode 100644 (file)
index 0000000..e75822b
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "moodle-question-searchform": {
+    "requires": [
+        "base",
+        "node"
+    ]
+  }
+}