Improved Question Bank Tags

From MoodleDocs


This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.

The project proposal is here:

The requirements / user stories have been written by the MUA - a copy is included here for clarity

User Stories / Requirements


  • As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.
  • As a teacher, I can filter my questions in courses based on tags.
  • As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.
  • As another teacher in the same course, I have access to the question tags on the questions in that course context.
  • As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)
  • As a teacher, I am able to add/modify/remove tags on questions.
  • As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.
  • As a teacher, I can add a 'random question' to my quiz where the question is taken from a question category (optionally including sub categories) with optional filtering by tags.

Nice to have:

  • Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.
  • As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.
  • As a teacher, I can export/import questions with their tags.
  • As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.
  • As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.


16th Nov 2017

It was discussed that the "random question from a set of questions" is not ideal because it is hard to "manage" the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every question instance using the set. Adding 10 random questions from a set would create 10 individual questions with the list of question ids stored in each (and each would then require updating individually). It also becomes more difficult to prevent a student from seeing the same random question in the same quiz more than once.

Initially "random question from a tag" was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity. So we would have only one random question type, which could be further restricted by specifying a tag. We also need to meet the use case where we want to use questions from different question categories.

This impacts one of the user requirements for the project:

"As a teacher, I can add a 'random question from question set' question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag."

would have to be modified to:

"As a teacher, I can add a 'random question' to my quiz where the question is taken from a question category (optionally including sub categories) with optional filtering by tags."

Note: The MUA requires the ability to pull random questions from multiple categories. It needs to be confirmed if pulling questions from a parent category including sub categories, combined with filtering by a tag will fullfill this requirement.


The requirements listed above can be met by implementing the following changes (which are described in detail further down):

  • Type of thing that can be added to a quiz "Random question from a question category + tag"
  • Enhanced question search allowing search/filter by tag everywhere
  • Allow adding course level tags to questions that exist in a category

Random question from a question category + tag


Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will make this field optional (allow null). The slot type can be determined by the presence or absence of the questionid field.

After these changes there will only be 2 possible slot types (single question, or random question). The random question will require new fields in the quiz_slots table storing questioncategoryid, includesubcats, and tagid.

Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php & repaginate.php in there. We will introduce a new abstract class "mod_quiz\local\structure\slot_type".

The slot_type subclass will be responsible for:

  • Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.
  • Display of UI to configure this slot type (JS and non-JS).

When the slottype is "single" - the \mod_quiz\local\structure\slot_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is "random" the \mod_quiz\local\structure\slot_random class is loaded directly from the quiz (also not a sub-plugin).

Currently there is a "fake" question category for each context. It does not exist in the database, but in places in the UI it is shown as a "fake" question category named top. We need to turn this into a real question category in the database, and enforce some validation rules to prevent modifying it, adding questions to it, or adding new questions categories as siblings of it. This allows us to (for example) add questions from any category in this course that have the label "midterm4" (because all categories will be a child of this top question category). We will need to modify import/restore to auto-create this top level category for backups older than $versionnumber (and enforce the other validation rules).

Other related code improvements

Tim suggests that before making the changes requested here might be the appropriate moment to improve parts of the quiz code, because then implementing the new features would be easier, and could be done using the latest coding practices:

  • There are currently two separate classes classes/structure.php and classes/repaginate.php. There is not good reason for this split. Implementing this proposal may require more new classes. These could all be in a new namespace mod_quiz\local\structure namespace and combine, and the two spearate historical classes could be merged.
  • The Edit quiz page currently uses old YUI javascript, renderers and a custom ajax script mod/quiz/edit_rest.php. This would be better as AMD, Templates and webservices.

DB changes

Update the quiz_slots table to change questionid to allow null.

quiz_slots(id, slot, quizid, page, requireprevious, question, questioncategoryid, subcats, tagid, maxmark)

(Note: please keep all the columns relating to what question gets slected together. That means that maxmark needs to go after them all, or before them all.)

DB structure changes

UI changes

These images are mockups for illustration only and are not to be taken as the final UI design.

Add a random question from a category + tag
Random question from category + tag added to a quiz
A problem

Note: There is currently a limitation in the question bank. There is no categoryid meaning "all the questions in this context", for example "All the questions in this course". In some places in the UI, that is shown as 'Top' under the context name, but it does not really exist - and the UI options (but fortunately not the database) adopt a horrible convention where the argument is $categoryid,$contextid, but if $categoryid is 0 then it means any category in this context. The kind of problem this causes is that you cannot export all the questions in a course.

This is also a problem for this bit of work. We want to be able to add a random question which is "Any question in this course with tag X".

I think the minimal change to allow this is to create in the database a question_category for "Top level of this Course question bank" for each context which has question. I think we can do that with only minimal changes in the question bank (e.g. we don't need to clean up to nasty $categoryid,$contextid params now. However, we would need to ensure that adding this category did not break things.)

Upgrade Steps Required

  • We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).
  • We will need to add columns to the quiz_slots table for questioncategoryid, subcats and tagid. (Quick update, columns will be initially null).
  • We will need to search for all "random" questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar. Although it should not happen we need to allow for the same random question instance being used by 2 quizzes.
  • We will then need to delete all "random" questions.
  • Create a new question category for every context that has questions. Update the existing question categories in that context with parent = 0 to parent = new "Top" question category id

Search for question by tag


We should be able to search for questions by tag from the tag management page. This work has been started on, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).

UI Changes

Search for questions from global tag search

Course level tags for questions


This will be implemented by defining a new "tag area" for "course questions". The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting "course question tags", and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: "moodle/course:viewquestiontags". Changing the course tags for a question will be controlled by a new capability "moodle/course:managequestiontags".

("... the component will be core_course ..." it was not immediately obvious to me that this was 'right'. After some thought I have concluded that is, indeed, the least bad way to represent it. Would it be good to explain this choice?)

UI Changes

Question bank shows course tags icon

Is the long list of icons really good UI. Is this the moment to do what has been done elsewhere in Moodle, and go for an "Edit" menu?

Also, editing question tags is done on the Edit quiestion form. Should we consolidate it, so that all question tag editing is done in one place? (Probably in the proposed new page, not in the Edit question form.)

Edit the course tags for a question