Permalink
Browse files

Merge branch 'MDL-38885-23' of git://github.com/FMCorz/moodle into MO…

…ODLE_23_STABLE
  • Loading branch information...
2 parents 48265a6 + e4e1bd9 commit f6735ae534461693861cddc81ecdbab67e982359 @stronk7 stronk7 committed May 10, 2013
Showing with 270 additions and 12 deletions.
  1. +78 −11 lib/formslib.php
  2. +192 −1 lib/tests/formslib_test.php
View
@@ -1514,6 +1514,81 @@ function setTypes($paramtypes) {
}
/**
+ * Return the type(s) to use to clean an element.
+ *
+ * In the case where the element has an array as a value, we will try to obtain a
+ * type defined for that specific key, and recursively until done.
+ *
+ * This method does not work reverse, you cannot pass a nested element and hoping to
+ * fallback on the clean type of a parent. This method intends to be used with the
+ * main element, which will generate child types if needed, not the other way around.
+ *
+ * Example scenario:
+ *
+ * You have defined a new repeated element containing a text field called 'foo'.
+ * By default there will always be 2 occurence of 'foo' in the form. Even though
+ * you've set the type on 'foo' to be PARAM_INT, for some obscure reason, you want
+ * the first value of 'foo', to be PARAM_FLOAT, which you set using setType:
+ * $mform->setType('foo[0]', PARAM_FLOAT).
+ *
+ * Now if you call this method passing 'foo', along with the submitted values of 'foo':
+ * array(0 => '1.23', 1 => '10'), you will get an array telling you that the key 0 is a
+ * FLOAT and 1 is an INT. If you had passed 'foo[1]', along with its value '10', you would
+ * get the default clean type returned (param $default).
+ *
+ * @param string $elementname name of the element.
+ * @param mixed $value value that should be cleaned.
+ * @param int $default default constant value to be returned (PARAM_...)
+ * @return string|array constant value or array of constant values (PARAM_...)
+ */
+ public function getCleanType($elementname, $value, $default = PARAM_RAW) {
+ $type = $default;
+ if (array_key_exists($elementname, $this->_types)) {
+ $type = $this->_types[$elementname];
+ }
+ if (is_array($value)) {
+ $default = $type;
+ $type = array();
+ foreach ($value as $subkey => $subvalue) {
+ $typekey = "$elementname" . "[$subkey]";
+ if (array_key_exists($typekey, $this->_types)) {
+ $subtype = $this->_types[$typekey];
+ } else {
+ $subtype = $default;
+ }
+ if (is_array($subvalue)) {
+ $type[$subkey] = $this->getCleanType($typekey, $subvalue, $subtype);
+ } else {
+ $type[$subkey] = $subtype;
+ }
+ }
+ }
+ return $type;
+ }
+
+ /**
+ * Return the cleaned value using the passed type(s).
+ *
+ * @param mixed $value value that has to be cleaned.
+ * @param int|array $type constant value to use to clean (PARAM_...), typically returned by {@link self::getCleanType()}.
+ * @return mixed cleaned up value.
+ */
+ public function getCleanedValue($value, $type) {
+ if (is_array($type) && is_array($value)) {
+ foreach ($type as $key => $param) {
+ $value[$key] = $this->getCleanedValue($value[$key], $param);
+ }
+ } else if (!is_array($type) && !is_array($value)) {
+ $value = clean_param($value, $type);
+ } else if (!is_array($type) && is_array($value)) {
+ $value = clean_param_array($value, $type, true);
+ } else {
+ throw new coding_exception('Unexpected type or value received in MoodleQuickForm::getCleanedValue()');
+ }
+ return $value;
+ }
+
+ /**
* Updates submitted values
*
* @param array $submission submitted values
@@ -1525,17 +1600,9 @@ function updateSubmission($submission, $files) {
if (empty($submission)) {
$this->_submitValues = array();
} else {
- foreach ($submission as $key=>$s) {
- if (array_key_exists($key, $this->_types)) {
- $type = $this->_types[$key];
- } else {
- $type = PARAM_RAW;
- }
- if (is_array($s)) {
- $submission[$key] = clean_param_array($s, $type, true);
- } else {
- $submission[$key] = clean_param($s, $type);
- }
+ foreach ($submission as $key => $s) {
+ $type = $this->getCleanType($key, $s);
+ $submission[$key] = $this->getCleanedValue($s, $type);
}
$this->_submitValues = $submission;
$this->_flagSubmitted = true;
View
@@ -190,6 +190,129 @@ public function test_rendering() {
$this->assertTag(array('tag'=>'input', 'id'=>'id_repeatradio_2_2',
'attributes'=>array('type'=>'radio', 'name'=>'repeatradio[2]', 'value'=>'2')), $html);
}
+
+ public function test_type_cleaning() {
+ $expectedtypes = array(
+ 'simpleel' => PARAM_INT,
+ 'groupel1' => PARAM_INT,
+ 'groupel2' => PARAM_FLOAT,
+ 'groupel3' => PARAM_INT,
+ 'namedgroup' => array(
+ 'sndgroupel1' => PARAM_INT,
+ 'sndgroupel2' => PARAM_FLOAT,
+ 'sndgroupel3' => PARAM_INT
+ ),
+ 'namedgroupinherit' => array(
+ 'thdgroupel1' => PARAM_INT,
+ 'thdgroupel2' => PARAM_INT
+ ),
+ 'repeatedel' => array(
+ 0 => PARAM_INT,
+ 1 => PARAM_INT
+ ),
+ 'repeatedelinherit' => array(
+ 0 => PARAM_INT,
+ 1 => PARAM_INT
+ ),
+ 'squaretest' => array(
+ 0 => PARAM_INT
+ ),
+ 'nested' => array(
+ 0 => array(
+ 'bob' => array(
+ 123 => PARAM_INT,
+ 'foo' => PARAM_FLOAT
+ ),
+ 'xyz' => PARAM_RAW
+ ),
+ 1 => PARAM_INT
+ )
+ );
+ $valuessubmitted = array(
+ 'simpleel' => '11.01',
+ 'groupel1' => '11.01',
+ 'groupel2' => '11.01',
+ 'groupel3' => '11.01',
+ 'namedgroup' => array(
+ 'sndgroupel1' => '11.01',
+ 'sndgroupel2' => '11.01',
+ 'sndgroupel3' => '11.01'
+ ),
+ 'namedgroupinherit' => array(
+ 'thdgroupel1' => '11.01',
+ 'thdgroupel2' => '11.01'
+ ),
+ 'repeatedel' => array(
+ 0 => '11.01',
+ 1 => '11.01'
+ ),
+ 'repeatedelinherit' => array(
+ 0 => '11.01',
+ 1 => '11.01'
+ ),
+ 'squaretest' => array(
+ 0 => '11.01'
+ ),
+ 'nested' => array(
+ 0 => array(
+ 'bob' => array(
+ 123 => '11.01',
+ 'foo' => '11.01'
+ ),
+ 'xyz' => '11.01'
+ ),
+ 1 => '11.01'
+ )
+ );
+ $expectedvalues = array(
+ 'simpleel' => 11,
+ 'groupel1' => 11,
+ 'groupel2' => 11.01,
+ 'groupel3' => 11,
+ 'namedgroup' => array(
+ 'sndgroupel1' => 11,
+ 'sndgroupel2' => 11.01,
+ 'sndgroupel3' => 11
+ ),
+ 'namedgroupinherit' => array(
+ 'thdgroupel1' => 11,
+ 'thdgroupel2' => 11
+ ),
+ 'repeatable' => 2,
+ 'repeatedel' => array(
+ 0 => 11,
+ 1 => 11
+ ),
+ 'repeatableinherit' => 2,
+ 'repeatedelinherit' => array(
+ 0 => 11,
+ 1 => 11
+ ),
+ 'squaretest' => array(
+ 0 => 11
+ ),
+ 'nested' => array(
+ 0 => array(
+ 'bob' => array(
+ 123 => 11,
+ 'foo' => 11.01
+ ),
+ 'xyz' => '11.01'
+ ),
+ 1 => 11
+ )
+ );
+
+ $mform = new formslib_clean_value();
+ $mform->get_form()->updateSubmission($valuessubmitted, null);
+ foreach ($expectedtypes as $elementname => $expected) {
+ $actual = $mform->get_form()->getCleanType($elementname, $valuessubmitted[$elementname]);
+ $this->assertSame($expected, $actual, "Failed validating clean type of '$elementname'");
+ }
+
+ $data = $mform->get_data();
+ $this->assertSame($expectedvalues, (array) $data);
+ }
}
@@ -217,4 +340,72 @@ public function definition() {
);
$this->repeat_elements($repeatels, 3, array(), 'numradios', 'addradios');
}
-}
+}
+
+class formslib_clean_value extends moodleform {
+ public function get_form() {
+ return $this->_form;
+ }
+ public function definition() {
+ $mform = $this->_form;
+
+ // Add a simple int.
+ $mform->addElement('text', 'simpleel', 'simpleel');
+ $mform->setType('simpleel', PARAM_INT);
+
+ // Add a non-named group.
+ $group = array(
+ $mform->createElement('text', 'groupel1', 'groupel1'),
+ $mform->createElement('text', 'groupel2', 'groupel2'),
+ $mform->createElement('text', 'groupel3', 'groupel3')
+ );
+ $mform->setType('groupel1', PARAM_INT);
+ $mform->setType('groupel2', PARAM_FLOAT);
+ $mform->setType('groupel3', PARAM_INT);
+ $mform->addGroup($group);
+
+ // Add a named group.
+ $group = array(
+ $mform->createElement('text', 'sndgroupel1', 'sndgroupel1'),
+ $mform->createElement('text', 'sndgroupel2', 'sndgroupel2'),
+ $mform->createElement('text', 'sndgroupel3', 'sndgroupel3')
+ );
+ $mform->addGroup($group, 'namedgroup');
+ $mform->setType('namedgroup[sndgroupel1]', PARAM_INT);
+ $mform->setType('namedgroup[sndgroupel2]', PARAM_FLOAT);
+ $mform->setType('namedgroup[sndgroupel3]', PARAM_INT);
+
+ // Add a named group, with inheritance.
+ $group = array(
+ $mform->createElement('text', 'thdgroupel1', 'thdgroupel1'),
+ $mform->createElement('text', 'thdgroupel2', 'thdgroupel2')
+ );
+ $mform->addGroup($group, 'namedgroupinherit');
+ $mform->setType('namedgroupinherit', PARAM_INT);
+
+ // Add a repetition.
+ $repeat = $mform->createElement('text', 'repeatedel', 'repeatedel');
+ $this->repeat_elements(array($repeat), 2, array('repeatedel' => array('type' => PARAM_INT)), 'repeatable', 'add', 0);
+
+ // Add a repetition, with inheritance.
+ $repeat = $mform->createElement('text', 'repeatedelinherit', 'repeatedelinherit');
+ $this->repeat_elements(array($repeat), 2, array(), 'repeatableinherit', 'add', 0);
+ $mform->setType('repeatedelinherit', PARAM_INT);
+
+ // Add an arbitrary named element.
+ $mform->addElement('text', 'squaretest[0]', 'squaretest[0]');
+ $mform->setType('squaretest[0]', PARAM_INT);
+
+ // Add an arbitrary nested array named element.
+ $mform->addElement('text', 'nested[0][bob][123]', 'nested[0][bob][123]');
+ $mform->setType('nested[0][bob][123]', PARAM_INT);
+
+ // Add inheritance test cases.
+ $mform->setType('nested', PARAM_INT);
+ $mform->setType('nested[0]', PARAM_RAW);
+ $mform->setType('nested[0][bob]', PARAM_FLOAT);
+ $mform->addElement('text', 'nested[1]', 'nested[1]');
+ $mform->addElement('text', 'nested[0][xyz]', 'nested[0][xyz]');
+ $mform->addElement('text', 'nested[0][bob][foo]', 'nested[0][bob][foo]');
+ }
+}

0 comments on commit f6735ae

Please sign in to comment.