Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions classes/local/api/package_api.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,19 @@ public function create_question(?string $currentstate, object $formdata): questi
*
* @param string $questionstate
* @param int $variant variant which should be started (`1` for questions with only one variant)
* @param array|null $attributes
* @return attempt_started the attempt's state and metadata. Note that the attempt state never changes after the
* attempt has been started.
* @throws GuzzleException
* @throws request_error
* @throws moodle_exception
*/
public function start_attempt(string $questionstate, int $variant): attempt_started {
public function start_attempt(string $questionstate, int $variant, ?array $attributes): attempt_started {
$options['multipart'] = $this->transform_to_multipart(
[
'variant' => $variant,
'context' => $this->get_context_id(),
'lms_provided_attributes' => $attributes,
],
$questionstate,
);
Expand All @@ -128,6 +130,7 @@ public function start_attempt(string $questionstate, int $variant): attempt_star
* View a previously created attempt.
*
* @param string $questionstate
* @param array|null $attributes
* @param string $attemptstate the attempt state previously returned from {@see start_attempt()}
* @param string|null $scoringstate the last scoring state if this attempt has already been scored
* @param object|null $response data currently entered by the student
Expand All @@ -136,14 +139,15 @@ public function start_attempt(string $questionstate, int $variant): attempt_star
* @throws request_error
* @throws moodle_exception
*/
public function view_attempt(string $questionstate, string $attemptstate, ?string $scoringstate = null,
public function view_attempt(string $questionstate, ?array $attributes, string $attemptstate, ?string $scoringstate = null,
?object $response = null): attempt {
$options['multipart'] = $this->transform_to_multipart(
[
'attempt_state' => $attemptstate,
'scoring_state' => $scoringstate,
'response' => $response,
'context' => $this->get_context_id(),
'lms_provided_attributes' => $attributes,
],
$questionstate,
);
Expand Down
18 changes: 18 additions & 0 deletions classes/local/api/question_data.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,24 @@ public static function from_question_response(question_response $response): self
);
}

/**
* Creates {@see question_data} from the question id.
*
* @param int $id
* @return ?self
* @throws moodle_exception
*/
public static function from_question_id(int $id): ?self {
global $DB;

$field = $DB->get_field('qtype_questionpy', 'questiondata', ['questionid' => $id]);
if ($field === false) {
return null;
}

return self::from_json($field);
}

/**
* Creates {@see question_data} from JSON.
*
Expand Down
16 changes: 15 additions & 1 deletion question.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
use qtype_questionpy\local\api\attempt;
use qtype_questionpy\local\api\attempt_ui;
use qtype_questionpy\local\api\package_dependency;
use qtype_questionpy\local\api\question_data;
use qtype_questionpy\local\api\scoring_code;
use qtype_questionpy\local\attempt_ui\question_ui_metadata_extractor;
use qtype_questionpy\question_bridge_base;
Expand Down Expand Up @@ -117,7 +118,10 @@ public function start_attempt(question_attempt_step $step, $variant): void {
global $PAGE;

try {
$attempt = $this->api->package($this->packagehash, $this->packagefile)->start_attempt($this->questionstate, $variant);
// Unfortunately, we cannot access attempt data, as the attempt is not stored in the database at this point of time.
$attributes = null;
$attempt = $this->api->package($this->packagehash, $this->packagefile)
->start_attempt($this->questionstate, $variant, $attributes);

$this->attemptstate = $attempt->attemptstate;
$step->set_qt_var(constants::QT_VAR_ATTEMPT_STATE, $attempt->attemptstate);
Expand Down Expand Up @@ -180,9 +184,18 @@ public function apply_attempt_state(question_attempt_step $step) {
/* TODO: This method is also called from question_attempt->regrade and
question_attempt->start_question_based_on, where we shouldn't need to get the UI. */
try {
if ($this->id !== null) {
$questiondata = question_data::from_question_id($this->id);
$requestedattributes = $questiondata->permissions?->attributes;
if ($requestedattributes) {
$attributes = $this->get_bridge()->get_attributes($requestedattributes);
}
}

$attempt = $this->api->package($this->packagehash, $this->packagefile)
->view_attempt(
$this->questionstate,
$attributes ?? null,
$this->attemptstate,
$this->scoringstate,
$lastresponse
Expand Down Expand Up @@ -419,6 +432,7 @@ public function make_behaviour(question_attempt $qa, $preferredbehaviour): quest
/**
* Get the QuestionPy bridge used to retrieve additional information about an attempt.
*
* @throws moodle_exception
* @return question_bridge_base
*/
public function get_bridge(): question_bridge_base {
Expand Down