If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

File storage conversion Quiz and Questions

From MoodleDocs

This page are some notes about what has to be done for MDL-16094.

I would like to review code changes before they are committed for all of this, but I can't see myself having time to do much work on this, only to help someone else do it.

Moodle 2.0


I believe it is the case that each HTML editor on a form has to use a separate HTML editor (otherwise copying files to and from draft areas does not work). However, for question types, I don't think that leads to the best usability.

Similarly, each HTML editor has to have a corresponding ...format field (like questiontext, questiontextformat) even though it is silly (from a usability point of view) for different parts of a question to use different formats.

Serving files

Files belonging to the quiz are served using the quiz_pluginfile() function and other callbacks in mod/quiz/lib.php, as for other modules. There is nothing special here.

Question files

The issue is with files belonging to questions. Doing proper access control before serving these files involves coordinating both the question type, and the activity (e.g. the quiz) that is using the questions.

Question components will be given names like question, or qtype_yyy, where yyy is the name of the particular question type, for example multichoice. And question file areas are requires as well, such as intro, feedback etc.


All questions belong to a particular context, via the link mdl_question.category ->, mdl_question_categories.contextid -> links. This is the context id that should be used for files belonging to that question.

Therefore, the URL for serving a file belonging to a question will look like one of these examples:


The $attemptid here is the id from the row of the mdl_question_attempts table for the quiz (or whatever) attempt that is using the question. In the question code, where we are outputting a question, the $attemptid and $questionid are normally available from the $state variable as $state->attempt and $state->question. Currently, question/preview.php does not store things in the database. It just uses the session, and a fake $attemptid of 0. That is not a problem (for us here. It is a problem in other ways.)

Therefore in pluginfile.php, we need code for any system, course category, course or module context, sends requests for files in a question_... or qtype_... file area to a question_pluginfile() function in lib/questionlib.php.

Next, we need to get some information from the thing (e.g. quiz) that the attempt belongs to. To identify the 'thing':

  • If $attemptid is 0, then thing is core_question_preview
  • Otherwise, load the row from mdl_question_attempts, and looks at the modulename field. The will contain something like 'quiz' which is the thing.

Next question_pluginfile calls a callback:

list($question, $state, $options) =
         thing_check_file_access($attemptid, $questionid, $context);

This does some basic access checks (For quiz, it will to something similar to the top of attempt.php and review.php, for core preview it just does some capability checks like at the top of question/preview.php.) If the user is not allowed to see the file, based on the quick check, a lot of nulls are returned. If access is allowed, $question, $state, $options are returned. These are the things that would be passed to print_question.

Finally, we call

 $qtype->check_file_access($question, $state, $options, $filearea, $itemid);

which returns true if the file can be served, or false if not. This will contain logic similar to that in ->print_question_formulation_and_controls to determine whether the file should be displayed. It should also check that $itemid for this file area belongs to this question.

File areas for the quiz

I have written what follows with reference to database columns, with secondary mention of the editing forms where the value is edited. That determines what itemid should be used with each file area (the id of the row from that table) but for clarity, for each file area I think we need, I have added a notation that looks like {contextid, area_name, itemid} to make it clear what the file areas are.

Quiz database structure

  • We need a file area for quiz.intro. {$quizcontextid, quiz_intro, ???}
  • We need a file area for quiz_feedback.feedbacktext. (The overall feedback on the quiz settings form.) If it is possible to do easily, we should replace the overall feedback boxes with HTML editors (the boxes currently accept HTML input into text fields, which is functionally complete, but sucky). {$quizcontextid, quiz_feedback,}
  • We need to add a feedbacktextformat column, if it has not already been done.
  • Ideally, access to overall feedback files should be controlled by the same logic as whether the feedback itself is displayed. However, I think it would be acceptable to release Moodle 2.0 without this. Just leave an open tracker issue assigned to me, and I can implement that check later.

No other quiz_... tables have files associated with any columns.

File areas for questions

Question database structure

There are no fields in the 'question engine' tables that have files. Except:

  • There should be a question_sessions.manualcommentformat column. (But manual comment should not support attached files.)

All the issues are in the 'question bank' part, which means the core question bank, and the all the question type plugins.

Core question bank

There is a context associated with each question, as explained in the Serving files section.

  • I think that (which is HTML) should not have files. However, we need a question_categories.infoformat field.
  • We need file areas for question.questiontext and question.generalfeedback. We also need to add the missing question.generalfeedbackformat field. {$questioncontextid, question_text,} {$questioncontextid, question_generalfeedback,}
  • We need file areas, and ...format columns for question_answers.answer and (Depending on the question type, question_answers.answer may be HTML, or it may not, but where it is not, we will force the ...format value to something appropriate. Anyway, as an example, answers are HTML for multichoice and truefalse, but not for numerical or shortanswer.) {$questioncontextid, question_answer,} {$questioncontextid, question_answer_feedback,}
  • We must get rid of the question.image column. We need an upgrade to:
    1. Do a database upgrade that appends an img tag to the questiontext, if the img column is not empty;
    2. and copy the file into the right file area;
    3. then drop the question.image column;
    4. remove that field from all editing forms;
    5. remove the places where the image is displayed.

Note that all the above changes require changes to the question editing form for all question types, but hopefully that can mostly be done in the form base class.

  • Question import needs to use the file-picker.
  • Question export should be changed to put the files in an appropriate file area. I am not sure what the best file area is right now, but probably somewhere in the user context. MDL-15573

Question types

Question types where nothing needs to be done

These only use the core question tables, or do not need files associated with their own tables.

  • Description
  • Essay
  • Missing type
  • Numerical

The new 2,0 number and unit grading use a new table question_numerical_options where the instructions field is HTML which could include images. This table is also used by calculated and calculated simple.--Pierre Pichet 08:11, 23 May 2010 (UTC)

  • Random
  • Random short-answer matching
  • Short answer
  • True-false


  • question_match_sub.questiontext needs a ...format column and a file area. (answertext does not. It is displayed in a select menu.) {$questioncontextid, qtype_match_stem,}

Multiple choice

  • correctfeedback, partiallycorrectfeedback and incorrectfeedback all need ...format columns and a file area.

{$questioncontextid, qtype_multichoice_correctfeedback,} {$questioncontextid, qtype_multichoice_partiallycorrectfeedback,} {$questioncontextid, qtype_multichoice_incorrectfeedback,}

  • The choice entry boxes on the editing form should be changed to HTML editors.

Question types I am not really sure about

  • Calculated* - I don't really know what Pierre is doing here. I need to get my head round it.

So here is the status of calculated in 2.0.

The calculatedsimple is just a regular calculated that can be edited in a one page because it is not using the shared category datasets. In both on them there is no new field with image to store other than question text and answer feedback.

The answer field is just math formula i.e. plain text.

The multichoice calculated is a multichoice where calculated math formula can be inserted {=...} so the requirements are the same as regular multichoice.

Regular calculated and multichoice calculated used the new table question_calculated_options although regular calculated only used the synchronize field, multichoice calculated using the other fields. I prefer to use only one new table and the fields for multichoice calculated are a copy of most of the multichoice ones.

This is a new table in 2.0 so no file conversion.

Pierre Pichet 08:01, 23 May 2010 (UTC)

  • Multi-answer - probably does not need any other file areas, but the code may need fixing a bit.

So here is the status of Multi-answer in 2.0.

Multi-answer code is the same has in 1.9, the improvements has been on the data validation in the edit_form with additional warnings when the user modify the number or question type in the question text peculiarly when the question has attempts stored.

I am working on the lang strings.

Pierre Pichet 08:01, 23 May 2010 (UTC)

For the future

As in, Moodle 2.1 or later.

  • Support files in student responses and manual comments.

See also