Merge branch 'MDL-34640' of git://github.com/timhunt/moodle
This commit is contained in:
@@ -206,6 +206,8 @@ class question_engine_data_mapper {
|
||||
public function load_question_attempt_step($stepid) {
|
||||
$records = $this->db->get_recordset_sql("
|
||||
SELECT
|
||||
quba.contextid,
|
||||
COALLESCE(q.qtype, 'missingtype') AS qtype,
|
||||
qas.id AS attemptstepid,
|
||||
qas.questionattemptid,
|
||||
qas.sequencenumber,
|
||||
@@ -216,7 +218,10 @@ SELECT
|
||||
qasd.name,
|
||||
qasd.value
|
||||
|
||||
FROM {question_attempt_steps} qas
|
||||
FROM {question_attempt_steps} qas
|
||||
JOIN {question_attempts} qa ON qa.id = qas.questionattemptid
|
||||
JOIN {question_usages} quba ON quba.id = qa.questionusageid
|
||||
LEFT JOIN {question} q ON q.id = qa.questionid
|
||||
LEFT JOIN {question_attempt_step_data} qasd ON qasd.attemptstepid = qas.id
|
||||
|
||||
WHERE
|
||||
@@ -1199,6 +1204,21 @@ class question_engine_unit_of_work implements question_usage_observer {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The interface implemented by {@link question_file_saver} and {@link question_file_loader}.
|
||||
*
|
||||
* @copyright 2012 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
interface question_response_files {
|
||||
/**
|
||||
* Get the files that were submitted.
|
||||
* @return array of stored_files objects.
|
||||
*/
|
||||
public function get_files();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This class represents the promise to save some files from a particular draft
|
||||
* file area into a particular file area. It is used beause the necessary
|
||||
@@ -1210,7 +1230,7 @@ class question_engine_unit_of_work implements question_usage_observer {
|
||||
* @copyright 2011 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class question_file_saver {
|
||||
class question_file_saver implements question_response_files {
|
||||
/** @var int the id of the draft file area to save files from. */
|
||||
protected $draftitemid;
|
||||
/** @var string the owning component name. */
|
||||
@@ -1290,6 +1310,73 @@ class question_file_saver {
|
||||
file_save_draft_area_files($this->draftitemid, $context->id,
|
||||
$this->component, $this->filearea, $itemid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the files that were submitted.
|
||||
* @return array of stored_files objects.
|
||||
*/
|
||||
public function get_files() {
|
||||
global $USER;
|
||||
|
||||
$fs = get_file_storage();
|
||||
$usercontext = context_user::instance($USER->id);
|
||||
|
||||
return $fs->get_area_files($usercontext->id, 'user', 'draft',
|
||||
$this->draftitemid, 'sortorder, filepath, filename', false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This class is the mirror image of {@link question_file_saver}. It allows
|
||||
* files to be accessed again later (e.g. when re-grading) using that same
|
||||
* API as when doing the original grading.
|
||||
*
|
||||
* @copyright 2012 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class question_file_loader implements question_response_files {
|
||||
/** @var question_attempt_step the step that these files belong to. */
|
||||
protected $step;
|
||||
|
||||
/** @var string the field name for these files - which is used to construct the file area name. */
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* @var string the value to stored in the question_attempt_step_data to
|
||||
* represent these files.
|
||||
*/
|
||||
protected $value;
|
||||
|
||||
/** @var int the context id that the files belong to. */
|
||||
protected $contextid;
|
||||
|
||||
/**
|
||||
* Constuctor.
|
||||
* @param question_attempt_step $step the step that these files belong to.
|
||||
* @param string $name string the field name for these files - which is used to construct the file area name.
|
||||
* @param string $value the value to stored in the question_attempt_step_data to
|
||||
* represent these files.
|
||||
* @param int $contextid the context id that the files belong to.
|
||||
*/
|
||||
public function __construct(question_attempt_step $step, $name, $value, $contextid) {
|
||||
$this->step = $step;
|
||||
$this->name = $name;
|
||||
$this->value = $value;
|
||||
$this->contextid = $contextid;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the files that were submitted.
|
||||
* @return array of stored_files objects.
|
||||
*/
|
||||
public function get_files() {
|
||||
return $this->step->get_qt_files($this->name, $this->contextid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1285,7 +1285,7 @@ class question_attempt {
|
||||
$autosavedsequencenumber = null;
|
||||
while ($record && $record->questionattemptid == $questionattemptid && !is_null($record->attemptstepid)) {
|
||||
$sequencenumber = $record->sequencenumber;
|
||||
$nextstep = question_attempt_step::load_from_records($records, $record->attemptstepid);
|
||||
$nextstep = question_attempt_step::load_from_records($records, $record->attemptstepid, $qa->get_question()->get_type_name());
|
||||
|
||||
if ($sequencenumber < 0) {
|
||||
if (!$autosavedstep) {
|
||||
|
||||
@@ -370,9 +370,11 @@ class question_attempt_step {
|
||||
* Create a question_attempt_step from records loaded from the database.
|
||||
* @param Iterator $records Raw records loaded from the database.
|
||||
* @param int $stepid The id of the records to extract.
|
||||
* @param string $qtype The question type of which this is an attempt.
|
||||
* If not given, each record must include a qtype field.
|
||||
* @return question_attempt_step The newly constructed question_attempt_step.
|
||||
*/
|
||||
public static function load_from_records($records, $attemptstepid) {
|
||||
public static function load_from_records($records, $attemptstepid, $qtype = null) {
|
||||
$currentrec = $records->current();
|
||||
while ($currentrec->attemptstepid != $attemptstepid) {
|
||||
$records->next();
|
||||
@@ -384,6 +386,7 @@ class question_attempt_step {
|
||||
}
|
||||
|
||||
$record = $currentrec;
|
||||
$contextid = null;
|
||||
$data = array();
|
||||
while ($currentrec && $currentrec->attemptstepid == $attemptstepid) {
|
||||
if (!is_null($currentrec->name)) {
|
||||
@@ -403,6 +406,22 @@ class question_attempt_step {
|
||||
if (!is_null($record->fraction)) {
|
||||
$step->fraction = $record->fraction + 0;
|
||||
}
|
||||
|
||||
// This next chunk of code requires getting $contextid and $qtype here.
|
||||
// Somehow, we need to get that information to this point by modifying
|
||||
// all the paths by which this method can be called.
|
||||
// Can we only return files when it's possible? Should there be some kind of warning?
|
||||
if (is_null($qtype)) {
|
||||
$qtype = $record->qtype;
|
||||
}
|
||||
foreach (question_bank::get_qtype($qtype)->response_file_areas() as $area) {
|
||||
if (empty($step->data[$area])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$step->data[$area] = new question_file_loader($step, $area, $step->data[$area], $record->contextid);
|
||||
}
|
||||
|
||||
return $step;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file contains tests for the question_attempt_step class.
|
||||
*
|
||||
* @package moodlecore
|
||||
* @subpackage questionengine
|
||||
* @copyright 2009 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once(dirname(__FILE__) . '/../lib.php');
|
||||
require_once(dirname(__FILE__) . '/helpers.php');
|
||||
|
||||
|
||||
/**
|
||||
* Unit tests for the loading data into the {@link question_attempt_step} class.
|
||||
*
|
||||
* @copyright 2009 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class question_attempt_step_db_test extends data_loading_method_test_base {
|
||||
public function test_load_with_data() {
|
||||
$records = new question_test_recordset(array(
|
||||
array('attemptstepid', 'questionattemptid', 'sequencenumber', 'state', 'fraction', 'timecreated', 'userid', 'name', 'value', 'qtype', 'contextid'),
|
||||
array( 1, 1, 0, 'todo', null, 1256228502, 13, null, null, 'description', 1),
|
||||
array( 2, 1, 1, 'complete', null, 1256228505, 13, 'x', 'a', 'description', 1),
|
||||
array( 2, 1, 1, 'complete', null, 1256228505, 13, '_y', '_b', 'description', 1),
|
||||
array( 2, 1, 1, 'complete', null, 1256228505, 13, '-z', '!c', 'description', 1),
|
||||
array( 2, 1, 1, 'complete', null, 1256228505, 13, '-_t', '!_d', 'description', 1),
|
||||
array( 3, 1, 2, 'gradedright', 1.0, 1256228515, 13, '-finish', '1', 'description', 1),
|
||||
));
|
||||
|
||||
$step = question_attempt_step::load_from_records($records, 2);
|
||||
$this->assertEquals(question_state::$complete, $step->get_state());
|
||||
$this->assertNull($step->get_fraction());
|
||||
$this->assertEquals(1256228505, $step->get_timecreated());
|
||||
$this->assertEquals(13, $step->get_user_id());
|
||||
$this->assertEquals(array('x' => 'a', '_y' => '_b', '-z' => '!c', '-_t' => '!_d'), $step->get_all_data());
|
||||
}
|
||||
|
||||
public function test_load_without_data() {
|
||||
$records = new question_test_recordset(array(
|
||||
array('attemptstepid', 'questionattemptid', 'sequencenumber', 'state', 'fraction', 'timecreated', 'userid', 'name', 'value', 'contextid'),
|
||||
array( 2, 1, 1, 'complete', null, 1256228505, 13, null, null, 1),
|
||||
));
|
||||
|
||||
$step = question_attempt_step::load_from_records($records, 2, 'description');
|
||||
$this->assertEquals(question_state::$complete, $step->get_state());
|
||||
$this->assertNull($step->get_fraction());
|
||||
$this->assertEquals(1256228505, $step->get_timecreated());
|
||||
$this->assertEquals(13, $step->get_user_id());
|
||||
$this->assertEquals(array(), $step->get_all_data());
|
||||
}
|
||||
|
||||
public function test_load_dont_be_too_greedy() {
|
||||
$records = new question_test_recordset(array(
|
||||
array('attemptstepid', 'questionattemptid', 'sequencenumber', 'state', 'fraction', 'timecreated', 'userid', 'name', 'value', 'contextid'),
|
||||
array( 1, 1, 0, 'todo', null, 1256228502, 13, 'x', 'right', 1),
|
||||
array( 2, 2, 0, 'complete', null, 1256228505, 13, 'x', 'wrong', 1),
|
||||
));
|
||||
|
||||
$step = question_attempt_step::load_from_records($records, 1, 'description');
|
||||
$this->assertEquals(array('x' => 'right'), $step->get_all_data());
|
||||
}
|
||||
}
|
||||
@@ -129,56 +129,3 @@ class question_attempt_step_test extends advanced_testcase {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unit tests for the loading data into the {@link question_attempt_step} class.
|
||||
*
|
||||
* @copyright 2009 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class question_attempt_step_db_test extends data_loading_method_test_base {
|
||||
public function test_load_with_data() {
|
||||
$records = new question_test_recordset(array(
|
||||
array('attemptstepid', 'questionattemptid', 'sequencenumber', 'state', 'fraction', 'timecreated', 'userid', 'name', 'value'),
|
||||
array( 1, 1, 0, 'todo', null, 1256228502, 13, null, null),
|
||||
array( 2, 1, 1, 'complete', null, 1256228505, 13, 'x', 'a'),
|
||||
array( 2, 1, 1, 'complete', null, 1256228505, 13, '_y', '_b'),
|
||||
array( 2, 1, 1, 'complete', null, 1256228505, 13, '-z', '!c'),
|
||||
array( 2, 1, 1, 'complete', null, 1256228505, 13, '-_t', '!_d'),
|
||||
array( 3, 1, 2, 'gradedright', 1.0, 1256228515, 13, '-finish', '1'),
|
||||
));
|
||||
|
||||
$step = question_attempt_step::load_from_records($records, 2);
|
||||
$this->assertEquals(question_state::$complete, $step->get_state());
|
||||
$this->assertNull($step->get_fraction());
|
||||
$this->assertEquals(1256228505, $step->get_timecreated());
|
||||
$this->assertEquals(13, $step->get_user_id());
|
||||
$this->assertEquals(array('x' => 'a', '_y' => '_b', '-z' => '!c', '-_t' => '!_d'), $step->get_all_data());
|
||||
}
|
||||
|
||||
public function test_load_without_data() {
|
||||
$records = new question_test_recordset(array(
|
||||
array('attemptstepid', 'questionattemptid', 'sequencenumber', 'state', 'fraction', 'timecreated', 'userid', 'name', 'value'),
|
||||
array( 2, 1, 1, 'complete', null, 1256228505, 13, null, null),
|
||||
));
|
||||
|
||||
$step = question_attempt_step::load_from_records($records, 2);
|
||||
$this->assertEquals(question_state::$complete, $step->get_state());
|
||||
$this->assertNull($step->get_fraction());
|
||||
$this->assertEquals(1256228505, $step->get_timecreated());
|
||||
$this->assertEquals(13, $step->get_user_id());
|
||||
$this->assertEquals(array(), $step->get_all_data());
|
||||
}
|
||||
|
||||
public function test_load_dont_be_too_greedy() {
|
||||
$records = new question_test_recordset(array(
|
||||
array('attemptstepid', 'questionattemptid', 'sequencenumber', 'state', 'fraction', 'timecreated', 'userid', 'name', 'value'),
|
||||
array( 1, 1, 0, 'todo', null, 1256228502, 13, 'x', 'right'),
|
||||
array( 2, 2, 0, 'complete', null, 1256228505, 13, 'x', 'wrong'),
|
||||
));
|
||||
|
||||
$step = question_attempt_step::load_from_records($records, 1);
|
||||
$this->assertEquals(array('x' => 'right'), $step->get_all_data());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user