Skip to content

Commit

Permalink
MDL-69625 course: return raw custom field value in external method.
Browse files Browse the repository at this point in the history
For clients that wish to consume the original value of the custom
field (e.g. timestamps for date fields), rather than the formatted
version, add a new "valueraw" property to the returned data.
  • Loading branch information
paulholden committed Oct 5, 2020
1 parent 87afa4d commit d178779
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 4 deletions.
4 changes: 4 additions & 0 deletions course/externallib.php
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,7 @@ public static function get_courses($options = array()) {
$courseinfo['customfields'][] = [
'type' => $data->get_type(),
'value' => $data->get_value(),
'valueraw' => $data->get_data_controller()->get_value(),
'name' => $data->get_name(),
'shortname' => $data->get_shortname()
];
Expand Down Expand Up @@ -735,6 +736,7 @@ public static function get_courses_returns() {
'shortname' => new external_value(PARAM_ALPHANUMEXT, 'The shortname of the custom field'),
'type' => new external_value(PARAM_COMPONENT,
'The type of the custom field - text, checkbox...'),
'valueraw' => new external_value(PARAM_RAW, 'The raw value of the custom field'),
'value' => new external_value(PARAM_RAW, 'The value of the custom field')]
), 'Custom fields and associated values', VALUE_OPTIONAL),
), 'course'
Expand Down Expand Up @@ -2489,6 +2491,7 @@ protected static function get_course_public_information(core_course_list_element
$coursereturns['customfields'][] = [
'type' => $data->get_type(),
'value' => $data->get_value(),
'valueraw' => $data->get_data_controller()->get_value(),
'name' => $data->get_name(),
'shortname' => $data->get_shortname()
];
Expand Down Expand Up @@ -2640,6 +2643,7 @@ protected static function get_course_structure($onlypublicdata = true) {
'The shortname of the custom field - to be able to build the field class in the code'),
'type' => new external_value(PARAM_ALPHANUMEXT,
'The type of the custom field - text field, checkbox...'),
'valueraw' => new external_value(PARAM_RAW, 'The raw value of the custom field'),
'value' => new external_value(PARAM_RAW, 'The value of the custom field'),
)
), 'Custom fields', VALUE_OPTIONAL),
Expand Down
150 changes: 146 additions & 4 deletions course/tests/externallib_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -775,8 +775,16 @@ public function test_get_courses () {
array('name' => 'coursedisplay', 'value' => $dbcourse->coursedisplay),
));
}
if ($dbcourse->id == 4) {
$this->assertEquals($course['customfields'], [array_merge($customfield, $customfieldvalue)]);

// Assert custom field that we previously added to test course 4.
if ($dbcourse->id == $course4->id) {
$this->assertEquals([
'shortname' => $customfield['shortname'],
'name' => $customfield['name'],
'type' => $customfield['type'],
'value' => $customfieldvalue['value'],
'valueraw' => $customfieldvalue['value'],
], $course['customfields'][0]);
}
}

Expand All @@ -789,6 +797,49 @@ public function test_get_courses () {
$this->assertEquals($DB->count_records('course'), count($courses));
}

/**
* Test retrieving courses returns custom field data
*/
public function test_get_courses_customfields(): void {
$this->resetAfterTest();
$this->setAdminUser();

$fieldcategory = $this->getDataGenerator()->create_custom_field_category([]);
$datefield = $this->getDataGenerator()->create_custom_field([
'categoryid' => $fieldcategory->get('id'),
'shortname' => 'mydate',
'name' => 'My date',
'type' => 'date',
]);

$newcourse = $this->getDataGenerator()->create_course(['customfields' => [
[
'shortname' => $datefield->get('shortname'),
'value' => 1580389200, // 30/01/2020 13:00 GMT.
],
]]);

$courses = external_api::clean_returnvalue(
core_course_external::get_courses_returns(),
core_course_external::get_courses(['ids' => [$newcourse->id]])
);

$this->assertCount(1, $courses);
$course = reset($courses);

$this->assertArrayHasKey('customfields', $course);
$this->assertCount(1, $course['customfields']);

// Assert the received custom field, "value" containing a human-readable version and "valueraw" the unmodified version.
$this->assertEquals([
'name' => $datefield->get('name'),
'shortname' => $datefield->get('shortname'),
'type' => $datefield->get('type'),
'value' => userdate(1580389200),
'valueraw' => 1580389200,
], reset($course['customfields']));
}

/**
* Test get_courses without capability
*/
Expand Down Expand Up @@ -912,6 +963,49 @@ public function test_search_courses () {
$results = core_course_external::search_courses('blocklist', $blockid);
}

/**
* Test searching for courses returns custom field data
*/
public function test_search_courses_customfields(): void {
$this->resetAfterTest();
$this->setAdminUser();

$fieldcategory = $this->getDataGenerator()->create_custom_field_category([]);
$datefield = $this->getDataGenerator()->create_custom_field([
'categoryid' => $fieldcategory->get('id'),
'shortname' => 'mydate',
'name' => 'My date',
'type' => 'date',
]);

$newcourse = $this->getDataGenerator()->create_course(['customfields' => [
[
'shortname' => $datefield->get('shortname'),
'value' => 1580389200, // 30/01/2020 13:00 GMT.
],
]]);

$result = external_api::clean_returnvalue(
core_course_external::search_courses_returns(),
core_course_external::search_courses('search', $newcourse->shortname)
);

$this->assertCount(1, $result['courses']);
$course = reset($result['courses']);

$this->assertArrayHasKey('customfields', $course);
$this->assertCount(1, $course['customfields']);

// Assert the received custom field, "value" containing a human-readable version and "valueraw" the unmodified version.
$this->assertEquals([
'name' => $datefield->get('name'),
'shortname' => $datefield->get('shortname'),
'type' => $datefield->get('type'),
'value' => userdate(1580389200),
'valueraw' => 1580389200,
], reset($course['customfields']));
}

/**
* Create a course with contents
* @return array A list with the course object and course modules objects
Expand Down Expand Up @@ -2453,8 +2547,13 @@ public function test_get_courses_by_field() {
$this->assertCount(1, $result['courses']);
$this->assertEquals($course2->id, $result['courses'][0]['id']);
// Check custom fields properly returned.
unset($customfield['categoryid']);
$this->assertEquals([array_merge($customfield, $customfieldvalue)], $result['courses'][0]['customfields']);
$this->assertEquals([
'shortname' => $customfield['shortname'],
'name' => $customfield['name'],
'type' => $customfield['type'],
'value' => $customfieldvalue['value'],
'valueraw' => $customfieldvalue['value'],
], $result['courses'][0]['customfields'][0]);

$result = core_course_external::get_courses_by_field('ids', "$course1->id,$course2->id");
$result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
Expand Down Expand Up @@ -2583,6 +2682,49 @@ public function test_get_courses_by_field() {
$this->assertCount(0, $result['courses']);
}

/**
* Test retrieving courses by field returns custom field data
*/
public function test_get_courses_by_field_customfields(): void {
$this->resetAfterTest();
$this->setAdminUser();

$fieldcategory = $this->getDataGenerator()->create_custom_field_category([]);
$datefield = $this->getDataGenerator()->create_custom_field([
'categoryid' => $fieldcategory->get('id'),
'shortname' => 'mydate',
'name' => 'My date',
'type' => 'date',
]);

$newcourse = $this->getDataGenerator()->create_course(['customfields' => [
[
'shortname' => $datefield->get('shortname'),
'value' => 1580389200, // 30/01/2020 13:00 GMT.
],
]]);

$result = external_api::clean_returnvalue(
core_course_external::get_courses_by_field_returns(),
core_course_external::get_courses_by_field('id', $newcourse->id)
);

$this->assertCount(1, $result['courses']);
$course = reset($result['courses']);

$this->assertArrayHasKey('customfields', $course);
$this->assertCount(1, $course['customfields']);

// Assert the received custom field, "value" containing a human-readable version and "valueraw" the unmodified version.
$this->assertEquals([
'name' => $datefield->get('name'),
'shortname' => $datefield->get('shortname'),
'type' => $datefield->get('type'),
'value' => userdate(1580389200),
'valueraw' => 1580389200,
], reset($course['customfields']));
}

public function test_get_courses_by_field_invalid_field() {
$this->expectException('invalid_parameter_exception');
$result = core_course_external::get_courses_by_field('zyx', 'x');
Expand Down
2 changes: 2 additions & 0 deletions course/upgrade.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ information provided here is intended especially for developers.

* The function make_categories_options() has now been deprecated. Please use \core_course_category::make_categories_list() instead.
* External function core_course_external::get_course_contents now returns a new field contextid with the module context id.
* The core_course_external class methods get_courses(), get_courses_by_field() and search_courses() now return a "valueraw" property
for each custom course field, which contains the original/unformatted version of the custom field value.

=== 3.9 ===

Expand Down

0 comments on commit d178779

Please sign in to comment.