MDL-66553 question bank: show tags and idnumbers in question list
This commit is contained in:
+1
-2
@@ -968,8 +968,7 @@ table.quizreviewsummary td.cell {
|
||||
border: 0 none;
|
||||
}
|
||||
|
||||
#categoryquestions th.modifiername .sorters,
|
||||
#categoryquestions th.creatorname .sorters {
|
||||
#categoryquestions th .sorters {
|
||||
font-weight: normal;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ Feature: Adding random questions to a quiz based on category and tags
|
||||
| Tags | foo |
|
||||
And I press "id_submitbutton"
|
||||
And I click on "Manage tags" "link" in the "question 2 name" "table_row"
|
||||
And I set the following fields to these values:
|
||||
And I set the following fields in the "Question tags" "dialogue" to these values:
|
||||
| Tags | bar |
|
||||
And I press "Save changes"
|
||||
And I am on "Course 1" course homepage
|
||||
|
||||
@@ -257,6 +257,42 @@ abstract class column_base {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* If this column needs extra data (e.g. tags) then load that here.
|
||||
*
|
||||
* The extra data should be added to the question object in the array.
|
||||
* Probably a good idea to check that another column has not already
|
||||
* loaded the data you want.
|
||||
*
|
||||
* @param \stdClass[] $questions the questions that will be displayed.
|
||||
*/
|
||||
public function load_additional_data(array $questions) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the tags for each question.
|
||||
*
|
||||
* Helper that can be used from {@link load_additional_data()};
|
||||
*
|
||||
* @param array $questions
|
||||
*/
|
||||
public function load_question_tags(array $questions) {
|
||||
$firstquestion = reset($questions);
|
||||
if (isset($firstquestion->tags)) {
|
||||
// Looks like tags are already loaded, so don't do it again.
|
||||
return;
|
||||
}
|
||||
|
||||
// Load the tags.
|
||||
$tagdata = \core_tag_tag::get_items_tags('core_question', 'question',
|
||||
array_keys($questions));
|
||||
|
||||
// Add them to the question objects.
|
||||
foreach ($tagdata as $questionid => $tags) {
|
||||
$questions[$questionid]->tags = $tags;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Can this column be sorted on? You can return either:
|
||||
* + false for no (the default),
|
||||
@@ -264,7 +300,7 @@ abstract class column_base {
|
||||
* + an array of subnames to sort on as follows
|
||||
* return array(
|
||||
* 'firstname' => array('field' => 'uc.firstname', 'title' => get_string('firstname')),
|
||||
* 'lastname' => array('field' => 'uc.lastname', 'field' => get_string('lastname')),
|
||||
* 'lastname' => array('field' => 'uc.lastname', 'title' => get_string('lastname')),
|
||||
* );
|
||||
* As well as field, and field, you can also add 'revers' => 1 if you want the default sort
|
||||
* order to be DESC.
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
<?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 question bank column showing the question name with idnumber and tags.
|
||||
*
|
||||
* @package core_question
|
||||
* @copyright 2019 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_question\bank;
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
|
||||
/**
|
||||
* A question bank column showing the question name with idnumber and tags.
|
||||
*
|
||||
* @copyright 2019 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class question_name_idnumber_tags_column extends question_name_column {
|
||||
public function get_name() {
|
||||
return 'qnameidnumbertags';
|
||||
}
|
||||
|
||||
protected function display_content($question, $rowclasses) {
|
||||
global $OUTPUT;
|
||||
|
||||
$layoutclasses = 'd-inline-flex flex-nowrap overflow-hidden w-100';
|
||||
$labelfor = $this->label_for($question);
|
||||
if ($labelfor) {
|
||||
echo '<label for="' . $labelfor . '" class="' . $layoutclasses . '">';
|
||||
$closetag = '</label>';
|
||||
} else {
|
||||
echo '<span class="' . $layoutclasses . '">';
|
||||
$closetag = '</span>';
|
||||
}
|
||||
|
||||
// Question name.
|
||||
echo \html_writer::span(format_string($question->name), 'questionname flex-grow-1 flex-shrink-1 text-truncate');
|
||||
|
||||
// Question idnumber.
|
||||
if ($question->idnumber !== null && $question->idnumber !== '') {
|
||||
echo ' ' . \html_writer::span(
|
||||
\html_writer::span(get_string('idnumber', 'question'), 'accesshide') . ' ' .
|
||||
\html_writer::span($question->idnumber, 'badge badge-primary'), 'ml-1');
|
||||
}
|
||||
|
||||
// Question tags.
|
||||
if (!empty($question->tags)) {
|
||||
$tags = \core_tag_tag::get_item_tags('core_question', 'question', $question->id);
|
||||
echo $OUTPUT->tag_list($tags, null, 'd-inline flex-shrink-1 text-truncate ml-1', 0, null, true);
|
||||
}
|
||||
|
||||
echo $closetag; // Computed above to ensure it matches.
|
||||
}
|
||||
|
||||
public function get_required_fields() {
|
||||
$fields = parent::get_required_fields();
|
||||
$fields[] = 'q.idnumber';
|
||||
return $fields;
|
||||
}
|
||||
|
||||
public function is_sortable() {
|
||||
return [
|
||||
'name' => ['field' => 'q.name', 'title' => get_string('questionname', 'question')],
|
||||
'lastname' => ['field' => 'q.idnumber', 'title' => get_string('idnumber', 'question')],
|
||||
];
|
||||
}
|
||||
|
||||
public function load_additional_data(array $questions) {
|
||||
parent::load_additional_data($questions);
|
||||
parent::load_question_tags($questions);
|
||||
}
|
||||
}
|
||||
@@ -177,9 +177,9 @@ class view {
|
||||
|
||||
if (empty($CFG->questionbankcolumns)) {
|
||||
$questionbankcolumns = array('checkbox_column', 'question_type_column',
|
||||
'question_name_column', 'tags_action_column', 'edit_action_column',
|
||||
'copy_action_column', 'preview_action_column', 'delete_action_column',
|
||||
'creator_name_column', 'modifier_name_column');
|
||||
'question_name_idnumber_tags_column', 'tags_action_column', 'edit_action_column',
|
||||
'copy_action_column', 'preview_action_column', 'delete_action_column',
|
||||
'creator_name_column', 'modifier_name_column');
|
||||
} else {
|
||||
$questionbankcolumns = explode(',', $CFG->questionbankcolumns);
|
||||
}
|
||||
@@ -467,9 +467,9 @@ class view {
|
||||
protected function load_page_questions($page, $perpage) {
|
||||
global $DB;
|
||||
$questions = $DB->get_recordset_sql($this->loadsql, $this->sqlparams, $page * $perpage, $perpage);
|
||||
if (!$questions->valid()) {
|
||||
// No questions on this page. Reset to page 0.
|
||||
if (empty($questions)) {
|
||||
$questions->close();
|
||||
// No questions on this page. Reset to page 0.
|
||||
$questions = $DB->get_recordset_sql($this->loadsql, $this->sqlparams, 0, $perpage);
|
||||
}
|
||||
return $questions;
|
||||
@@ -784,7 +784,15 @@ class view {
|
||||
if ($totalnumber == 0) {
|
||||
return;
|
||||
}
|
||||
$questions = $this->load_page_questions($page, $perpage);
|
||||
$questionsrs = $this->load_page_questions($page, $perpage);
|
||||
$questions = [];
|
||||
foreach ($questionsrs as $question) {
|
||||
$questions[$question->id] = $question;
|
||||
}
|
||||
$questionsrs->close();
|
||||
foreach ($this->requiredcolumns as $name => $column) {
|
||||
$column->load_additional_data($questions);
|
||||
}
|
||||
|
||||
echo '<div class="categorypagingbarcontainer">';
|
||||
$pageingurl = new \moodle_url('edit.php', $pageurl->params());
|
||||
@@ -805,7 +813,6 @@ class view {
|
||||
$this->print_table_row($question, $rowcount);
|
||||
$rowcount += 1;
|
||||
}
|
||||
$questions->close();
|
||||
$this->end_table();
|
||||
echo "</div>\n";
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ Feature: A teacher can duplicate questions in the question bank
|
||||
Then I should see "Duplicated question name"
|
||||
And I should see "Test question to be copied"
|
||||
And "Duplicated question name" row "Last modified by" column of "categoryquestions" table should contain "Teacher 1"
|
||||
And "Test question to be copied" row "Created by" column of "categoryquestions" table should contain "Admin User"
|
||||
And "Test question to be copied ID number qid" row "Created by" column of "categoryquestions" table should contain "Admin User"
|
||||
|
||||
@javascript
|
||||
Scenario: Duplicated questions automatically get a new name suggested
|
||||
|
||||
@@ -32,9 +32,11 @@ Feature: A teacher can put questions in categories in the question bank
|
||||
| Name | New Category 1 |
|
||||
| Parent category | Top |
|
||||
| Category info | Created as a test |
|
||||
| ID number | newcatidnumber |
|
||||
And I press "submitbutton"
|
||||
Then I should see "New Category 1 (0)"
|
||||
Then I should see "New Category 1 ID number newcatidnumber (0)"
|
||||
And I should see "Created as a test" in the "New Category 1" "list_item"
|
||||
And "New Category 1 [newcatidnumber]" "option" should exist in the "Parent category" "select"
|
||||
|
||||
Scenario: A question category can be edited
|
||||
When I navigate to "Question bank > Categories" in current page administration
|
||||
|
||||
@@ -35,7 +35,7 @@ Feature: A teacher can put questions with idnumbers in categories with idnumbers
|
||||
# Correction to a unique idnumber for the context.
|
||||
And I set the field "ID number" to "c1unused"
|
||||
And I press "Add category"
|
||||
Then I should see "Sub used category (0)"
|
||||
Then I should see "Sub used category ID number c1unused (0)"
|
||||
And I should see "Created as a test" in the "Sub used category" "list_item"
|
||||
|
||||
Scenario: A question category can be edited and saved without changing the idnumber
|
||||
|
||||
@@ -18,10 +18,10 @@ Feature: The questions in the question bank can be sorted in various ways
|
||||
| contextlevel | reference | name |
|
||||
| Course | C1 | Test questions |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | user | questiontext |
|
||||
| Test questions | essay | A question 1 name | admin | Question 1 text |
|
||||
| Test questions | essay | B question 2 name | teacher1 | Question 2 text |
|
||||
| Test questions | numerical | C question 3 name | teacher1 | Question 3 text |
|
||||
| questioncategory | qtype | name | user | questiontext | idnumber |
|
||||
| Test questions | essay | A question 1 name | admin | Question 1 text | |
|
||||
| Test questions | essay | B question 2 name | teacher1 | Question 2 text | |
|
||||
| Test questions | numerical | C question 3 name | teacher1 | Question 3 text | numidnum |
|
||||
And I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage
|
||||
And I navigate to "Question bank > Questions" in current page administration
|
||||
@@ -30,6 +30,12 @@ Feature: The questions in the question bank can be sorted in various ways
|
||||
Scenario: The questions are sorted by type by default
|
||||
Then "A question 1 name" "checkbox" should appear before "C question 3 name" "checkbox"
|
||||
|
||||
@javascript
|
||||
Scenario: The questions can be sorted by idnumber
|
||||
When I follow "Sort by ID number ascending"
|
||||
Then "C question 3 name" "checkbox" should appear before "A question 1 name" "checkbox"
|
||||
And I should see "numidnum" in the "C question 3 name" "table_row"
|
||||
|
||||
@javascript
|
||||
Scenario: The questions can be sorted in reverse order by type
|
||||
When I follow "Sort by Question type descending"
|
||||
@@ -37,14 +43,14 @@ Feature: The questions in the question bank can be sorted in various ways
|
||||
|
||||
@javascript
|
||||
Scenario: The questions can be sorted by name
|
||||
When I follow "Sort by Question ascending"
|
||||
When I follow "Sort by Question name ascending"
|
||||
Then "A question 1 name" "checkbox" should appear before "B question 2 name" "checkbox"
|
||||
And "B question 2 name" "checkbox" should appear before "C question 3 name" "checkbox"
|
||||
|
||||
@javascript
|
||||
Scenario: The questions can be sorted in reverse order by name
|
||||
When I follow "Sort by Question ascending"
|
||||
And I follow "Sort by Question descending"
|
||||
When I follow "Sort by Question name ascending"
|
||||
And I follow "Sort by Question name descending"
|
||||
Then "C question 3 name" "checkbox" should appear before "B question 2 name" "checkbox"
|
||||
And "B question 2 name" "checkbox" should appear before "A question 1 name" "checkbox"
|
||||
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
This files describes API changes for code that uses the question API.
|
||||
|
||||
=== 3.8 ===
|
||||
|
||||
If you have customised the display of the question bank (using $CFG->questionbankcolumns)
|
||||
then be aware that the default configuration has changed, and you may wish to make
|
||||
equivalent changes in your customised version. The old column question_name_column
|
||||
has been replaced by question_name_idnumber_tags_column. The old question_name_column
|
||||
still exists, so it is safe to continue using it.
|
||||
|
||||
=== 3.7 ===
|
||||
|
||||
The code for the is_valid_number function that was duplicated in the
|
||||
|
||||
Reference in New Issue
Block a user