diff --git a/lib/classes/external/exporter.php b/lib/classes/external/exporter.php index bfaa6ef0918..3fe6673b17e 100644 --- a/lib/classes/external/exporter.php +++ b/lib/classes/external/exporter.php @@ -145,13 +145,14 @@ abstract class exporter { // If the field is PARAM_RAW and has a format field. if ($propertyformat = self::get_format_field($properties, $property)) { - if (!property_exists($record, $propertyformat)) { + $formatdefinition = $properties[$propertyformat]; + if (!property_exists($record, $propertyformat) && !array_key_exists('default', $formatdefinition)) { // Whoops, we got something that wasn't defined. throw new coding_exception('Unexpected property ' . $propertyformat); } $formatparams = $this->get_format_parameters($property); - $format = $record->$propertyformat; + $format = $record->$propertyformat ?? $formatdefinition['default']; list($text, $format) = \core_external\util::format_text($data->$property, $format, $formatparams['context'], $formatparams['component'], $formatparams['filearea'], $formatparams['itemid'], $formatparams['options']); diff --git a/lib/tests/exporter_test.php b/lib/tests/exporter_test.php index bbcf5b43331..2c91e1c3f3b 100644 --- a/lib/tests/exporter_test.php +++ b/lib/tests/exporter_test.php @@ -29,6 +29,7 @@ use core_external\external_multiple_structure; use core_external\external_settings; use core_external\external_single_structure; use core_external\external_value; +use core_external\util; /** * Exporter testcase. @@ -202,6 +203,49 @@ class exporter_test extends \advanced_testcase { // Assert nested elements are formatted correctly. $this->assertEquals('id', $properties['nestedarray']['type']['id']['description']); } + + /** + * Tests for the handling of the default attribute of format properties in exporters. + * + * @covers \core\external\exporter::export + * @return void + */ + public function test_export_format_no_default(): void { + global $PAGE; + $output = $PAGE->get_renderer('core'); + $syscontext = \context_system::instance(); + $related = [ + 'context' => $syscontext, + ] + $this->validrelated; + + // Pass a data that does not have the format property for stringA. + $data = [ + 'stringA' => '__Go to:__ [Moodle.org](https://moodle.org)', + 'intB' => 1, + ]; + + // Note: For testing purposes only. Never extend exporter implementation. Only extend from the base exporter class! + $testablexporterclass = new class($data, $related) extends core_testable_exporter { + /** + * Properties definition. + */ + public static function define_properties(): array { + $properties = parent::define_properties(); + $properties['stringAformat']['default'] = FORMAT_MARKDOWN; + return $properties; + } + }; + // For a property format with default set, it should be able to export a data even if the property format is not passed. + $result = $testablexporterclass->export($output); + $expected = 'Go to: Moodle.org'; + $this->assertStringContainsString($expected, $result->stringA); + $this->assertEquals(FORMAT_HTML, $result->stringAformat); + + // Passing data to an exporter with a required property format will throw an exception. + $exporter = new core_testable_exporter($data, $related); + $this->expectException(\coding_exception::class); + $exporter->export($output); + } } /**