diff --git a/course/externallib.php b/course/externallib.php
index f38953a354c..ddede57b623 100644
--- a/course/externallib.php
+++ b/course/externallib.php
@@ -756,6 +756,26 @@ class core_course_external extends external_api {
);
}
+ /**
+ * Return array of all editable course custom fields indexed by their shortname
+ *
+ * @param \context $context
+ * @param int $courseid
+ * @return \core_customfield\field_controller[]
+ */
+ public static function get_editable_customfields(\context $context, int $courseid = 0): array {
+ $result = [];
+
+ $handler = \core_course\customfield\course_handler::create();
+ $handler->set_parent_context($context);
+
+ foreach ($handler->get_editable_fields($courseid) as $field) {
+ $result[$field->get('shortname')] = $field;
+ }
+
+ return $result;
+ }
+
/**
* Returns description of method parameters
*
@@ -928,8 +948,13 @@ class core_course_external extends external_api {
// Custom fields.
if (!empty($course['customfields'])) {
+ $customfields = self::get_editable_customfields($context);
foreach ($course['customfields'] as $field) {
- $course['customfield_'.$field['shortname']] = $field['value'];
+ if (array_key_exists($field['shortname'], $customfields)) {
+ // Ensure we're populating the element form fields correctly.
+ $controller = \core_customfield\data_controller::create(0, null, $customfields[$field['shortname']]);
+ $course[$controller->get_form_element_name()] = $field['value'];
+ }
}
}
@@ -1141,10 +1166,15 @@ class core_course_external extends external_api {
}
}
- // Prepare list of custom fields.
+ // Custom fields.
if (isset($course['customfields'])) {
+ $customfields = self::get_editable_customfields($context, $course['id']);
foreach ($course['customfields'] as $field) {
- $course['customfield_' . $field['shortname']] = $field['value'];
+ if (array_key_exists($field['shortname'], $customfields)) {
+ // Ensure we're populating the element form fields correctly.
+ $controller = \core_customfield\data_controller::create(0, null, $customfields[$field['shortname']]);
+ $course[$controller->get_form_element_name()] = $field['value'];
+ }
}
}
diff --git a/course/tests/externallib_test.php b/course/tests/externallib_test.php
index 3911a36d977..e71b974c543 100644
--- a/course/tests/externallib_test.php
+++ b/course/tests/externallib_test.php
@@ -453,10 +453,12 @@ class externallib_test extends externallib_advanced_testcase {
// Custom fields.
$fieldcategory = self::getDataGenerator()->create_custom_field_category(['name' => 'Other fields']);
- $customfield = ['shortname' => 'test', 'name' => 'Custom field', 'type' => 'text',
- 'categoryid' => $fieldcategory->get('id'),
- 'configdata' => ['visibility' => \core_course\customfield\course_handler::VISIBLETOALL]];
- $field = self::getDataGenerator()->create_custom_field($customfield);
+ $fieldtext = self::getDataGenerator()->create_custom_field([
+ 'categoryid' => $fieldcategory->get('id'), 'name' => 'Text', 'shortname' => 'text', 'type' => 'text',
+ ]);
+ $fieldtextarea = self::getDataGenerator()->create_custom_field([
+ 'categoryid' => $fieldcategory->get('id'), 'name' => 'Textarea', 'shortname' => 'textarea', 'type' => 'textarea',
+ ]);
// Set the required capabilities by the external function
$contextid = context_system::instance()->id;
@@ -508,7 +510,10 @@ class externallib_test extends externallib_advanced_testcase {
$course4['fullname'] = 'Test course with custom fields';
$course4['shortname'] = 'Testcoursecustomfields';
$course4['categoryid'] = $category->id;
- $course4['customfields'] = [['shortname' => $customfield['shortname'], 'value' => 'Test value']];
+ $course4['customfields'] = [
+ ['shortname' => $fieldtext->get('shortname'), 'value' => 'And I want to tell you so much'],
+ ['shortname' => $fieldtextarea->get('shortname'), 'value' => 'I love you'],
+ ];
$courses = array($course4, $course1, $course2, $course3);
$createdcourses = core_course_external::create_courses($courses);
@@ -580,7 +585,10 @@ class externallib_test extends externallib_advanced_testcase {
$handler = core_course\customfield\course_handler::create();
$customfields = $handler->export_instance_data_object($createdcourse['id']);
- $this->assertEquals((object)['test' => 'Test value'], $customfields);
+ $this->assertEquals((object) [
+ 'text' => 'And I want to tell you so much',
+ 'textarea' => '
I love you
',
+ ], $customfields);
} else {
throw new moodle_exception('Unexpected shortname');
}
@@ -1857,12 +1865,17 @@ class externallib_test extends externallib_advanced_testcase {
// Course with custom fields.
$fieldcategory = self::getDataGenerator()->create_custom_field_category(['name' => 'Other fields']);
- $customfield = ['shortname' => 'test', 'name' => 'Custom field', 'type' => 'text',
- 'categoryid' => $fieldcategory->get('id'),
- 'configdata' => ['visibility' => \core_course\customfield\course_handler::VISIBLETOALL, 'locked' => 1]];
- $field = self::getDataGenerator()->create_custom_field($customfield);
- $originalcourse3 = self::getDataGenerator()->create_course(['customfield_test' => 'Test value']);
+ $fieldtext = self::getDataGenerator()->create_custom_field([
+ 'categoryid' => $fieldcategory->get('id'), 'name' => 'Text', 'shortname' => 'text', 'type' => 'text', 'configdata' => [
+ 'locked' => 1,
+ ],
+ ]);
+ $fieldtextarea = self::getDataGenerator()->create_custom_field([
+ 'categoryid' => $fieldcategory->get('id'), 'name' => 'Textarea', 'shortname' => 'textarea', 'type' => 'textarea',
+ ]);
+
+ $originalcourse3 = self::getDataGenerator()->create_course();
self::getDataGenerator()->enrol_user($USER->id, $originalcourse3->id, $roleid);
// Course values to be updated.
@@ -1895,8 +1908,11 @@ class externallib_test extends externallib_advanced_testcase {
$course2['forcetheme'] = 'classic';
$course3['id'] = $originalcourse3->id;
- $updatedcustomfieldvalue = ['shortname' => 'test', 'value' => 'Updated test value'];
- $course3['customfields'] = [$updatedcustomfieldvalue];
+ $course3['customfields'] = [
+ ['shortname' => $fieldtext->get('shortname'), 'value' => 'I long to see the sunlight in your hair'],
+ ['shortname' => $fieldtextarea->get('shortname'), 'value' => 'And tell you time and time again'],
+ ];
+
$courses = array($course1, $course2, $course3);
$updatedcoursewarnings = core_course_external::update_courses($courses);
@@ -1937,7 +1953,10 @@ class externallib_test extends externallib_advanced_testcase {
}
$this->assertEquals($course2['enablecompletion'], $courseinfo->enablecompletion);
- $this->assertEquals(['test' => null], (array)$customfields);
+ $this->assertEquals((object) [
+ 'text' => null,
+ 'textarea' => null,
+ ], $customfields);
} else if ($course['id'] == $course1['id']) {
$this->assertEquals($course1['fullname'], $courseinfo->fullname);
$this->assertEquals($course1['shortname'], $courseinfo->shortname);
@@ -1947,9 +1966,15 @@ class externallib_test extends externallib_advanced_testcase {
$this->assertEquals(5, course_get_format($course['id'])->get_last_section_number());
$this->assertEquals(0, $courseinfo->newsitems);
$this->assertEquals(FORMAT_MOODLE, $courseinfo->summaryformat);
- $this->assertEquals(['test' => null], (array)$customfields);
+ $this->assertEquals((object) [
+ 'text' => null,
+ 'textarea' => null,
+ ], $customfields);
} else if ($course['id'] == $course3['id']) {
- $this->assertEquals(['test' => $updatedcustomfieldvalue['value']], (array)$customfields);
+ $this->assertEquals((object) [
+ 'text' => 'I long to see the sunlight in your hair',
+ 'textarea' => 'And tell you time and time again
',
+ ], $customfields);
} else {
throw new moodle_exception('Unexpected shortname');
}
@@ -2087,14 +2112,18 @@ class externallib_test extends externallib_advanced_testcase {
$this->setUser($user);
self::getDataGenerator()->enrol_user($user->id, $course3['id'], $roleid);
- $newupdatedcustomfieldvalue = ['shortname' => 'test', 'value' => 'New updated value'];
- $course3['customfields'] = [$newupdatedcustomfieldvalue];
+ $course3['customfields'] = [
+ ['shortname' => 'text', 'value' => 'New updated value'],
+ ];
core_course_external::update_courses([$course3]);
// Custom field was not updated.
$customfields = \core_course\customfield\course_handler::create()->export_instance_data_object($course3['id']);
- $this->assertEquals(['test' => $updatedcustomfieldvalue['value']], (array)$customfields);
+ $this->assertEquals((object) [
+ 'text' => 'I long to see the sunlight in your hair',
+ 'textarea' => 'And tell you time and time again
',
+ ], $customfields);
}
/**
diff --git a/customfield/field/textarea/classes/data_controller.php b/customfield/field/textarea/classes/data_controller.php
index 3d52fe15bc4..a72d99c8bd3 100644
--- a/customfield/field/textarea/classes/data_controller.php
+++ b/customfield/field/textarea/classes/data_controller.php
@@ -88,7 +88,14 @@ class data_controller extends \core_customfield\data_controller {
if (!property_exists($datanew, $fieldname)) {
return;
}
+
+ // Normalise form data, for cases it's come from an external source.
$fromform = $datanew->$fieldname;
+ if (!is_array($fromform)) {
+ $fromform = ['text' => $fromform];
+ $fromform['format'] = $this->get('id') ? $this->get('valueformat') :
+ $this->get_field()->get_configdata_property('defaultvalueformat');
+ }
if (!$this->get('id')) {
$this->data->set('value', '');
diff --git a/customfield/tests/generator/lib.php b/customfield/tests/generator/lib.php
index 06cfe479f97..93a85c6a3d2 100644
--- a/customfield/tests/generator/lib.php
+++ b/customfield/tests/generator/lib.php
@@ -124,6 +124,7 @@ class core_customfield_generator extends component_generator_base {
'locked' => 0,
'visibility' => 2,
'defaultvalue' => '',
+ 'defaultvalueformat' => FORMAT_MOODLE,
'displaysize' => 0,
'maxlength' => 0,
'ispassword' => 0,