Skip to content

Commit b957d2f

Browse files
committed
refactor: use file_prepare_draft_area to load response files
It modifies the 'source' field, which other functions might depend on. Closes: #219
1 parent d56d79d commit b957d2f

File tree

3 files changed

+47
-18
lines changed

3 files changed

+47
-18
lines changed

classes/local/attempt_ui/qpy_file_upload.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,17 +136,18 @@ private function render_writable(question_attempt $qa, question_ui_renderer $ren
136136
global $CFG, $PAGE, $USER;
137137
require_once($CFG->libdir . '/form/filemanager.php');
138138

139-
$draftitemid = file_get_unused_draft_itemid();
139+
$combineddraftitemid = $renderer->prepare_combined_draft_area($qa);
140+
140141
$rfs = di::get(response_file_service::class);
141-
$rfs->prepare_draft_area($renderer->options->context->id, $qa, $this->name, $USER->id, $draftitemid);
142+
$splitdraftitemid = $rfs->prepare_split_draft_area($this->name, $USER->id, $combineddraftitemid);
142143

143144
// This is used to tell the qbehaviour what draft areas to save.
144-
$renderer->draftareas[$this->name] = $draftitemid;
145+
$renderer->draftareas[$this->name] = $splitdraftitemid;
145146

146147
$limits = $this->get_limits_in($renderer->options->context);
147148

148149
$fm = new form_filemanager((object)[
149-
'itemid' => $draftitemid,
150+
'itemid' => $splitdraftitemid,
150151
'subdirs' => false,
151152
'context' => $renderer->options->context,
152153
'maxfiles' => $limits->maxfiles,

classes/local/attempt_ui/question_ui_renderer.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ class question_ui_renderer {
6969
*/
7070
public array $mappableduplicatefieldnames = [];
7171

72+
/** @var int $combineddraftitemid */
73+
private int $combineddraftitemid = 0;
74+
7275
/**
7376
* Private constructor. Use {@see question_ui_renderer::render()}.
7477
*
@@ -779,4 +782,27 @@ private function check_for_and_preserve_unknown_options(array $availableoptsinfo
779782
}
780783
return $warnings;
781784
}
785+
786+
/**
787+
* Uses {@see file_prepare_draft_area} (indirectly) to copy all response files to a new draft area.
788+
*
789+
* We do this because {@see file_prepare_draft_area} does some possibly important and hard-to-rewrite magic concerning the
790+
* file source.
791+
*
792+
* This is done lazily because read-only views won't need a draft area, and at most once because the draft area contains all
793+
* field's files. When rendering the upload field, each element calls this method and then copies its own files in to a separate
794+
* draft area.
795+
*
796+
* @param question_attempt $qa
797+
* @return int
798+
*/
799+
public function prepare_combined_draft_area(question_attempt $qa): int {
800+
if (!$this->combineddraftitemid) {
801+
$this->combineddraftitemid = $qa->prepare_response_files_draft_itemid(
802+
constants::QT_VAR_RESPONSE_FILES,
803+
$this->options->context->id
804+
);
805+
}
806+
return $this->combineddraftitemid;
807+
}
782808
}

classes/local/files/response_file_service.php

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@
2121
use core\context;
2222
use file_exception;
2323
use Generator;
24-
use qtype_questionpy\constants;
24+
use moodle_exception;
2525
use qtype_questionpy\local\attempt_ui\qpy_file_upload;
26-
use question_attempt;
2726
use stored_file;
2827
use stored_file_creation_exception;
2928

@@ -176,36 +175,39 @@ public static function filter_combined_files_for_field(array $files, string $fie
176175
}
177176

178177
/**
179-
* Out of the files belonging to a question attempt, copies the ones that belong to the given fieldname to the given draft area.
178+
* From a draft area containing all response files, copies the ones belonging to the given fieldname to a new draft area.
180179
*
181-
* @param int $contextid The attempt's context (not necessarily the question's). See {@see question_display_options::$context}.
182-
* @param question_attempt $qa
183180
* @param string $fieldname
184181
* @param int $userid
185-
* @param int $draftitemid
182+
* @param int $combineddraftitemid
183+
* @return int
184+
* @throws moodle_exception
186185
* @throws coding_exception
187186
* @throws file_exception
188187
* @throws stored_file_creation_exception
189188
*/
190-
public function prepare_draft_area(
191-
int $contextid,
192-
question_attempt $qa,
189+
public function prepare_split_draft_area(
193190
string $fieldname,
194191
int $userid,
195-
int $draftitemid
196-
): void {
192+
int $combineddraftitemid,
193+
): int {
194+
$usercontext = context_user::instance($userid);
195+
$resultdraftid = file_get_unused_draft_itemid();
196+
197197
$fs = get_file_storage();
198-
$allfiles = $qa->get_last_qt_files(constants::QT_VAR_RESPONSE_FILES, $contextid);
198+
$allfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $combineddraftitemid, includedirs: false);
199199

200200
foreach (self::filter_combined_files_for_field($allfiles, $fieldname) as $filename => $file) {
201201
$fs->create_file_from_storedfile([
202202
'component' => 'user',
203203
'filearea' => 'draft',
204-
'itemid' => $draftitemid,
205-
'contextid' => context_user::instance($userid)->id,
204+
'itemid' => $resultdraftid,
205+
'contextid' => $usercontext->id,
206206
'filename' => $filename,
207207
], $file);
208208
}
209+
210+
return $resultdraftid;
209211
}
210212

211213
/**

0 commit comments

Comments
 (0)