diff --git a/webservice/rest/locallib.php b/webservice/rest/locallib.php index 1ead1513413..f0bd340b166 100644 --- a/webservice/rest/locallib.php +++ b/webservice/rest/locallib.php @@ -224,7 +224,8 @@ class webservice_rest_server extends webservice_base_server { } else if ($desc instanceof external_single_structure) { $single = ''."\n"; foreach ($desc->keys as $key=>$subdesc) { - $single .= ''.self::xmlize_result($returns[$key], $subdesc).''."\n"; + $value = isset($returns[$key]) ? $returns[$key] : null; + $single .= ''.self::xmlize_result($value, $subdesc).''."\n"; } $single .= ''."\n"; return $single; diff --git a/webservice/rest/tests/server_test.php b/webservice/rest/tests/server_test.php new file mode 100644 index 00000000000..354fc6048f4 --- /dev/null +++ b/webservice/rest/tests/server_test.php @@ -0,0 +1,217 @@ +. + +/** + * Rest server tests. + * + * @package webservice_rest + * @copyright 2016 Frédéric Massart - FMCorz.net + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); +global $CFG; + +require_once($CFG->libdir . '/externallib.php'); +require_once($CFG->dirroot . '/webservice/rest/locallib.php'); + +/** + * Rest server testcase. + * + * @package webservice_rest + * @copyright 2016 Frédéric Massart - FMCorz.net + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class webservice_rest_server_testcase extends advanced_testcase { + + /** + * Data provider for test_xmlize. + * @return array + */ + public function xmlize_provider() { + $data = []; + $data[] = [null, null, '']; + $data[] = [new external_value(PARAM_BOOL), false, "0\n"]; + $data[] = [new external_value(PARAM_BOOL), true, "1\n"]; + $data[] = [new external_value(PARAM_ALPHA), null, "\n"]; + $data[] = [new external_value(PARAM_ALPHA), 'a', "a\n"]; + $data[] = [new external_value(PARAM_INT), 123, "123\n"]; + $data[] = [ + new external_multiple_structure(new external_value(PARAM_INT)), + [1, 2, 3], + "\n" . + "1\n" . + "2\n" . + "3\n" . + "\n" + ]; + $data[] = [ // Multiple structure with null value. + new external_multiple_structure(new external_value(PARAM_ALPHA)), + ['A', null, 'C'], + "\n" . + "A\n" . + "\n" . + "C\n" . + "\n" + ]; + $data[] = [ // Multiple structure without values. + new external_multiple_structure(new external_value(PARAM_ALPHA)), + [], + "\n" . + "\n" + ]; + $data[] = [ + new external_single_structure([ + 'one' => new external_value(PARAM_INT), + 'two' => new external_value(PARAM_INT), + 'three' => new external_value(PARAM_INT), + ]), + ['one' => 1, 'two' => 2, 'three' => 3], + "\n" . + "1\n\n" . + "2\n\n" . + "3\n\n" . + "\n" + ]; + $data[] = [ // Single structure with null value. + new external_single_structure([ + 'one' => new external_value(PARAM_INT), + 'two' => new external_value(PARAM_INT), + 'three' => new external_value(PARAM_INT), + ]), + ['one' => 1, 'two' => null, 'three' => 3], + "\n" . + "1\n\n" . + "\n\n" . + "3\n\n" . + "\n" + ]; + $data[] = [ // Single structure missing keys. + new external_single_structure([ + 'one' => new external_value(PARAM_INT), + 'two' => new external_value(PARAM_INT), + 'three' => new external_value(PARAM_INT), + ]), + ['two' => null, 'three' => 3], + "\n" . + "\n\n" . + "\n\n" . + "3\n\n" . + "\n" + ]; + $data[] = [ // Nested structure. + new external_single_structure([ + 'one' => new external_multiple_structure( + new external_value(PARAM_INT) + ), + 'two' => new external_multiple_structure( + new external_single_structure([ + 'firstname' => new external_value(PARAM_RAW), + 'lastname' => new external_value(PARAM_RAW), + ]) + ), + 'three' => new external_single_structure([ + 'firstname' => new external_value(PARAM_RAW), + 'lastname' => new external_value(PARAM_RAW), + ]), + ]), + [ + 'one' => [2, 3, 4], + 'two' => [ + ['firstname' => 'Louis', 'lastname' => 'Armstrong'], + ['firstname' => 'Neil', 'lastname' => 'Armstrong'], + ], + 'three' => ['firstname' => 'Neil', 'lastname' => 'Armstrong'], + ], + "\n" . + "\n". + "2\n" . + "3\n" . + "4\n" . + "\n\n" . + "\n". + "\n" . + "Louis\n\n" . + "Armstrong\n\n" . + "\n" . + "\n" . + "Neil\n\n" . + "Armstrong\n\n" . + "\n" . + "\n\n" . + "\n" . + "Neil\n\n" . + "Armstrong\n\n" . + "\n\n" . + "\n" + ]; + $data[] = [ // Nested structure with missing keys. + new external_single_structure([ + 'one' => new external_multiple_structure( + new external_value(PARAM_INT) + ), + 'two' => new external_multiple_structure( + new external_single_structure([ + 'firstname' => new external_value(PARAM_RAW), + 'lastname' => new external_value(PARAM_RAW), + ]) + ), + 'three' => new external_single_structure([ + 'firstname' => new external_value(PARAM_RAW), + 'lastname' => new external_value(PARAM_RAW), + ]), + ]), + [ + 'two' => [ + ['firstname' => 'Louis'], + ['lastname' => 'Armstrong'], + ], + 'three' => ['lastname' => 'Armstrong'], + ], + "\n" . + "\n\n\n" . + "\n". + "\n" . + "Louis\n\n" . + "\n\n" . + "\n" . + "\n" . + "\n\n" . + "Armstrong\n\n" . + "\n" . + "\n\n" . + "\n" . + "\n\n" . + "Armstrong\n\n" . + "\n\n" . + "\n" + ]; + return $data; + } + + /** + * @dataProvider xmlize_provider + * @param external_description $description The data structure. + * @param mixed $value The value to xmlise. + * @param mixed $expected The expected output. + */ + public function test_xmlize($description, $value, $expected) { + $method = new ReflectionMethod('webservice_rest_server', 'xmlize_result'); + $method->setAccessible(true); + $this->assertEquals($expected, $method->invoke(null, $value, $description)); + } + +}