diff --git a/lib/db/services.php b/lib/db/services.php index 8060d7fb83a..76496ac5632 100644 --- a/lib/db/services.php +++ b/lib/db/services.php @@ -906,6 +906,15 @@ $functions = array( 'capabilities' => '', ), + 'core_message_delete_message' => array( + 'classname' => 'core_message_external', + 'methodname' => 'delete_message', + 'classpath' => 'message/externallib.php', + 'description' => 'Deletes a message.', + 'type' => 'write', + 'capabilities' => 'moodle/site:deleteownmessage', + ), + // === notes related functions === 'moodle_notes_create_notes' => array( @@ -1216,6 +1225,7 @@ $services = array( 'core_completion_get_course_completion_status', 'core_user_view_user_list', 'core_message_mark_message_read', + 'core_message_delete_message', 'core_notes_view_notes', 'mod_forum_view_forum_discussion', 'core_user_view_user_profile', diff --git a/message/externallib.php b/message/externallib.php index 962216f7c9c..35aef7e9db1 100644 --- a/message/externallib.php +++ b/message/externallib.php @@ -25,6 +25,7 @@ */ require_once("$CFG->libdir/externallib.php"); +require_once($CFG->dirroot . "/message/lib.php"); /** * Message external functions @@ -69,7 +70,6 @@ class core_message_external extends external_api { */ public static function send_instant_messages($messages = array()) { global $CFG, $USER, $DB; - require_once($CFG->dirroot . "/message/lib.php"); // Check if messaging is enabled. if (!$CFG->messaging) { @@ -652,7 +652,6 @@ class core_message_external extends external_api { public static function get_messages($useridto, $useridfrom = 0, $type = 'both', $read = true, $newestfirst = true, $limitfrom = 0, $limitnum = 0) { global $CFG, $USER; - require_once($CFG->dirroot . "/message/lib.php"); $warnings = array(); @@ -853,7 +852,6 @@ class core_message_external extends external_api { */ public static function get_blocked_users($userid) { global $CFG, $USER, $PAGE; - require_once($CFG->dirroot . "/message/lib.php"); // Warnings array, it can be empty at the end but is mandatory. $warnings = array(); @@ -957,7 +955,6 @@ class core_message_external extends external_api { */ public static function mark_message_read($messageid, $timeread) { global $CFG, $DB, $USER; - require_once($CFG->dirroot . "/message/lib.php"); // Check if private messaging between users is allowed. if (empty($CFG->messaging)) { @@ -1008,6 +1005,90 @@ class core_message_external extends external_api { ); } + /** + * Returns description of method parameters + * + * @return external_function_parameters + * @since 3.1 + */ + public static function delete_message_parameters() { + return new external_function_parameters( + array( + 'messageid' => new external_value(PARAM_INT, 'The message id'), + 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the message for'), + 'read' => new external_value(PARAM_BOOL, 'If is a message read', VALUE_DEFAULT, true) + ) + ); + } + + /** + * Deletes a message + * + * @param int $messageid the message id + * @param int $userid the user id of who we want to delete the message for + * @param bool $read if is a message read (default to true) + * @return external_description + * @throws moodle_exception + * @since 3.1 + */ + public static function delete_message($messageid, $userid, $read = true) { + global $CFG, $DB; + + // Check if private messaging between users is allowed. + if (empty($CFG->messaging)) { + throw new moodle_exception('disabled', 'message'); + } + + // Warnings array, it can be empty at the end but is mandatory. + $warnings = array(); + + // Validate params. + $params = array( + 'messageid' => $messageid, + 'userid' => $userid, + 'read' => $read + ); + $params = self::validate_parameters(self::delete_message_parameters(), $params); + + // Validate context. + $context = context_system::instance(); + self::validate_context($context); + + $messagestable = $params['read'] ? 'message_read' : 'message'; + $message = $DB->get_record($messagestable, array('id' => $params['messageid']), '*', MUST_EXIST); + + $user = core_user::get_user($params['userid'], '*', MUST_EXIST); + core_user::require_active_user($user); + + $status = false; + if (message_can_delete_message($message, $user->id)) { + $status = message_delete_message($message, $user->id);; + } else { + throw new moodle_exception('You do not have permission to delete this message'); + } + + $results = array( + 'status' => $status, + 'warnings' => $warnings + ); + return $results; + } + + /** + * Returns description of method result value + * + * @return external_description + * @since 3.1 + */ + public static function delete_message_returns() { + return new external_single_structure( + array( + 'status' => new external_value(PARAM_BOOL, 'True if the message was deleted, false otherwise'), + 'warnings' => new external_warnings() + ) + ); + } + } /** diff --git a/message/tests/externallib_test.php b/message/tests/externallib_test.php index c46828cdffc..dff81e44530 100644 --- a/message/tests/externallib_test.php +++ b/message/tests/externallib_test.php @@ -697,4 +697,105 @@ class core_message_externallib_testcase extends externallib_advanced_testcase { } + /** + * Test delete_message. + */ + public function test_delete_message() { + global $DB; + $this->resetAfterTest(true); + + $user1 = self::getDataGenerator()->create_user(); + $user2 = self::getDataGenerator()->create_user(); + $user3 = self::getDataGenerator()->create_user(); + $user4 = self::getDataGenerator()->create_user(); + + // Login as user1. + $this->setUser($user1); + $this->assertEquals(array(), core_message_external::create_contacts(array($user2->id, $user3->id))); + + // User user1 does not interchange messages with user3. + $m1to2 = message_post_message($user1, $user2, 'some random text 1', FORMAT_MOODLE); + $m2to3 = message_post_message($user2, $user3, 'some random text 3', FORMAT_MOODLE); + $m3to2 = message_post_message($user3, $user2, 'some random text 4', FORMAT_MOODLE); + $m3to4 = message_post_message($user3, $user4, 'some random text 4', FORMAT_MOODLE); + + // Retrieve all messages sent by user2 (they are currently unread). + $lastmessages = message_get_messages($user1->id, $user2->id, 0, false); + + // Delete a message not read, as a user from. + $result = core_message_external::delete_message($m1to2, $user1->id, false); + $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result); + $this->assertTrue($result['status']); + $this->assertCount(0, $result['warnings']); + $deletedmessage = $DB->get_record('message', array('id' => $m1to2)); + $this->assertNotEquals(0, $deletedmessage->timeuserfromdeleted); + + // Try to delete the same message again. + $result = core_message_external::delete_message($m1to2, $user1->id, false); + $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result); + $this->assertFalse($result['status']); + + // Try to delete a message that does not belong to me. + try { + $messageid = core_message_external::delete_message($m2to3, $user3->id, false); + $this->fail('Exception expected due invalid messageid.'); + } catch (moodle_exception $e) { + $this->assertEquals('You do not have permission to delete this message', $e->errorcode); + } + + $this->setUser($user3); + // Delete a message not read, as a user to. + $result = core_message_external::delete_message($m2to3, $user3->id, false); + $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result); + $this->assertTrue($result['status']); + $this->assertCount(0, $result['warnings']); + $deletedmessage = $DB->get_record('message', array('id' => $m2to3)); + $this->assertNotEquals(0, $deletedmessage->timeusertodeleted); + + // Delete a message read. + $message = $DB->get_record('message', array('id' => $m3to2)); + $messageid = message_mark_message_read($message, time()); + $result = core_message_external::delete_message($messageid, $user3->id); + $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result); + $this->assertTrue($result['status']); + $this->assertCount(0, $result['warnings']); + $deletedmessage = $DB->get_record('message_read', array('id' => $messageid)); + $this->assertNotEquals(0, $deletedmessage->timeuserfromdeleted); + + // Invalid message ids. + try { + $result = core_message_external::delete_message(-1, $user1->id); + $this->fail('Exception expected due invalid messageid.'); + } catch (dml_missing_record_exception $e) { + $this->assertEquals('invalidrecord', $e->errorcode); + } + + // Invalid user. + try { + $result = core_message_external::delete_message($m1to2, -1, false); + $this->fail('Exception expected due invalid user.'); + } catch (moodle_exception $e) { + $this->assertEquals('invaliduser', $e->errorcode); + } + + // Not active user. + delete_user($user2); + try { + $result = core_message_external::delete_message($m1to2, $user2->id, false); + $this->fail('Exception expected due invalid user.'); + } catch (moodle_exception $e) { + $this->assertEquals('userdeleted', $e->errorcode); + } + + // Now, as an admin, try to delete any message. + $this->setAdminUser(); + $result = core_message_external::delete_message($m3to4, $user4->id, false); + $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result); + $this->assertTrue($result['status']); + $this->assertCount(0, $result['warnings']); + $deletedmessage = $DB->get_record('message', array('id' => $m3to4)); + $this->assertNotEquals(0, $deletedmessage->timeusertodeleted); + + } + } diff --git a/version.php b/version.php index 3e00bee66e6..6200b85cdbc 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2015111600.02; // YYYYMMDD = weekly release date of this DEV branch. +$version = 2015113000.00; // YYYYMMDD = weekly release date of this DEV branch. // RR = release increments - 00 in DEV branches. // .XX = incremental changes.