From 407856338c2df8e5f90dea6bebd765ef18959cd1 Mon Sep 17 00:00:00 2001 From: Rodrigo Mady da Silva Date: Thu, 28 Apr 2022 17:05:42 -0300 Subject: [PATCH] MDL-74568 mod_chat: Add Webservice mod_chat_view_sessions --- mod/chat/classes/external/view_sessions.php | 121 ++++++++++++++++ mod/chat/db/services.php | 9 ++ .../tests/external/view_sessions_test.php | 133 ++++++++++++++++++ mod/chat/version.php | 2 +- 4 files changed, 264 insertions(+), 1 deletion(-) create mode 100644 mod/chat/classes/external/view_sessions.php create mode 100644 mod/chat/tests/external/view_sessions_test.php diff --git a/mod/chat/classes/external/view_sessions.php b/mod/chat/classes/external/view_sessions.php new file mode 100644 index 00000000000..474cc11d60b --- /dev/null +++ b/mod/chat/classes/external/view_sessions.php @@ -0,0 +1,121 @@ +. + +namespace mod_chat\external; + +use core_external\external_api; +use core_external\external_function_parameters; +use core_external\external_single_structure; +use core_external\external_value; +use core_external\external_warnings; + +/** + * External service to log viewed previous chat sessions. + * + * @package mod_chat + * @category external + * @copyright 2023 Rodrigo Mady + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since Moodle 4.3 + */ +class view_sessions extends external_api { + /** + * Returns description of method parameters + * + * @return external_function_parameters + */ + public static function execute_parameters(): external_function_parameters { + return new external_function_parameters([ + 'cmid' => new external_value(PARAM_INT, 'Course module id', VALUE_REQUIRED), + 'start' => new external_value(PARAM_INT, 'Session start time', VALUE_DEFAULT, 0), + 'end' => new external_value(PARAM_INT, 'Session end time', VALUE_DEFAULT, 0), + ]); + } + + /** + * Execute the chat view sessions event. + * + * @param int $cmid the chat course module id + * @param null|int $start + * @param null|int $end + * @return array + * @throws \restricted_context_exception + */ + public static function execute(int $cmid, ?int $start = 0, ?int $end = 0): array { + global $DB; + $warnings = []; + $status = false; + // Validate the cmid ID. + [ + 'cmid' => $cmid, + 'start' => $start, + 'end' => $end, + ] = self::validate_parameters(self::execute_parameters(), [ + 'cmid' => $cmid, + 'start' => $start, + 'end' => $end, + ]); + if (!$cm = get_coursemodule_from_id('chat', $cmid)) { + throw new \moodle_exception('invalidcoursemodule', 'error'); + } + if (!$chat = $DB->get_record('chat', ['id' => $cm->instance])) { + throw new \moodle_exception('invalidcoursemodule', 'error'); + } + + $context = \context_module::instance($cm->id); + self::validate_context($context); + + // Check capability. + if (has_capability('mod/chat:readlog', $context)) { + $params = [ + 'context' => $context, + 'objectid' => $chat->id, + 'other' => [ + 'start' => $start, + 'end' => $end + ] + ]; + $event = \mod_chat\event\sessions_viewed::create($params); + $status = true; + $event->add_record_snapshot('chat', $chat); + $event->trigger(); + } else { + $warnings[] = [ + 'item' => $cm->id, + 'warningcode' => 'nopermissiontoseethechatlog', + 'message' => get_string('nopermissiontoseethechatlog', 'chat') + ]; + } + + $result = [ + 'status' => $status, + 'warnings' => $warnings + ]; + return $result; + } + + /** + * Describe the return structure of the external service. + * + * @return external_single_structure + */ + public static function execute_returns(): external_single_structure { + return new external_single_structure([ + 'status' => new external_value(PARAM_BOOL, 'status: true if success'), + 'warnings' => new external_warnings() + ]); + } +} diff --git a/mod/chat/db/services.php b/mod/chat/db/services.php index 6bbd9289600..6cc8a0ffe3e 100644 --- a/mod/chat/db/services.php +++ b/mod/chat/db/services.php @@ -96,4 +96,13 @@ $functions = array( 'type' => 'read', 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) ), + + 'mod_chat_view_sessions' => [ + 'classname' => 'mod_chat\external\view_sessions', + 'methodname' => 'execute', + 'description' => 'Trigger the chat session viewed event.', + 'type' => 'write', + 'capabilities' => 'mod/chat:readlog', + 'services' => [MOODLE_OFFICIAL_MOBILE_SERVICE] + ], ); diff --git a/mod/chat/tests/external/view_sessions_test.php b/mod/chat/tests/external/view_sessions_test.php new file mode 100644 index 00000000000..ad66d96ec63 --- /dev/null +++ b/mod/chat/tests/external/view_sessions_test.php @@ -0,0 +1,133 @@ +. + +/** + * Tests for external function mod_chat_view_sessions. + * + * @package mod_chat + * @category external + * @copyright 2022 Rodrigo Mady + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since Moodle 4.3 + */ + +namespace mod_chat\external; + +use externallib_advanced_testcase; +use moodle_exception; + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; + +require_once($CFG->dirroot . '/webservice/tests/helpers.php'); + +/** + * Test Class for external function mod_chat_view_sessions. + * + * @package mod_chat + * @category external + * @copyright 2023 Rodrigo Mady + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since Moodle 4.3 + * @coversDefaultClass \mod_chat\external\view_sessions + */ +class view_sessions_test extends externallib_advanced_testcase { + + /** + * Prepare the test. + * + * @return array + */ + private function prepare_test_data(): array { + global $DB; + $this->resetAfterTest(true); + $course = $this->getDataGenerator()->create_course(); + $student1 = $this->getDataGenerator()->create_and_enrol($course); + $chat = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]); + $context = \context_module::instance($chat->cmid); + $studentroleid = $DB->get_field('role', 'id', ['shortname' => 'student']); + assign_capability('mod/chat:readlog', CAP_ALLOW, $studentroleid, $context, true); + $this->setUser($student1); + + return [ + 'chat' => $chat, + ]; + } + + /** + * Helper to call view_sessions WS function. + * + * @param int $cmid + * @param int $sessionstart + * @param int $sessionend + * @return array + */ + protected function view_sessions(int $cmid, int $sessionstart = 0, int $sessionend = 0): array { + $result = view_sessions::execute($cmid, $sessionstart, $sessionend); + return \core_external\external_api::clean_returnvalue(view_sessions::execute_returns(), $result); + } + + /** + * Test for webservice view sessions. + * @covers ::execute + */ + public function test_view_sessions(): void { + $data = $this->prepare_test_data(); + $result = $this->view_sessions($data['chat']->cmid); + $this->assertArrayHasKey('status', $result); + $this->assertArrayHasKey('warnings', $result); + $this->assertTrue($result['status']); + } + + /** + * Test for webservice view sessions without capability. + * @covers ::execute + */ + public function test_view_sessions_without_capability(): void { + global $DB; + $data = $this->prepare_test_data(); + $context = \context_module::instance($data['chat']->cmid); + $studentroleid = $DB->get_field('role', 'id', ['shortname' => 'student']); + assign_capability('mod/chat:readlog', CAP_PROHIBIT, $studentroleid, $context, true); + $result = $this->view_sessions($data['chat']->cmid); + $this->assertArrayHasKey('status', $result); + $this->assertArrayHasKey('warnings', $result); + $this->assertFalse($result['status']); + $this->assertEquals(get_string('nopermissiontoseethechatlog', 'chat'), $result['warnings'][0]['message']); + } + + /** + * Test for webservice view sessions with start and end dates. + * @covers ::execute + */ + public function test_view_sessions_with_start_end_dates(): void { + $data = $this->prepare_test_data(); + $result = $this->view_sessions($data['chat']->cmid, strtotime('today'), strtotime('tomorrow')); + $this->assertArrayHasKey('status', $result); + $this->assertArrayHasKey('warnings', $result); + $this->assertTrue($result['status']); + } + + /** + * Test execute with no valid instance of cmid. + * @covers ::execute + */ + public function test_view_sessions_no_instance(): void { + $this->expectException(moodle_exception::class); + $this->view_sessions(1234); + } +} diff --git a/mod/chat/version.php b/mod/chat/version.php index 504e10b9127..3dd853bf062 100644 --- a/mod/chat/version.php +++ b/mod/chat/version.php @@ -24,6 +24,6 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2023042400; // The current module version (Date: YYYYMMDDXX). +$plugin->version = 2023042401; // The current module version (Date: YYYYMMDDXX). $plugin->requires = 2023041800; // Requires this Moodle version. $plugin->component = 'mod_chat'; // Full name of the plugin (used for diagnostics).