MDL-16505 Removing qtype_datasetdependent questiontype
This commit is contained in:
+1
-1
@@ -41,7 +41,7 @@ class question_dataset_dependent_definitions_form extends moodleform {
|
||||
$mandatorydatasets += $this->qtypeobj->find_dataset_names($answer->answer);
|
||||
}
|
||||
}else{
|
||||
foreach ($SESSION->datasetdependent->questionform->answers as $answer){
|
||||
foreach ($SESSION->calculated->questionform->answers as $answer){
|
||||
$mandatorydatasets += $this->qtypeobj->find_dataset_names($answer);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -34,7 +34,7 @@ class question_dataset_dependent_items_form extends moodleform {
|
||||
$this->qtypeobj =& $QTYPES[$this->question->qtype];
|
||||
//get the dataset defintions for this question
|
||||
if (empty($question->id)) {
|
||||
$this->datasetdefs = $this->qtypeobj->get_dataset_definitions($question->id, $SESSION->datasetdependent->definitionform->dataset);
|
||||
$this->datasetdefs = $this->qtypeobj->get_dataset_definitions($question->id, $SESSION->calculated->definitionform->dataset);
|
||||
} else {
|
||||
if (empty($question->options)) {
|
||||
$this->get_question_options($question);
|
||||
@@ -6,13 +6,16 @@
|
||||
|
||||
/// QUESTION TYPE CLASS //////////////////
|
||||
|
||||
require_once("$CFG->dirroot/question/type/datasetdependent/abstractqtype.php");
|
||||
define("LITERAL", "1");
|
||||
define("FILE", "2");
|
||||
define("LINK", "3");
|
||||
|
||||
|
||||
class question_calculated_qtype extends question_dataset_dependent_questiontype {
|
||||
class question_calculated_qtype extends default_questiontype {
|
||||
|
||||
// Used by the function custom_generator_tools:
|
||||
var $calcgenerateidhasbeenadded = false;
|
||||
public $virtualqtype = false;
|
||||
|
||||
function name() {
|
||||
return 'calculated';
|
||||
@@ -285,6 +288,57 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype
|
||||
}
|
||||
}
|
||||
|
||||
function restore_session_and_responses(&$question, &$state) {
|
||||
if (!ereg('^dataset([0-9]+)[^-]*-(.*)$',
|
||||
$state->responses[''], $regs)) {
|
||||
notify ("Wrongly formatted raw response answer " .
|
||||
"{$state->responses['']}! Could not restore session for " .
|
||||
" question #{$question->id}.");
|
||||
$state->options->datasetitem = 1;
|
||||
$state->options->dataset = array();
|
||||
$state->responses = array('' => '');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Restore the chosen dataset
|
||||
$state->options->datasetitem = $regs[1];
|
||||
$state->options->dataset =
|
||||
$this->pick_question_dataset($question,$state->options->datasetitem);
|
||||
$state->responses = array('' => $regs[2]);
|
||||
return true;
|
||||
}
|
||||
|
||||
function create_session_and_responses(&$question, &$state, $cmoptions, $attempt) {
|
||||
// Find out how many datasets are available
|
||||
global $CFG, $DB;
|
||||
if(!$maxnumber = (int)$DB->get_field_sql(
|
||||
"SELECT MIN(a.itemcount)
|
||||
FROM {question_dataset_definitions} a,
|
||||
{question_datasets} b
|
||||
WHERE b.question = ?
|
||||
AND a.id = b.datasetdefinition", array($question->id))) {
|
||||
print_error('cannotgetdsforquestion', 'question', '', $question->id);
|
||||
}
|
||||
|
||||
// Choose a random dataset
|
||||
$state->options->datasetitem = rand(1, $maxnumber);
|
||||
$state->options->dataset =
|
||||
$this->pick_question_dataset($question,$state->options->datasetitem);
|
||||
$state->responses = array('' => '');
|
||||
return true;
|
||||
}
|
||||
|
||||
function save_session_and_responses(&$question, &$state) {
|
||||
global $DB;
|
||||
$responses = 'dataset'.$state->options->datasetitem.'-'.
|
||||
$state->responses[''];
|
||||
// Set the legacy answer field
|
||||
if (!$DB->set_field('question_states', 'answer', $responses, array('id'=> $state->id))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function create_runtime_question($question, $form) {
|
||||
$question = parent::create_runtime_question($question, $form);
|
||||
$question->options->answers = array();
|
||||
@@ -345,7 +399,216 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function finished_edit_wizard(&$form) {
|
||||
return isset($form->backtoquiz);
|
||||
}
|
||||
// This gets called by editquestion.php after the standard question is saved
|
||||
function print_next_wizard_page(&$question, &$form, $course) {
|
||||
global $CFG, $USER, $SESSION, $COURSE;
|
||||
|
||||
// Catch invalid navigation & reloads
|
||||
if (empty($question->id) && empty($SESSION->calculated)) {
|
||||
redirect('edit.php?courseid='.$COURSE->id, 'The page you are loading has expired.', 3);
|
||||
}
|
||||
|
||||
// See where we're coming from
|
||||
switch($form->wizardpage) {
|
||||
case 'question':
|
||||
require("$CFG->dirroot/question/type/calculated/datasetdefinitions.php");
|
||||
break;
|
||||
case 'datasetdefinitions':
|
||||
case 'datasetitems':
|
||||
require("$CFG->dirroot/question/type/calculated/datasetitems.php");
|
||||
break;
|
||||
default:
|
||||
print_error('invalidwizardpage', 'question');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// This gets called by question2.php after the standard question is saved
|
||||
function &next_wizard_form($submiturl, $question, $wizardnow){
|
||||
global $CFG, $SESSION, $COURSE;
|
||||
|
||||
// Catch invalid navigation & reloads
|
||||
if (empty($question->id) && empty($SESSION->calculated)) {
|
||||
redirect('edit.php?courseid='.$COURSE->id, 'The page you are loading has expired. Cannot get next wizard form.', 3);
|
||||
}
|
||||
if (empty($question->id)){
|
||||
$question =& $SESSION->calculated->questionform;
|
||||
}
|
||||
|
||||
// See where we're coming from
|
||||
switch($wizardnow) {
|
||||
case 'datasetdefinitions':
|
||||
require("$CFG->dirroot/question/type/calculated/datasetdefinitions_form.php");
|
||||
$mform =& new question_dataset_dependent_definitions_form("$submiturl?wizardnow=datasetdefinitions", $question);
|
||||
break;
|
||||
case 'datasetitems':
|
||||
require("$CFG->dirroot/question/type/calculated/datasetitems_form.php");
|
||||
$regenerate = optional_param('forceregeneration', 0, PARAM_BOOL);
|
||||
$mform =& new question_dataset_dependent_items_form("$submiturl?wizardnow=datasetitems", $question, $regenerate);
|
||||
break;
|
||||
default:
|
||||
print_error('invalidwizardpage', 'question');
|
||||
break;
|
||||
}
|
||||
|
||||
return $mform;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should be overriden if you want to include a special heading or some other
|
||||
* html on a question editing page besides the question editing form.
|
||||
*
|
||||
* @param question_edit_form $mform a child of question_edit_form
|
||||
* @param object $question
|
||||
* @param string $wizardnow is '' for first page.
|
||||
*/
|
||||
function display_question_editing_page(&$mform, $question, $wizardnow){
|
||||
switch ($wizardnow){
|
||||
case '':
|
||||
//on first page default display is fine
|
||||
parent::display_question_editing_page($mform, $question, $wizardnow);
|
||||
return;
|
||||
break;
|
||||
case 'datasetdefinitions':
|
||||
print_heading_with_help(get_string("choosedatasetproperties", "quiz"), "questiondatasets", "quiz");
|
||||
break;
|
||||
case 'datasetitems':
|
||||
print_heading_with_help(get_string("editdatasets", "quiz"), 'questiondatasets', "quiz");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
$mform->display();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method prepare the $datasets in a format similar to dadatesetdefinitions_form.php
|
||||
* so that they can be saved
|
||||
* using the function save_dataset_definitions($form)
|
||||
* when creating a new calculated question or
|
||||
* whenediting an already existing calculated question
|
||||
* or by function save_as_new_dataset_definitions($form, $initialid)
|
||||
* when saving as new an already existing calculated question
|
||||
*
|
||||
* @param object $form
|
||||
* @param int $questionfromid default = '0'
|
||||
*/
|
||||
function preparedatasets(&$form , $questionfromid='0'){
|
||||
// the dataset names present in the edit_question_form and edit_calculated_form are retrieved
|
||||
$possibledatasets = $this->find_dataset_names($form->questiontext);
|
||||
$mandatorydatasets = array();
|
||||
foreach ($form->answers as $answer) {
|
||||
$mandatorydatasets += $this->find_dataset_names($answer);
|
||||
}
|
||||
// if there are identical datasetdefs already saved in the original question.
|
||||
// either when editing a question or saving as new
|
||||
// they are retrieved using $questionfromid
|
||||
if ($questionfromid!='0'){
|
||||
$form->id = $questionfromid ;
|
||||
}
|
||||
$datasets = array();
|
||||
$key = 0 ;
|
||||
// always prepare the mandatorydatasets present in the answers
|
||||
// the $options are not used here
|
||||
foreach ($mandatorydatasets as $datasetname) {
|
||||
if (!isset($datasets[$datasetname])) {
|
||||
list($options, $selected) =
|
||||
$this->dataset_options($form, $datasetname);
|
||||
$datasets[$datasetname]='';
|
||||
$form->dataset[$key]=$selected ;
|
||||
$key++;
|
||||
}
|
||||
}
|
||||
// do not prepare possibledatasets when creating a question
|
||||
// they will defined and stored with datasetdefinitions_form.php
|
||||
// the $options are not used here
|
||||
if ($questionfromid!='0'){
|
||||
|
||||
foreach ($possibledatasets as $datasetname) {
|
||||
if (!isset($datasets[$datasetname])) {
|
||||
list($options, $selected) =
|
||||
$this->dataset_options($form, $datasetname,false);
|
||||
$datasets[$datasetname]='';
|
||||
$form->dataset[$key]=$selected ;
|
||||
$key++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $datasets ;
|
||||
}
|
||||
|
||||
/**
|
||||
* this version save the available data at the different steps of the question editing process
|
||||
* without using global $SESSION as storage between steps
|
||||
* at the first step $wizardnow = 'question'
|
||||
* when creating a new question
|
||||
* when modifying a question
|
||||
* when copying as a new question
|
||||
* the general parameters and answers are saved using parent::save_question
|
||||
* then the datasets are prepared and saved
|
||||
* at the second step $wizardnow = 'datasetdefinitions'
|
||||
* the datadefs final type are defined as private, category or not a datadef
|
||||
* at the third step $wizardnow = 'datasetitems'
|
||||
* the datadefs parameters and the data items are created or defined
|
||||
*
|
||||
* @param object question
|
||||
* @param object $form
|
||||
* @param int $course
|
||||
* @param PARAM_ALPHA $wizardnow should be added as we are coming from question2.php
|
||||
*/
|
||||
function save_question($question, $form, $course) {
|
||||
$wizardnow = optional_param('wizardnow', '', PARAM_ALPHA);
|
||||
$id = optional_param('id', 0, PARAM_INT); // question id
|
||||
// in case 'question'
|
||||
// for a new question $form->id is empty
|
||||
// when saving as new question
|
||||
// $question->id = 0, $form is $data from question2.php
|
||||
// and $data->makecopy is defined as $data->id is the initial question id
|
||||
// edit case. If it is a new question we don't necessarily need to
|
||||
// return a valid question object
|
||||
|
||||
// See where we're coming from
|
||||
switch($wizardnow) {
|
||||
case '' :
|
||||
case 'question': // coming from the first page, creating the second
|
||||
if (empty($form->id)) { // for a new question $form->id is empty
|
||||
$question = parent::save_question($question, $form, $course);
|
||||
//prepare the datasets using default $questionfromid
|
||||
$this->preparedatasets($form);
|
||||
$form->id = $question->id;
|
||||
$this->save_dataset_definitions($form);
|
||||
} else if (!empty($form->makecopy)){
|
||||
$questionfromid = $form->id ;
|
||||
$question = parent::save_question($question, $form, $course);
|
||||
//prepare the datasets
|
||||
$this->preparedatasets($form,$questionfromid);
|
||||
$form->id = $question->id;
|
||||
$this->save_as_new_dataset_definitions($form,$questionfromid );
|
||||
} else {// editing a question
|
||||
$question = parent::save_question($question, $form, $course);
|
||||
//prepare the datasets
|
||||
$this->preparedatasets($form,$question->id);
|
||||
$form->id = $question->id;
|
||||
$this->save_dataset_definitions($form);
|
||||
}
|
||||
break;
|
||||
case 'datasetdefinitions':
|
||||
|
||||
$this->save_dataset_definitions($form);
|
||||
break;
|
||||
case 'datasetitems':
|
||||
$this->save_dataset_items($question, $form);
|
||||
break;
|
||||
default:
|
||||
print_error('invalidwizardpage', 'question');
|
||||
break;
|
||||
}
|
||||
return $question;
|
||||
}
|
||||
/**
|
||||
* Deletes question from the question-type specific tables
|
||||
*
|
||||
@@ -379,10 +642,10 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype
|
||||
$numericalquestion = fullclone($question);
|
||||
foreach ($numericalquestion->options->answers as $key => $answer) {
|
||||
$answer = fullclone($numericalquestion->options->answers[$key]);
|
||||
$numericalquestion->options->answers[$key]->answer = $this->substitute_variables($answer->answer,
|
||||
$numericalquestion->options->answers[$key]->answer = $this->substitute_variables_and_eval($answer->answer,
|
||||
$state->options->dataset);
|
||||
}
|
||||
$numericalquestion->questiontext = parent::substitute_variables(
|
||||
$numericalquestion->questiontext = $this->substitute_variables(
|
||||
$numericalquestion->questiontext, $state->options->dataset);
|
||||
//evaluate the equations i.e {=5+4)
|
||||
$qtext = "";
|
||||
@@ -411,7 +674,7 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype
|
||||
$numericalquestion = fullclone($question);
|
||||
foreach ($numericalquestion->options->answers as $key => $answer) {
|
||||
$answer = $numericalquestion->options->answers[$key]->answer; // for PHP 4.x
|
||||
$numericalquestion->options->answers[$key]->answer = $this->substitute_variables($answer,
|
||||
$numericalquestion->options->answers[$key]->answer = $this->substitute_variables_and_eval($answer,
|
||||
$state->options->dataset);
|
||||
}
|
||||
$virtualqtype = $this->get_virtual_qtype();
|
||||
@@ -434,7 +697,7 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype
|
||||
}
|
||||
foreach ($numericalquestion->options->answers as $key => $answer) {
|
||||
$answer = &$numericalquestion->options->answers[$key]; // for PHP 4.x
|
||||
$answer->answer = $this->substitute_variables($answer->answer,
|
||||
$answer->answer = $this->substitute_variables_and_eval($answer->answer,
|
||||
$state->options->dataset);
|
||||
}
|
||||
$virtualqtype = $this->get_virtual_qtype();
|
||||
@@ -456,11 +719,11 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype
|
||||
}
|
||||
foreach ($numericalquestion->options->answers as $key => $answer) {
|
||||
$answer = &$numericalquestion->options->answers[$key]; // for PHP 4.x
|
||||
$answer->answer = $this->substitute_variables($answer->answer,
|
||||
$answer->answer = $this->substitute_variables_and_eval($answer->answer,
|
||||
$state->options->dataset);
|
||||
// apply_unit
|
||||
}
|
||||
$numericalquestion->questiontext = $this->substitute_variables(
|
||||
$numericalquestion->questiontext = $this->substitute_variables_and_eval(
|
||||
$numericalquestion->questiontext, $state->options->dataset);
|
||||
$responses = $virtualqtype->get_all_responses($numericalquestion, $state);
|
||||
$response = reset($responses->responses);
|
||||
@@ -670,7 +933,6 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype
|
||||
FROM {question_dataset_items}
|
||||
WHERE definition = ? ORDER BY itemnumber", array($datasetdef->id));
|
||||
}
|
||||
// echo "<pre>"; print_r($datasetdefs[$defid]->items);
|
||||
for ($numberadded =$maxnumber+1 ; $numberadded <= $maxnumber+$numbertoadd ; $numberadded++){
|
||||
if (isset($datasetdefs[$defid]->items[$numberadded]) && ! $regenerate ){
|
||||
// echo "<p>Reuse an previously used record".$numberadded."id".$datasetdef->id."</p>";
|
||||
@@ -683,7 +945,6 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype
|
||||
} else {
|
||||
$datasetitem->value = '';
|
||||
}
|
||||
//pp echo "<pre>"; print_r( $datasetitem );
|
||||
if (!$DB->insert_record('question_dataset_items', $datasetitem)) {
|
||||
print_error('cannotinsert', 'question');
|
||||
}
|
||||
@@ -772,7 +1033,7 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype
|
||||
$virtualqtype = $this->get_virtual_qtype();
|
||||
foreach ($answers as $answer) {
|
||||
// $formula = $answer->answer;
|
||||
$formula = parent::substitute_variables($answer->answer,$data);
|
||||
$formula = $this->substitute_variables($answer->answer,$data);
|
||||
/* foreach ($data as $name => $value) {
|
||||
$formula = str_replace('{'.$name.'}', $value, $formula);
|
||||
}*/
|
||||
@@ -814,17 +1075,17 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype
|
||||
// filters options that are currently not accepted by calculated
|
||||
// It also determines a default selection...
|
||||
//$renameabledatasets not implemented anmywhere
|
||||
list($options, $selected) = parent::dataset_options($form, $name,'','qtype_calculated');
|
||||
list($options, $selected) = $this->dataset_options_from_database($form, $name,'','qtype_calculated');
|
||||
// list($options, $selected) = $this->dataset_optionsa($form, $name);
|
||||
|
||||
foreach ($options as $key => $whatever) {
|
||||
if (!ereg('^'.LITERAL.'-', $key) && $key != '0') {
|
||||
if (!ereg('^1-', $key) && $key != '0') {
|
||||
unset($options[$key]);
|
||||
}
|
||||
}
|
||||
if (!$selected) {
|
||||
if ($mandatory){
|
||||
$selected = LITERAL . "-0-$name"; // Default
|
||||
$selected = "1-0-$name"; // Default
|
||||
}else {
|
||||
$selected = "0"; // Default
|
||||
}
|
||||
@@ -880,8 +1141,21 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype
|
||||
}
|
||||
|
||||
function substitute_variables($str, $dataset) {
|
||||
$formula = parent::substitute_variables($str, $dataset);
|
||||
if ($error = qtype_calculated_find_formula_errors($formula)) {
|
||||
// print_r(
|
||||
|
||||
foreach ($dataset as $name => $value) {
|
||||
if($value < 0 ){
|
||||
$str = str_replace('{'.$name.'}', '('.$value.')', $str);
|
||||
} else {
|
||||
$str = str_replace('{'.$name.'}', $value, $str);
|
||||
}
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
|
||||
function substitute_variables_and_eval($str, $dataset) {
|
||||
$formula = $this->substitute_variables($str, $dataset) ;
|
||||
if ($error = qtype_calculated_find_formula_errors($formula)) {
|
||||
return $error;
|
||||
}
|
||||
/// Calculate the correct answer
|
||||
@@ -893,6 +1167,309 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype
|
||||
return $str;
|
||||
}
|
||||
|
||||
function get_dataset_definitions($questionid, $newdatasets) {
|
||||
global $DB;
|
||||
//get the existing datasets for this question
|
||||
$datasetdefs = array();
|
||||
if (!empty($questionid)) {
|
||||
global $CFG;
|
||||
$sql = "SELECT i.*
|
||||
FROM {question_datasets} d,
|
||||
{question_dataset_definitions} i
|
||||
WHERE d.question = ?
|
||||
AND d.datasetdefinition = i.id
|
||||
";
|
||||
if ($records = $DB->get_records_sql($sql, array($questionid))) {
|
||||
foreach ($records as $r) {
|
||||
$datasetdefs["$r->type-$r->category-$r->name"] = $r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($newdatasets as $dataset) {
|
||||
if (!$dataset) {
|
||||
continue; // The no dataset case...
|
||||
}
|
||||
|
||||
if (!isset($datasetdefs[$dataset])) {
|
||||
//make new datasetdef
|
||||
list($type, $category, $name) = explode('-', $dataset, 3);
|
||||
$datasetdef = new stdClass;
|
||||
$datasetdef->type = $type;
|
||||
$datasetdef->name = $name;
|
||||
$datasetdef->category = $category;
|
||||
$datasetdef->itemcount = 0;
|
||||
$datasetdef->options = 'uniform:1.0:10.0:1';
|
||||
$datasetdefs[$dataset] = clone($datasetdef);
|
||||
}
|
||||
}
|
||||
return $datasetdefs;
|
||||
}
|
||||
|
||||
function save_dataset_definitions($form) {
|
||||
global $DB;
|
||||
// Save datasets
|
||||
$datasetdefinitions = $this->get_dataset_definitions($form->id, $form->dataset);
|
||||
$tmpdatasets = array_flip($form->dataset);
|
||||
$defids = array_keys($datasetdefinitions);
|
||||
foreach ($defids as $defid) {
|
||||
$datasetdef = &$datasetdefinitions[$defid];
|
||||
if (isset($datasetdef->id)) {
|
||||
if (!isset($tmpdatasets[$defid])) {
|
||||
// This dataset is not used any more, delete it
|
||||
$DB->delete_records('question_datasets', array('question' => $form->id, 'datasetdefinition' => $datasetdef->id));
|
||||
if ($datasetdef->category == 0) { // Question local dataset
|
||||
$DB->delete_records('question_dataset_definitions', array('id' => $datasetdef->id));
|
||||
$DB->delete_records('question_dataset_items', array('definition' => $datasetdef->id));
|
||||
}
|
||||
}
|
||||
// This has already been saved or just got deleted
|
||||
unset($datasetdefinitions[$defid]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$datasetdef->id = $DB->insert_record('question_dataset_definitions', $datasetdef)) {
|
||||
print_error("cannotcreatedataset", 'question', '', $defid);
|
||||
}
|
||||
|
||||
if (0 != $datasetdef->category) {
|
||||
// We need to look for already existing
|
||||
// datasets in the category.
|
||||
// By first creating the datasetdefinition above we
|
||||
// can manage to automatically take care of
|
||||
// some possible realtime concurrence
|
||||
if ($olderdatasetdefs = $DB->get_records_select( 'question_dataset_definitions',
|
||||
"type = ?
|
||||
AND name = ?
|
||||
AND category = ?
|
||||
AND id < ?
|
||||
ORDER BY id DESC", array($datasetdef->type, $datasetdef->name, $datasetdef->category, $datasetdef->id))) {
|
||||
|
||||
while ($olderdatasetdef = array_shift($olderdatasetdefs)) {
|
||||
$DB->delete_records('question_dataset_definitions', array('id' => $datasetdef->id));
|
||||
$datasetdef = $olderdatasetdef;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create relation to this dataset:
|
||||
$questiondataset = new stdClass;
|
||||
$questiondataset->question = $form->id;
|
||||
$questiondataset->datasetdefinition = $datasetdef->id;
|
||||
if (!$DB->insert_record('question_datasets', $questiondataset)) {
|
||||
print_error('cannotcreaterelation', 'question', '', $name);
|
||||
}
|
||||
unset($datasetdefinitions[$defid]);
|
||||
}
|
||||
|
||||
// Remove local obsolete datasets as well as relations
|
||||
// to datasets in other categories:
|
||||
if (!empty($datasetdefinitions)) {
|
||||
foreach ($datasetdefinitions as $def) {
|
||||
$DB->delete_records('question_datasets', array('question' => $form->id, 'datasetdefinition' => $def->id));
|
||||
|
||||
if ($def->category == 0) { // Question local dataset
|
||||
$DB->delete_records('question_dataset_definitions', array('id' => $def->id));
|
||||
$DB->delete_records('question_dataset_items', array('definition' => $def->id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/** This function create a copy of the datasets ( definition and dataitems)
|
||||
* from the preceding question if they remain in the new question
|
||||
* otherwise its create the datasets that have been added as in the
|
||||
* save_dataset_definitions()
|
||||
*/
|
||||
function save_as_new_dataset_definitions($form, $initialid) {
|
||||
global $CFG, $DB;
|
||||
// Get the datasets from the intial question
|
||||
$datasetdefinitions = $this->get_dataset_definitions($initialid, $form->dataset);
|
||||
// $tmpdatasets contains those of the new question
|
||||
$tmpdatasets = array_flip($form->dataset);
|
||||
$defids = array_keys($datasetdefinitions);// new datasets
|
||||
foreach ($defids as $defid) {
|
||||
$datasetdef = &$datasetdefinitions[$defid];
|
||||
if (isset($datasetdef->id)) {
|
||||
// This dataset exist in the initial question
|
||||
if (!isset($tmpdatasets[$defid])) {
|
||||
// do not exist in the new question so ignore
|
||||
unset($datasetdefinitions[$defid]);
|
||||
continue;
|
||||
}
|
||||
// create a copy but not for category one
|
||||
if (0 == $datasetdef->category) {
|
||||
$olddatasetid = $datasetdef->id ;
|
||||
$olditemcount = $datasetdef->itemcount ;
|
||||
$datasetdef->itemcount =0;
|
||||
if (!$datasetdef->id = $DB->insert_record('question_dataset_definitions', $datasetdef)) {
|
||||
print_error('cannotcreatedataset', 'question', '', $defid);
|
||||
}
|
||||
//copy the dataitems
|
||||
$olditems = $DB->get_records_sql( // Use number as key!!
|
||||
" SELECT itemnumber, value
|
||||
FROM {question_dataset_items}
|
||||
WHERE definition = ? ", array($olddatasetid));
|
||||
if (count($olditems) > 0 ) {
|
||||
$itemcount = 0;
|
||||
foreach($olditems as $item ){
|
||||
$item->definition = $datasetdef->id;
|
||||
if (!$DB->insert_record('question_dataset_items', $item)) {
|
||||
print_error('cannotinsertitem', 'question', '', array($item->itemnumber, $item->value, $datasetdef->name));
|
||||
}
|
||||
$itemcount++;
|
||||
}
|
||||
//update item count
|
||||
$datasetdef->itemcount =$itemcount;
|
||||
$DB->update_record('question_dataset_definitions', $datasetdef);
|
||||
} // end of copy the dataitems
|
||||
}// end of copy the datasetdef
|
||||
// Create relation to the new question with this
|
||||
// copy as new datasetdef from the initial question
|
||||
$questiondataset = new stdClass;
|
||||
$questiondataset->question = $form->id;
|
||||
$questiondataset->datasetdefinition = $datasetdef->id;
|
||||
if (!$DB->insert_record('question_datasets', $questiondataset)) {
|
||||
print_error('cannotcreaterelation', 'question', '', $name);
|
||||
}
|
||||
unset($datasetdefinitions[$defid]);
|
||||
continue;
|
||||
}// end of datasetdefs from the initial question
|
||||
// really new one code similar to save_dataset_definitions()
|
||||
if (!$datasetdef->id = $DB->insert_record('question_dataset_definitions', $datasetdef)) {
|
||||
print_error('cannotcreatedataset', 'question', '', $defid);
|
||||
}
|
||||
|
||||
if (0 != $datasetdef->category) {
|
||||
// We need to look for already existing
|
||||
// datasets in the category.
|
||||
// By first creating the datasetdefinition above we
|
||||
// can manage to automatically take care of
|
||||
// some possible realtime concurrence
|
||||
if ($olderdatasetdefs = $DB->get_records_select(
|
||||
'question_dataset_definitions',
|
||||
"type = ?
|
||||
AND name = ?
|
||||
AND category = ?
|
||||
AND id < ?
|
||||
ORDER BY id DESC", array($datasetdef->type, $datasetdef->name, $datasetdef->category, $datasetdef->id))) {
|
||||
|
||||
while ($olderdatasetdef = array_shift($olderdatasetdefs)) {
|
||||
$DB->delete_records('question_dataset_definitions', array('id' => $datasetdef->id));
|
||||
$datasetdef = $olderdatasetdef;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create relation to this dataset:
|
||||
$questiondataset = new stdClass;
|
||||
$questiondataset->question = $form->id;
|
||||
$questiondataset->datasetdefinition = $datasetdef->id;
|
||||
if (!$DB->insert_record('question_datasets', $questiondataset)) {
|
||||
print_error('cannotcreaterelation', 'question', '', $name);
|
||||
}
|
||||
unset($datasetdefinitions[$defid]);
|
||||
}
|
||||
|
||||
// Remove local obsolete datasets as well as relations
|
||||
// to datasets in other categories:
|
||||
if (!empty($datasetdefinitions)) {
|
||||
foreach ($datasetdefinitions as $def) {
|
||||
$DB->delete_records('question_datasets', array('question' => $form->id, 'datasetdefinition' => $def->id));
|
||||
|
||||
if ($def->category == 0) { // Question local dataset
|
||||
$DB->delete_records('question_dataset_definitions', array('id' => $def->id));
|
||||
$DB->delete_records('question_dataset_items', array('definition' => $def->id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Dataset functionality
|
||||
function pick_question_dataset($question, $datasetitem) {
|
||||
// Select a dataset in the following format:
|
||||
// An array indexed by the variable names (d.name) pointing to the value
|
||||
// to be substituted
|
||||
global $CFG, $DB;
|
||||
if (!$dataset = $DB->get_records_sql(
|
||||
"SELECT d.name, i.value
|
||||
FROM {question_dataset_definitions} d,
|
||||
{question_dataset_items} i,
|
||||
{question_datasets} q
|
||||
WHERE q.question = ?
|
||||
AND q.datasetdefinition = d.id
|
||||
AND d.id = i.definition
|
||||
AND i.itemnumber = ?", array($question->id, $datasetitem))) {
|
||||
print_error('cannotgetdsfordependent', 'question', '', array($question->id, $datasetitem));
|
||||
}
|
||||
array_walk($dataset, create_function('&$val', '$val = $val->value;'));
|
||||
return $dataset;
|
||||
}
|
||||
|
||||
function dataset_options_from_database($form, $name,$prefix='',$langfile='quiz') {
|
||||
|
||||
// First options - it is not a dataset...
|
||||
$options['0'] = get_string($prefix.'nodataset', $langfile);
|
||||
|
||||
// Construct question local options
|
||||
global $CFG, $DB;
|
||||
$currentdatasetdef = $DB->get_record_sql(
|
||||
"SELECT a.*
|
||||
FROM {question_dataset_definitions} a,
|
||||
{question_datasets} b
|
||||
WHERE a.id = b.datasetdefinition
|
||||
AND b.question = ?
|
||||
AND a.name = ?", array($form->id, $name))
|
||||
or $currentdatasetdef->type = '0';
|
||||
foreach (array( LITERAL, FILE, LINK) as $type) {
|
||||
$key = "$type-0-$name";
|
||||
if ($currentdatasetdef->type == $type
|
||||
and $currentdatasetdef->category == 0) {
|
||||
$options[$key] = get_string($prefix."keptlocal$type", $langfile);
|
||||
} else {
|
||||
$options[$key] = get_string($prefix."newlocal$type", $langfile);
|
||||
}
|
||||
}
|
||||
|
||||
// Construct question category options
|
||||
$categorydatasetdefs = $DB->get_records_sql(
|
||||
"SELECT a.type, a.id
|
||||
FROM {question_dataset_definitions} a,
|
||||
{question_datasets} b
|
||||
WHERE a.id = b.datasetdefinition
|
||||
AND a.category = ?
|
||||
AND a.name = ?", array($form->category, $name));
|
||||
foreach(array( LITERAL, FILE, LINK) as $type) {
|
||||
$key = "$type-$form->category-$name";
|
||||
if (isset($categorydatasetdefs[$type])
|
||||
and $categorydef = $categorydatasetdefs[$type]) {
|
||||
if ($currentdatasetdef->type == $type
|
||||
and $currentdatasetdef->id == $categorydef->id) {
|
||||
$options[$key] = get_string($prefix."keptcategory$type", $langfile);
|
||||
} else {
|
||||
$options[$key] = get_string($prefix."existingcategory$type", $langfile);
|
||||
}
|
||||
} else {
|
||||
$options[$key] = get_string($prefix."newcategory$type", $langfile);
|
||||
}
|
||||
}
|
||||
|
||||
// All done!
|
||||
return array($options, $currentdatasetdef->type
|
||||
? "$currentdatasetdef->type-$currentdatasetdef->category-$name"
|
||||
: '');
|
||||
}
|
||||
|
||||
function find_dataset_names($text) {
|
||||
/// Returns the possible dataset names found in the text as an array
|
||||
/// The array has the dataset name for both key and value
|
||||
$datasetnames = array();
|
||||
while (ereg('\\{([[:alpha:]][^>} <{"\']*)\\}', $text, $regs)) {
|
||||
$datasetnames[$regs[1]] = $regs[1];
|
||||
$text = str_replace($regs[0], '', $text);
|
||||
}
|
||||
return $datasetnames;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function retrieve the item count of the available category shareable
|
||||
* wild cards that is added as a comment displayed when a wild card with
|
||||
@@ -985,6 +1562,12 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype
|
||||
}
|
||||
return $text ;
|
||||
}
|
||||
function get_virtual_qtype() {
|
||||
if (!$this->virtualqtype) {
|
||||
$this->virtualqtype = $this->create_virtual_qtype();
|
||||
}
|
||||
return $this->virtualqtype;
|
||||
}
|
||||
|
||||
|
||||
/// BACKUP FUNCTIONS ////////////////////////////
|
||||
@@ -1153,7 +1736,7 @@ function qtype_calculated_calculate_answer($formula, $individualdata,
|
||||
|
||||
/// Exchange formula variables with the correct values...
|
||||
global $QTYPES;
|
||||
$answer = $QTYPES['calculated']->substitute_variables($formula, $individualdata);
|
||||
$answer = $QTYPES['calculated']->substitute_variables_and_eval($formula, $individualdata);
|
||||
if ('1' == $answerformat) { /* Answer is to have $answerlength decimals */
|
||||
/*** Adjust to the correct number of decimals ***/
|
||||
if (stripos($answer,'e')>0 ){
|
||||
|
||||
Reference in New Issue
Block a user