Skip to content

Commit

Permalink
MDL-27410 qtype_calculated better errorhandling for invalid expressions.
Browse files Browse the repository at this point in the history
Better method names.
  • Loading branch information
timhunt committed May 18, 2011
1 parent 0652547 commit 19e911a
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 18 deletions.
42 changes: 26 additions & 16 deletions question/type/calculated/question.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ class qtype_calculated_dataset_loader {
protected $questionid;

/** @var int the id of the question we are helping. */
protected $setsavailable = null;
protected $itemsavailable = null;

/**
* Constructor
Expand All @@ -113,33 +113,39 @@ public function __construct($questionid) {
$this->questionid = $questionid;
}

public function get_number_of_datasets() {
/**
* Get the number of items (different values) in each dataset used by this
* question. This is the minimum number of items in any dataset used by this
* question.
* @return int the number of items available.
*/
public function get_number_of_items() {
global $DB;

if (is_null($this->setsavailable)) {
$this->setsavailable = $DB->get_field_sql('
if (is_null($this->itemsavailable)) {
$this->itemsavailable = $DB->get_field_sql('
SELECT MIN(qdd.itemcount)
FROM {question_dataset_definitions} qdd
JOIN {question_datasets} qd ON qdd.id = qd.datasetdefinition
WHERE qd.question = ?
', array($question->id), MUST_EXIST);
', array($this->questionid), MUST_EXIST);
}

return $this->setsavailable;
return $this->itemsavailable;
}

/**
* Load a particular data set.
* @param int $setnumber which set of values to load.
* 0 <= $setnumber < {@link get_number_of_datasets()}.
* Load a particular set of values for each dataset used by this question.
* @param int $itemnumber which set of values to load.
* 0 < $itemnumber <= {@link get_number_of_items()}.
* @return qtype_calculated_variable_substituter with the correct variable
* -> value substitutions set up.
*/
public function load_dataset($setnumber) {
if ($setnumber <= 0 || $setnumber > $this->get_number_of_datasets()) {
public function load_values($itemnumber) {
if ($itemnumber <= 0 || $itemnumber > $this->get_number_of_items()) {
$a = new stdClass();
$a->id = $question->id;
$a->item = $datasetitem;
$a->id = $this->questionid;
$a->item = $itemnumber;
throw new moodle_exception('cannotgetdsfordependent', 'question', '', $a);
}

Expand All @@ -150,7 +156,7 @@ public function load_dataset($setnumber) {
JOIN {question_datasets} qd ON qdd.id = qd.datasetdefinition
WHERE qd.question = ?
AND qdi.itemnumber = ?
', array($question->id, $setnumber));
', array($this->questionid, $itemnumber));

return new qtype_calculated_variable_substituter($values);
}
Expand Down Expand Up @@ -222,8 +228,12 @@ public function get_values() {
* @return float the computed result.
*/
public function calculate($expression) {
eval('$str = ' . $this->substitute_values($expression) . ';');
return $str;
$exp = $this->substitute_values($expression);
// This validation trick from http://php.net/manual/en/function.eval.php
if (!@eval('return true; $result = ' . $exp . ';')) {
throw new moodle_exception('illegalformulasyntax', 'qtype_calculated', '', $expression);
}
return eval('return ' . $exp . ';');
}

/**
Expand Down
11 changes: 9 additions & 2 deletions question/type/calculated/simpletest/testvariablesubstituter.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class qtype_calculated_variable_substituter_test extends UnitTestCase {
public function test_simple_equation() {
public function test_simple_expression() {
$vs = new qtype_calculated_variable_substituter(array('a' => 1, 'b' => 2));
$this->assertEqual(3, $vs->calculate('{a} + {b}'));
}

public function test_simple_equation_negatives() {
public function test_simple_expression_negatives() {
$vs = new qtype_calculated_variable_substituter(array('a' => -1, 'b' => -2));
$this->assertEqual(1, $vs->calculate('{a}-{b}'));
}
Expand All @@ -50,4 +50,11 @@ public function test_cannot_use_nonnumbers() {
$this->expectException();
$vs = new qtype_calculated_variable_substituter(array('a' => 'frog', 'b' => -2));
}

public function test_invalid_expression() {
$this->expectException();
$vs = new qtype_calculated_variable_substituter(array('a' => 1, 'b' => 2));
$vs->calculate('{a} + {b}?');
}

}

0 comments on commit 19e911a

Please sign in to comment.