Skip to content

Commit

Permalink
MDL-35053 questions: question files outside an attempt.
Browse files Browse the repository at this point in the history
Sometimes it is necssary to display parts of a question outside of an
attempt. For example for staff review. When displaying the question, we
need to handle images in the question text. In the past there was a
mechanism for this that could only cope with the question text.

This commit introduces a new method that can handle displaying any
part of the question content.

This commit intentionally does not upgrade the parts of the system that
use the mecanism. That is so that this commit can be used to demonstrate
that backwards-compatibility works. The next commit will upgrade the
callers.
  • Loading branch information
timhunt committed Jul 26, 2013
1 parent bdd045c commit 181393a
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 16 deletions.
93 changes: 77 additions & 16 deletions lib/questionlib.php
Original file line number Diff line number Diff line change
Expand Up @@ -1731,21 +1731,60 @@ function question_rewrite_question_urls($text, $file, $contextid, $component,

/**
* Rewrite the PLUGINFILE urls in the questiontext, when viewing the question
* text outside and attempt (for example, in the question bank listing or in the
* text outside an attempt (for example, in the question bank listing or in the
* quiz statistics report).
*
* @param string $questiontext the question text.
* @param int $contextid the context the text is being displayed in.
* @param string $component component
* @param array $ids other IDs will be used to check file permission
* @param array $options
* @param array $questionid the question id
* @param array $options e.g. forcedownload. Passed to file_rewrite_pluginfile_urls.
* @return string $questiontext with URLs rewritten.
* @deprecated since Moodle 2.6
*/
function question_rewrite_questiontext_preview_urls($questiontext, $contextid,
$component, $questionid, $options=null) {
global $DB;

debugging('question_rewrite_questiontext_preview_urls has been deprecated. ' .
'Please use question_rewrite_question_preview_urls instead', DEBUG_DEVELOPER);
$questioncontextid = $DB->get_field_sql('
SELECT qc.contextid
FROM {question} q
JOIN {question_categories} qc ON qc.id = q.category
WHERE q.id = :id', array('id' => $questionid), MUST_EXIST);

return question_rewrite_question_preview_urls($questiontext, $questioncontextid,
'question', 'questiontext', $contextid, $component, $questionid, $options);
}

/**
* Rewrite the PLUGINFILE urls in part of the content of a question, for use when
* viewing the question outside an attempt (for example, in the question bank
* listing or in the quiz statistics report).
*
* @param string $text the question text.
* @param int $questionid the question id.
* @param int $filecontextid the context id of the question being displayed.
* @param string $filecomponent the component that owns the file area.
* @param string $filearea the file area name.
* @param int|null $itemid the file's itemid
* @param int $previewcontextid the context id where the preview is being displayed.
* @param string $previewcomponent component responsible for displaying the preview.
* @param array $options text and file options ('forcehttps'=>false)
* @return string $questiontext with URLs rewritten.
*/
function question_rewrite_question_preview_urls($text, $questionid,
$filecontextid, $filecomponent, $filearea, $itemid,
$previewcontextid, $previewcomponent, $options = null) {

return file_rewrite_pluginfile_urls($questiontext, 'pluginfile.php', $contextid,
'question', 'questiontext_preview', "$component/$questionid", $options);
$path = "preview/$previewcontextid/$previewcomponent/$questionid";
if ($itemid) {
$path .= '/' . $itemid;
}

return file_rewrite_pluginfile_urls($text, 'pluginfile.php', $filecontextid,
$filecomponent, $filearea, $path, $options);
}

/**
Expand All @@ -1754,10 +1793,13 @@ function question_rewrite_questiontext_preview_urls($questiontext, $contextid,
* @param array $args the remaining file arguments (file path).
* @param bool $forcedownload whether the user must be forced to download the file.
* @param array $options additional options affecting the file serving
* @deprecated since Moodle 2.6.
*/
function question_send_questiontext_file($questionid, $args, $forcedownload, $options) {
global $DB;

debugging('question_send_questiontext_file has been deprecated. It is no longer necessary. ' .
'You can now just use send_stored_file.', DEBUG_DEVELOPER);
$question = $DB->get_record_sql('
SELECT q.id, qc.contextid
FROM {question} q
Expand Down Expand Up @@ -1799,16 +1841,7 @@ function question_send_questiontext_file($questionid, $args, $forcedownload, $op
function question_pluginfile($course, $context, $component, $filearea, $args, $forcedownload, array $options=array()) {
global $DB, $CFG;

if ($filearea === 'questiontext_preview') {
$component = array_shift($args);
$questionid = array_shift($args);

component_callback($component, 'questiontext_preview_pluginfile', array(
$context, $questionid, $args, $forcedownload, $options));

send_file_not_found();
}

// Special case, sending a question bank export.
if ($filearea === 'export') {
list($context, $course, $cm) = get_context_info_array($context->id);
require_login($course, false, $cm);
Expand Down Expand Up @@ -1868,7 +1901,35 @@ function question_pluginfile($course, $context, $component, $filearea, $args, $f
send_file($content, $filename, 0, 0, true, true, $qformat->mime_type());
}

$qubaid = (int)array_shift($args);
// Normal case, a file belonging to a question.
$qubaidorpreview = array_shift($args);

// Two sub-cases: 1. A question being previewed outside an attempt/usage.
if ($qubaidorpreview === 'preview') {
$previewcontextid = (int)array_shift($args);
$previewcomponent = array_shift($args);
$questionid = (int) array_shift($args);
$previewcontext = context_helper::instance_by_id($previewcontextid);

$result = component_callback($previewcomponent, 'question_preview_pluginfile', array(
$previewcontext, $questionid,
$context, $component, $filearea, $args,
$forcedownload, $options), 'newcallbackmissing');

if ($result === 'newcallbackmissing' && $filearea = 'questiontext') {
// Fall back to the legacy callback for backwards compatibility.
debugging("Component {$previewcomponent} does not define the expected " .
"{$previewcomponent}_question_preview_pluginfile callback. Falling back to the deprecated " .
"{$previewcomponent}_questiontext_preview_pluginfile callback.", DEBUG_DEVELOPER);
component_callback($previewcomponent, 'questiontext_preview_pluginfile', array(
$previewcontext, $questionid, $args, $forcedownload, $options));
}

send_file_not_found();
}

// 2. A question being attempted in the normal way.
$qubaid = (int)$qubaidorpreview;
$slot = (int)array_shift($args);

$module = $DB->get_field('question_usages', 'component',
Expand Down
28 changes: 28 additions & 0 deletions question/upgrade.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
This files describes API changes for code that uses the question API.

=== 2.6 ===

1) It is sometimes necessary to display bits of question content without having
and attempt (question_usage) in progress. Two examples of this are the option
in the question bank to display the questiontext, and in the quiz statistics
report, where it displays the question text above the report.

Previously, this display was done using a special method that only worked for
the question text, but which would not work for other parts of the question.
That old mechanism has been deprecated, and there is a new method that you
should use.

To display the question, replace calls to question_rewrite_questiontext_preview_urls
with calls to question_rewrite_question_preview_urls. Because the new function
is more flexibile, you have to pass more arguments.

To perform the necessary permission checks when the file is downloaded, you need
to implement the callback [component name]_question_preview_pluginfile.
(Previously you implemented [component name]_questiontext_preview_pluginfile.)
quiz_statistics_question_preview_pluginfile is an example of what to do.

question_send_questiontext_file has been deprecated. It is no longer necessary.

To ensure you are no longer using or defining any deprecated functions,
search for the regular expression:
question_rewrite_questiontext_preview_urls|_questiontext_preview_pluginfile|question_send_questiontext_file

0 comments on commit 181393a

Please sign in to comment.