]> git.mjollnir.org Git - moodle.git/commitdiff
question bank: MDL-17302 refactor question bank display code into a class.
authortjhunt <tjhunt>
Wed, 21 Jan 2009 08:49:15 +0000 (08:49 +0000)
committertjhunt <tjhunt>
Wed, 21 Jan 2009 08:49:15 +0000 (08:49 +0000)
Step 3. Start working ot the code to initialise things from a list of columns, and build the corresponding SQL query.

lang/en_utf8/error.php
question/editlib.php

index 2224c09da6ea791a992363a3e26df96b10fea76e..f8a7668471dfe26bc80540dfdff414911f2ccf22 100644 (file)
@@ -441,6 +441,7 @@ $string['unknownrole'] = 'Unknown role \"$a\"';
 $string['unknownuseraction'] = 'Sorry, I do not understand this user action';
 $string['unknownuserselector'] = 'Unknown user selector';
 $string['unknownmodulename'] = 'Unknown module name for form';
+$string['unknownsortcolumn'] = 'Unknown sort column $a';
 $string['unknoworder'] = 'Unknown ordering';
 $string['unknowparamtype'] = 'Unknown parameter type: $a';
 $string['unknowquestiontype'] = 'Unsupported question type $a';
index dace59203614c2d30fc978f2da4ae32ef5f7658a..371d64fe2f4c7c3d64430e74e23497bd5f12da27 100644 (file)
@@ -238,7 +238,8 @@ abstract class question_bank_column_base {
 
     /**
      * @param object $question the row from the $question table, augmented with extra information.
-     * @return string internal name for this column. Used as a CSS class name, and to store information about the current sort.
+     * @return string internal name for this column. Used as a CSS class name,
+     *     and to store information about the current sort. Must match PARAM_ALPHA.
      */
     abstract protected function get_name();
 
@@ -262,6 +263,9 @@ abstract class question_bank_column_base {
      * If to columns try to use the same alias with different joins, you get an error.
      * The only table included by default is the question table, which is aliased to 'q'.
      *
+     * It is importnat that your join simply adds additional data (or NULLs) to the
+     * existing rows of the query. It must not cause additional rows.
+     *
      * @return array 'table_alias' => 'JOIN clause'
      */
     public function get_extra_joins() {
@@ -625,6 +629,12 @@ class question_bank_view {
     protected $quizorcourseid;
     protected $contexts;
     protected $cm;
+    protected $knowncolumntypes;
+    protected $visiblecolumns;
+    protected $requiredcolumns;
+    protected $sort;
+    protected $countsql;
+    protected $loadsql;
 
     public function __construct($contexts, $pageurl, $cm = null) {
         global $CFG, $COURSE;
@@ -647,6 +657,137 @@ class question_bank_view {
         } else {
             $this->editquestionurl->param('courseid', $COURSE->id);
         }
+
+        $this->init_column_types();
+        $this->init_columns(array('checkbox', 'qtype', 'questionname', 'creatorname',
+                'modifiername', 'editaction', 'previewaction', 'moveaction', 'deleteaction'));
+        $this->init_sort();
+    }
+
+    protected function init_columns() {
+        $types = array(
+            new question_bank_checkbox_column($this),
+            new question_bank_question_type_column($this),
+            new question_bank_question_name_column($this),
+            new question_bank_creator_name_column($this),
+            new question_bank_modifier_name_column($this),
+            new question_bank_edit_action_column($this),
+            new question_bank_preview_action_column($this),
+            new question_bank_move_action_column($this),
+            new question_bank_delete_action_column($this),
+        );
+        $this->knowncolumntypes = array();
+        foreach ($columns as $col) {
+            $this->knowncolumntypes[$col->get_name()] = $col;
+        }
+    }
+
+    protected function init_columns($wanted) {
+        $this->visiblecolumns = array();
+        foreach ($wanted as $colname) {
+            if (!isset($this->knowncolumntypes[$colname])) {
+                throw new coding_exception('Unknown column type ' . $colname . ' requested in init columns.');
+            }
+            $this->visiblecolumns[$colname] = $this->knowncolumntypes[$colname];
+        }
+        $this->requiredcolumns = $this->visiblecolumns;
+    }
+
+    protected function init_sort() {
+        $this->init_sort_from_params();
+        if (empty($this->sort)) {
+            $this->sort = $this->default_sort();
+        }
+    }
+
+    /**
+     * Deal with a sort name of the forum columnname, or colname_subsort by
+     * breaking it up, validating the bits that are presend, and returning them.
+     * If there is no subsort, then $subsort is returned as ''.
+     * @return array array($colname, $subsort).
+     */
+    protected function parse_subsort($sort) {
+    /// Do the parsing.
+        if (strpos($sort, '_') !== false) {
+            list($colname, $subsort) = explode('_', $sort, 2);
+        } else {
+            $colname = $sort;
+            $subsort = '';
+        }
+    /// Validate the column name.
+        if (!isset($this->knowncolumntypes[$colname]) || !$this->knowncolumntypes[$colname]->is_sortable()) {
+            $this->baseurl->remove_params('qbs1', 'qbs2', 'qbs3');
+            throw new moodle_exception('unknownsortcolumn', '', $link = $this->baseurl->out(), $colname);
+        }
+    /// Validate the subsort, if present.
+        if ($subsort) {
+            $subsorts = $this->knowncolumntypes[$colname]->is_sortable();
+            if (!is_array($subsorts) || !isset($subsorts[$subsort])) {
+                throw new moodle_exception('unknownsortcolumn', '', $link = $this->baseurl->out(), $sort);
+            }
+        }
+        return array($colname, $subsort);
+    }
+
+    protected function init_sort_from_params() {
+        $this->sort = array();
+        for ($i = 1; $i < 3; $i++) {
+            if (!$sort = optional_param('qbs1', '', PARAM_ALPHAEXT)) {
+                break;
+            }
+            // Work out the appropriate order.
+            $order = 1;
+            if ($sort[0] == '-') {
+                $order = -1;
+                $sort = substr($sort1, 1);
+                if (!$sort) {
+                    break;
+                }
+            }
+            // Deal with subsorts.
+            list($colname, $subsort) = $this->parse_subsort($sort);
+            $this->requiredcolumns[$colname] = $this->knowncolumntypes[$colname];
+            $sort[$sort] = $order;
+        }
+    }
+
+    protected function default_sort() {
+        return array('qtype' => 1, 'questionname' => 1);
+    }
+
+    protected function build_query_sql() {
+    /// Get the required tables.
+        $joins = array();
+        foreach ($this->requiredcolumns as $column) {
+            $extrajoins = $column->get_extra_joins();
+            foreach ($extrajoins as $prefix => $join) {
+                if (isset($joins[$prefix]) && $joins[$prefix] != $join) {
+                    throw new coding_exception('Join ' . $join . ' conflicts with previous join ' . $joins[$prefix]);
+                }
+                $joins[$prefix] = $join;
+            }
+        }
+
+    /// Get the required fields.
+        $fields = array();
+        foreach ($this->visiblecolumns as $column) {
+            $fields += $column->get_required_fields();
+        }
+        $fields = array_unique($fields);
+
+    /// Build the order by clause.
+        $sorts = array();
+        foreach ($this->sort as $sort => $order) {
+            list($colname, $subsort) = $this->parse_subsort($sort);
+            $sorts[] = $this->knowncolumntypes[$colname]->sort_expression($order < 0, $subsort);
+        }
+
+    /// Build the SQL.
+        $sql = ' FROM {question} q ' . implode(' ', $joins);
+        // TODO where clause.
+        $sql .= ' ORDER BY ' . implode(', ', $sorts);
+        $this->countsql = 'SELECT count(1)' . $sql;
+        $this->loadsql = 'SELECT ' . implode(', ', $fields) . $sql;
     }
 
     public function base_url($questionid) {