From eec2d09f84d47ef1118b530583da781a844f5117 Mon Sep 17 00:00:00 2001 From: Jake Dallimore Date: Tue, 21 Jan 2020 11:04:54 +0800 Subject: [PATCH] MDL-67585 core_course: add exporter for course content items An exporter will allow let us add calculated fields like 'favourited' to the data being transferred. --- .../course_content_item_exporter.php | 123 ++++++++++++++++++ .../course_content_items_exporter.php | 104 +++++++++++++++ course/tests/exporters_content_item_test.php | 74 +++++++++++ course/tests/exporters_content_items_test.php | 68 ++++++++++ 4 files changed, 369 insertions(+) create mode 100644 course/classes/local/exporters/course_content_item_exporter.php create mode 100644 course/classes/local/exporters/course_content_items_exporter.php create mode 100644 course/tests/exporters_content_item_test.php create mode 100644 course/tests/exporters_content_items_test.php diff --git a/course/classes/local/exporters/course_content_item_exporter.php b/course/classes/local/exporters/course_content_item_exporter.php new file mode 100644 index 00000000000..855a2ebf1cb --- /dev/null +++ b/course/classes/local/exporters/course_content_item_exporter.php @@ -0,0 +1,123 @@ +. + +/** + * Contains the course_content_item_exporter class. + * + * @package core + * @subpackage course + * @copyright 2020 Jake Dallimore + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace core_course\local\exporters; + +defined('MOODLE_INTERNAL') || die(); + +use core\external\exporter; +use core_course\local\entity\content_item; + +/** + * The course_content_item_exporter class. + * + * @copyright 2020 Jake Dallimore + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class course_content_item_exporter extends exporter { + + /** @var content_item $contentitem the content_item to export. */ + private $contentitem; + + /** + * The course_content_item_exporter constructor. + * + * @param content_item $contentitem the content item to export. + * @param array $related the array of related objects used during export. + */ + public function __construct(content_item $contentitem, array $related = []) { + $this->contentitem = $contentitem; + + return parent::__construct($contentitem, $related); + } + + /** + * Definition of all properties originating in the export target, \core_course\local\entity\content_item. + * + * @return array The array of property values, indexed by name. + */ + protected static function define_properties() { + return [ + 'id' => ['type' => PARAM_INT, 'description' => 'The id of the content item'], + 'name' => ['type' => PARAM_TEXT, 'description' => 'Name of the content item'], + 'title' => ['type' => PARAM_TEXT, 'description' => 'The string title of the content item, human readable'], + 'link' => ['type' => PARAM_URL, 'description' => 'The link to the content item creation page'], + 'icon' => ['type' => PARAM_RAW, 'description' => 'Html containing the icon for the content item'], + 'help' => ['type' => PARAM_RAW, 'description' => 'Html description / help for the content item'], + 'archetype' => ['type' => PARAM_RAW, 'description' => 'The archetype of the module exposing the content item'], + 'componentname' => ['type' => PARAM_TEXT, 'description' => 'The name of the component exposing the content item'], + ]; + } + + /** + * Definition of all properties which are either calculated or originate in a related domain object. + * + * @return array The array of property values, indexed by name. + */ + protected static function define_other_properties() { + // This will hold user-dependant properties such as whether the item is starred or recommended. + return []; + } + + /** + * Get ALL properties for the content_item DTO being exported. + * + * These properties are a mix of: + * - readonly properties of the primary object (content_item) being exported. + * - calculated values + * - properties originating from the related domain objects. + * + * Normally, those properties defined in get_properties() are added to the export automatically as part of the superclass code, + * provided they are public properties on the export target. In this case, the export target is content_item, which doesn't + * provide public access to its properties, so those are fetched via their respective getters here. + * + * @param \renderer_base $output + * @return array The array of property values, indexed by name. + */ + protected function get_other_values(\renderer_base $output) { + $properties = [ + 'id' => $this->contentitem->get_id(), + 'name' => $this->contentitem->get_name(), + 'title' => $this->contentitem->get_title()->get_value(), + 'link' => $this->contentitem->get_link()->out(false), + 'icon' => $this->contentitem->get_icon(), + 'help' => $this->contentitem->get_help(), + 'archetype' => $this->contentitem->get_archetype(), + 'componentname' => $this->contentitem->get_component_name(), + ]; + + return $properties; + } + + /** + * Define the list of related objects, used by this exporter. + * + * @return array the list of related objects. + */ + protected static function define_related(): array { + return [ + 'context' => 'context' + ]; + } +} diff --git a/course/classes/local/exporters/course_content_items_exporter.php b/course/classes/local/exporters/course_content_items_exporter.php new file mode 100644 index 00000000000..177e49f86c3 --- /dev/null +++ b/course/classes/local/exporters/course_content_items_exporter.php @@ -0,0 +1,104 @@ +. + +/** + * Contains the course_content_items_exporter class. + * + * @package core + * @subpackage course + * @copyright 2020 Jake Dallimore + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace core_course\local\exporters; + +defined('MOODLE_INTERNAL') || die(); + +use core\external\exporter; +use core_course\local\entity\content_item; + +/** + * The course_content_items_exporter class. + * + * @copyright 2020 Jake Dallimore + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class course_content_items_exporter extends exporter { + + /** @var content_item[] the array of content items. */ + private $contentitems; + + /** + * The course_content_items_exporter constructor. + * + * @param array $contentitems the array of \core_course\local\entity\content_item objects to export. + * @param array $related any related objects, see define_related for what's expected. + */ + public function __construct(array $contentitems, array $related) { + $this->contentitems = $contentitems; + + parent::__construct($contentitems, $related); + } + + /** + * Return the properties defining this export. + * + * @return array the array of properties. + */ + public static function define_properties() { + return [ + 'content_items' => [ + 'type' => course_content_item_exporter::read_properties_definition(), + 'multiple' => true + ] + ]; + } + + /** + * Generate and return the data for this export. + * + * @param \renderer_base $output + * @return array the array of course content_items + */ + protected function get_other_values(\renderer_base $output) { + + $contentitemexport = function(content_item $contentitem) use ($output) { + $exporter = new course_content_item_exporter( + $contentitem, + [ + 'context' => $this->related['context'] + ] + ); + return $exporter->export($output); + }; + + $exportedcontentitems = array_map($contentitemexport, $this->contentitems); + + return [ + 'content_items' => $exportedcontentitems + ]; + } + + /** + * Define the list of related objects, used by this exporter. + * + * @return array the list of related objects. + */ + protected static function define_related() { + return [ + 'context' => '\context' + ]; + } +} diff --git a/course/tests/exporters_content_item_test.php b/course/tests/exporters_content_item_test.php new file mode 100644 index 00000000000..32c0018653b --- /dev/null +++ b/course/tests/exporters_content_item_test.php @@ -0,0 +1,74 @@ +. + +/** + * Contains the tests for the course_content_item_exporter class. + * + * @package core + * @subpackage course + * @copyright 2020 Jake Dallimore + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace tests\core_course; + +defined('MOODLE_INTERNAL') || die(); + +use core_course\local\exporters\course_content_item_exporter; +use core_course\local\repository\content_item_readonly_repository; + +/** + * The tests for the course_content_item_exporter class. + * + * @copyright 2020 Jake Dallimore + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class exporters_course_content_item_testcase extends \advanced_testcase { + + /** + * Test confirming a content_item can be exported for a course. + */ + public function test_export_course_content_item() { + $this->resetAfterTest(); + global $PAGE; + + $course = $this->getDataGenerator()->create_course(); + $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher'); + $cir = new content_item_readonly_repository(); + $contentitems = $cir->find_all_for_course($course, $user); + $contentitem = array_shift($contentitems); + + $ciexporter = new course_content_item_exporter($contentitem, ['context' => \context_course::instance($course->id)]); + $renderer = $PAGE->get_renderer('core'); + $exporteditem = $ciexporter->export($renderer); + + $this->assertObjectHasAttribute('id', $exporteditem); + $this->assertEquals($exporteditem->id, $contentitem->get_id()); + $this->assertObjectHasAttribute('name', $exporteditem); + $this->assertEquals($exporteditem->name, $contentitem->get_name()); + $this->assertObjectHasAttribute('title', $exporteditem); + $this->assertEquals($exporteditem->title, $contentitem->get_title()->get_value()); + $this->assertObjectHasAttribute('link', $exporteditem); + $this->assertEquals($exporteditem->link, $contentitem->get_link()->out(false)); + $this->assertObjectHasAttribute('icon', $exporteditem); + $this->assertEquals($exporteditem->icon, $contentitem->get_icon()); + $this->assertObjectHasAttribute('help', $exporteditem); + $this->assertEquals($exporteditem->help, $contentitem->get_help()); + $this->assertObjectHasAttribute('archetype', $exporteditem); + $this->assertEquals($exporteditem->archetype, $contentitem->get_archetype()); + $this->assertObjectHasAttribute('componentname', $exporteditem); + $this->assertEquals($exporteditem->componentname, $contentitem->get_component_name()); + } +} diff --git a/course/tests/exporters_content_items_test.php b/course/tests/exporters_content_items_test.php new file mode 100644 index 00000000000..0e6065a8b36 --- /dev/null +++ b/course/tests/exporters_content_items_test.php @@ -0,0 +1,68 @@ +. + +/** + * Contains the tests for the course_content_items_exporter class. + * + * @package core + * @subpackage course + * @copyright 2020 Jake Dallimore + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace tests\core_course; + +defined('MOODLE_INTERNAL') || die(); + +use core_course\local\exporters\course_content_items_exporter; +use core_course\local\repository\content_item_readonly_repository; + +/** + * The tests for the course_content_items_exporter class. + * + * @copyright 2020 Jake Dallimore + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class exporters_course_content_items_testcase extends \advanced_testcase { + + /** + * Test confirming the collection of content_items can be exported for a course. + */ + public function test_export_course_content_items() { + $this->resetAfterTest(); + global $PAGE; + + $course = $this->getDataGenerator()->create_course(); + $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher'); + $cir = new content_item_readonly_repository(); + $contentitems = $cir->find_all_for_course($course, $user); + + $ciexporter = new course_content_items_exporter($contentitems, ['context' => \context_course::instance($course->id)]); + $renderer = $PAGE->get_renderer('core'); + $exportedcontentitems = $ciexporter->export($renderer); + + $this->assertObjectHasAttribute('content_items', $exportedcontentitems); + foreach ($exportedcontentitems->content_items as $key => $dto) { + $this->assertObjectHasAttribute('id', $dto); + $this->assertObjectHasAttribute('name', $dto); + $this->assertObjectHasAttribute('title', $dto); + $this->assertObjectHasAttribute('link', $dto); + $this->assertObjectHasAttribute('icon', $dto); + $this->assertObjectHasAttribute('help', $dto); + $this->assertObjectHasAttribute('archetype', $dto); + $this->assertObjectHasAttribute('componentname', $dto); + } + } +}