Merge branch 'MDL-65132-master' of git://github.com/cescobedo/moodle
authorAndrew Nicols <andrew@nicols.co.uk>
Mon, 6 May 2019 13:02:29 +0000 (21:02 +0800)
committerAdrian Greeve <abgreeve@gmail.com>
Tue, 7 May 2019 08:24:40 +0000 (16:24 +0800)
1  2 
message/classes/api.php
message/tests/api_test.php
message/tests/externallib_test.php

@@@ -3326,9 -3332,61 +3335,65 @@@ class api 
              // Delete the messages now.
              $DB->delete_records('messages', ['conversationid' => $conversationid]);
          }
 +
 +        // Delete all favourite records for all users relating to this conversation.
 +        $service = \core_favourites\service_factory::get_service_for_component('core_message');
 +        $service->delete_favourites_by_type('message_conversations', $convcontext);
      }
+     /**
+      * Checks if a user can delete a message for all users.
+      *
+      * @param int $userid the user id of who we want to delete the message for all users
+      * @param int $messageid The message id
+      * @return bool Returns true if a user can delete the message for all users, false otherwise.
+      */
+     public static function can_delete_message_for_all_users(int $userid, int $messageid) : bool {
+         global $DB;
+         $sql = "SELECT mc.id, mc.contextid
+                   FROM {message_conversations} mc
+             INNER JOIN {messages} m
+                     ON mc.id = m.conversationid
+                  WHERE m.id = :messageid";
+         $conversation = $DB->get_record_sql($sql, ['messageid' => $messageid]);
+         if (!empty($conversation->contextid)) {
+             return has_capability('moodle/site:deleteanymessage',
+                 \context::instance_by_id($conversation->contextid), $userid);
+         }
+         return has_capability('moodle/site:deleteanymessage', \context_system::instance(), $userid);
+     }
+     /**
+      * Delete a message for all users.
+      *
+      * This function does not verify any permissions.
+      *
+      * @param int $messageid The message id
+      * @return void
+      */
+     public static function delete_message_for_all_users(int $messageid) {
+         global $DB, $USER;
+         if (!$DB->record_exists('messages', ['id' => $messageid])) {
+             return false;
+         }
+         // Get all members in the conversation where the message belongs.
+         $membersql = "SELECT mcm.id, mcm.userid
+                         FROM {message_conversation_members} mcm
+                   INNER JOIN {messages} m
+                           ON mcm.conversationid = m.conversationid
+                        WHERE m.id = :messageid";
+         $params = [
+             'messageid' => $messageid
+         ];
+         $members = $DB->get_records_sql($membersql, $params);
+         if ($members) {
+             foreach ($members as $member) {
+                 self::delete_message($member->userid, $messageid);
+             }
+         }
+     }
  }
@@@ -6957,16 -6895,179 +6957,187 @@@ class core_message_api_testcase extend
          $this->assertEquals(1, $DB->count_records('messages', ['id' => $g2m2]));
          $this->assertEquals(1, $DB->count_records('messages', ['id' => $g2m3]));
          $this->assertEquals(1, $DB->count_records('messages', ['id' => $g2m4]));
 +
 +        // Confirm favourites were deleted for both users.
 +        $user1service = \core_favourites\service_factory::get_service_for_user_context(context_user::instance($user1->id));
 +        $this->assertFalse($user1service->favourite_exists('core_message', 'message_conversations', $groupconversation1->id,
 +            $coursecontext1));
 +        $user2service = \core_favourites\service_factory::get_service_for_user_context(context_user::instance($user1->id));
 +        $this->assertFalse($user2service->favourite_exists('core_message', 'message_conversations', $groupconversation1->id,
 +            $coursecontext1));
      }
  
+     /**
+      * Tests the user can delete message for all users as a teacher.
+      */
+     public function test_can_delete_message_for_all_users_teacher() {
+         global $DB;
+         $this->resetAfterTest(true);
+         // Create fake data to test it.
+         list($teacher, $student1, $student2, $convgroup, $convindividual) = $this->create_delete_message_test_data();
+         // Allow Teacher can delete messages for all.
+         $editingteacher = $DB->get_record('role', ['shortname' => 'editingteacher']);
+         assign_capability('moodle/site:deleteanymessage', CAP_ALLOW, $editingteacher->id, context_system::instance());
+         // Set as the first user.
+         $this->setUser($teacher);
+         // Send a message to private conversation and in a group conversation.
+         $messageidind = \core_message\tests\helper::send_fake_message_to_conversation($teacher, $convindividual->id);
+         $messageidgrp = \core_message\tests\helper::send_fake_message_to_conversation($teacher, $convgroup->id);
+         // Teacher cannot delete message for everyone in a private conversation.
+         $this->assertFalse(\core_message\api::can_delete_message_for_all_users($teacher->id, $messageidind));
+         // Teacher can delete message for everyone in a group conversation.
+         $this->assertTrue(\core_message\api::can_delete_message_for_all_users($teacher->id, $messageidgrp));
+     }
+     /**
+      * Tests the user can delete message for all users as a student.
+      */
+     public function test_can_delete_message_for_all_users_student() {
+         $this->resetAfterTest(true);
+         // Create fake data to test it.
+         list($teacher, $student1, $student2, $convgroup, $convindividual) = $this->create_delete_message_test_data();
+         // Set as the first user.
+         $this->setUser($student1);
+         // Send a message to private conversation and in a group conversation.
+         $messageidind = \core_message\tests\helper::send_fake_message_to_conversation($teacher, $convindividual->id);
+         $messageidgrp = \core_message\tests\helper::send_fake_message_to_conversation($teacher, $convgroup->id);
+         // Student1 cannot delete message for everyone in a private conversation.
+         $this->assertFalse(\core_message\api::can_delete_message_for_all_users($student1->id, $messageidind));
+         // Student1 cannot delete message for everyone in a group conversation.
+         $this->assertFalse(\core_message\api::can_delete_message_for_all_users($student1->id, $messageidgrp));
+     }
+     /**
+      * Tests tdelete message for all users in group conversation.
+      */
+     public function test_delete_message_for_all_users_group_conversation() {
+         global $DB;
+         $this->resetAfterTest(true);
+         // Create fake data to test it.
+         list($teacher, $student1, $student2, $convgroup, $convindividual) = $this->create_delete_message_test_data();
+         // Send 3 messages to a group conversation.
+         $mgid1 = \core_message\tests\helper::send_fake_message_to_conversation($teacher, $convgroup->id);
+         $mgid2 = \core_message\tests\helper::send_fake_message_to_conversation($student1, $convgroup->id);
+         $mgid3 = \core_message\tests\helper::send_fake_message_to_conversation($student2, $convgroup->id);
+         // Delete message 1 for all users.
+         \core_message\api::delete_message_for_all_users($mgid1);
+         // Get the messages to check if the message 1 was deleted for teacher.
+         $convmessages1 = \core_message\api::get_conversation_messages($teacher->id, $convgroup->id);
+         // Only has to remains 2 messages.
+         $this->assertCount(2, $convmessages1['messages']);
+         // Check if no one of the two messages is message 1.
+         foreach ($convmessages1['messages'] as $message) {
+             $this->assertNotEquals($mgid1, $message->id);
+         }
+         // Get the messages to check if the message 1 was deleted for student1.
+         $convmessages2 = \core_message\api::get_conversation_messages($student1->id, $convgroup->id);
+         // Only has to remains 2 messages.
+         $this->assertCount(2, $convmessages2['messages']);
+         // Check if no one of the two messages is message 1.
+         foreach ($convmessages2['messages'] as $message) {
+             $this->assertNotEquals($mgid1, $message->id);
+         }
+         // Get the messages to check if the message 1 was deleted for student2.
+         $convmessages3 = \core_message\api::get_conversation_messages($student2->id, $convgroup->id);
+         // Only has to remains 2 messages.
+         $this->assertCount(2, $convmessages3['messages']);
+         // Check if no one of the two messages is message 1.
+         foreach ($convmessages3['messages'] as $message) {
+             $this->assertNotEquals($mgid1, $message->id);
+         }
+     }
+     /**
+      * Tests delete message for all users in private conversation.
+      */
+     public function test_delete_message_for_all_users_individual_conversation() {
+         global $DB;
+         $this->resetAfterTest(true);
+         // Create fake data to test it.
+         list($teacher, $student1, $student2, $convgroup, $convindividual) = $this->create_delete_message_test_data();
+         // Send 2 messages in a individual conversation.
+         $mid1 = \core_message\tests\helper::send_fake_message_to_conversation($teacher, $convindividual->id);
+         $mid2 = \core_message\tests\helper::send_fake_message_to_conversation($student1, $convindividual->id);
+         // Delete the first message for all users.
+         \core_message\api::delete_message_for_all_users($mid1);
+         // Get the messages to check if the message 1 was deleted for teacher.
+         $convmessages1 = \core_message\api::get_conversation_messages($teacher->id, $convindividual->id);
+         // Only has to remains 1 messages for teacher.
+         $this->assertCount(1, $convmessages1['messages']);
+         // Check the one messages remains not is the first message.
+         $this->assertNotEquals($mid1, $convmessages1['messages'][0]->id);
+         // Get the messages to check if the message 1 was deleted for student1.
+         $convmessages2 = \core_message\api::get_conversation_messages($student1->id, $convindividual->id);
+         // Only has to remains 1 messages for student1.
+         $this->assertCount(1, $convmessages2['messages']);
+         // Check the one messages remains not is the first message.
+         $this->assertNotEquals($mid1, $convmessages2['messages'][0]->id);
+     }
+     /**
+      * Helper to seed the database with initial state with data.
+      */
+     protected function create_delete_message_test_data() {
+         // Create some users.
+         $teacher = self::getDataGenerator()->create_user();
+         $student1 = self::getDataGenerator()->create_user();
+         $student2 = self::getDataGenerator()->create_user();
+         // Create a course and enrol the users.
+         $course = $this->getDataGenerator()->create_course();
+         $coursecontext = context_course::instance($course->id);
+         $this->getDataGenerator()->enrol_user($teacher->id, $course->id, 'editingteacher');
+         $this->getDataGenerator()->enrol_user($student1->id, $course->id, 'student');
+         $this->getDataGenerator()->enrol_user($student2->id, $course->id, 'student');
+         // Create a group and added the users into.
+         $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
+         groups_add_member($group1->id, $teacher->id);
+         groups_add_member($group1->id, $student1->id);
+         groups_add_member($group1->id, $student2->id);
+         // Create a group conversation linked with the course.
+         $convgroup = \core_message\api::create_conversation(
+             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
+             [$teacher->id, $student1->id, $student2->id],
+             'Group test delete for everyone', \core_message\api::MESSAGE_CONVERSATION_ENABLED,
+             'core_group',
+             'groups',
+             $group1->id,
+             context_course::instance($course->id)->id
+         );
+         // Create and individual conversation.
+         $convindividual = \core_message\api::create_conversation(
+             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
+             [$teacher->id, $student1->id]
+         );
+         return [$teacher, $student1, $student2, $convgroup, $convindividual];
+     }
      /**
       * Comparison function for sorting contacts.
       *
Simple merge