mirror of
https://github.com/moodle/moodle.git
synced 2025-04-13 12:32:08 +02:00
MDL-64715 message: add support for self conversations
Added new MESSAGE_CONVERSATION_TYPE_SELF type for self-conversations and upgraded legacy self-conversations to the new type, removing repeated members in the message_conversation_members table. Besides, from now, a self-conversation will be created by default for all the existing users. All the self-conversations have been also starred and a default message will be displayed always to explain how to use them.
This commit is contained in:
parent
fcd7f0f982
commit
734b198fd3
@ -52,9 +52,11 @@ $string['defaultmessageoutputs'] = 'Notification settings';
|
||||
$string['defaults'] = 'Defaults';
|
||||
$string['deleteallconfirm'] = "Are you sure you would like to delete this entire conversation? This will not delete it for other conversation participants.";
|
||||
$string['deleteallmessages'] = "Delete all messages";
|
||||
$string['deleteallselfconfirm'] = "Are you sure you would like to delete this entire personal conversation?";
|
||||
$string['deleteconversation'] = "Delete conversation";
|
||||
$string['deleteselectedmessages'] = 'Delete selected messages';
|
||||
$string['deleteselectedmessagesconfirm'] = 'Are you sure you would like to delete the selected messages? This will not delete them for other conversation participants.';
|
||||
$string['deleteselectedmessagesconfirmselfconversation'] = 'Are you sure you would like to delete the selected personal messages?';
|
||||
$string['disableall'] = 'Disable notifications';
|
||||
$string['disabled'] = 'Messaging is disabled on this site';
|
||||
$string['disallowed'] = 'Disallowed';
|
||||
@ -211,6 +213,8 @@ $string['searchcombined'] = 'Search people and messages';
|
||||
$string['seeall'] = 'See all';
|
||||
$string['selectmessagestodelete'] = 'Select messages to delete';
|
||||
$string['selectnotificationtoview'] = 'Select from the list of notifications on the side to view more details';
|
||||
$string['selfconversation'] = 'Personal space';
|
||||
$string['selfconversationdefaultmessage'] = 'Save draft messages, links, notes etc. to access later.';
|
||||
$string['send'] = 'Send';
|
||||
$string['sender'] = '{$a}:';
|
||||
$string['sendingvia'] = 'Sending "{$a->provider}" via "{$a->processor}"';
|
||||
|
@ -109,6 +109,12 @@ class manager {
|
||||
// Get conversation type and name. We'll use this to determine which message subject to generate, depending on type.
|
||||
$conv = $DB->get_record('message_conversations', ['id' => $eventdata->convid], 'id, type, name');
|
||||
|
||||
// For now Self conversations are not processed because users are aware of the messages sent by themselves, so we
|
||||
// can return early.
|
||||
if ($conv->type == \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF) {
|
||||
return $savemessage->id;
|
||||
}
|
||||
|
||||
// We treat individual conversations the same as any direct message with 'userfrom' and 'userto' specified.
|
||||
// We know the other user, so set the 'userto' field so that the event code will get access to this field.
|
||||
// If this was a legacy caller (eventdata->userto is set), then use that instead, as we want to use the fields specified
|
||||
|
@ -1170,6 +1170,15 @@ $functions = array(
|
||||
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
|
||||
'ajax' => true
|
||||
),
|
||||
'core_message_get_self_conversation' => array(
|
||||
'classname' => 'core_message_external',
|
||||
'methodname' => 'get_self_conversation',
|
||||
'classpath' => 'message/externallib.php',
|
||||
'description' => 'Retrieve a self-conversation for a user',
|
||||
'type' => 'read',
|
||||
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
|
||||
'ajax' => true
|
||||
),
|
||||
'core_message_get_messages' => array(
|
||||
'classname' => 'core_message_external',
|
||||
'methodname' => 'get_messages',
|
||||
|
@ -2988,5 +2988,189 @@ function xmldb_main_upgrade($oldversion) {
|
||||
upgrade_main_savepoint(true, 2019041000.02);
|
||||
}
|
||||
|
||||
if ($oldversion < 2019041300.01) {
|
||||
// STEP 1. For the existing and migrated self-conversations, set the type to the new MESSAGE_CONVERSATION_TYPE_SELF, update
|
||||
// the convhash and star them.
|
||||
$sql = "SELECT mcm.conversationid, mcm.userid, MAX(mcm.id) as maxid
|
||||
FROM {message_conversation_members} mcm
|
||||
GROUP BY mcm.conversationid, mcm.userid
|
||||
HAVING COUNT(*) > 1";
|
||||
$selfconversationsrs = $DB->get_recordset_sql($sql);
|
||||
$maxids = [];
|
||||
foreach ($selfconversationsrs as $selfconversation) {
|
||||
$DB->update_record('message_conversations',
|
||||
['id' => $selfconversation->conversationid,
|
||||
'type' => \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF,
|
||||
'convhash' => \core_message\helper::get_conversation_hash([$selfconversation->userid])
|
||||
]
|
||||
);
|
||||
|
||||
// Star the existing self-conversation.
|
||||
$favouriterecord = new \stdClass();
|
||||
$favouriterecord->component = 'core_message';
|
||||
$favouriterecord->itemtype = 'message_conversations';
|
||||
$favouriterecord->itemid = $selfconversation->conversationid;
|
||||
$userctx = \context_user::instance($selfconversation->userid);
|
||||
$favouriterecord->contextid = $userctx->id;
|
||||
$favouriterecord->userid = $selfconversation->userid;
|
||||
$favouriterecord->timecreated = time();
|
||||
$favouriterecord->timemodified = $favouriterecord->timecreated;
|
||||
|
||||
$DB->insert_record('favourite', $favouriterecord);
|
||||
|
||||
// Set the self-conversation member with maxid to remove it later.
|
||||
$maxids[] = $selfconversation->maxid;
|
||||
}
|
||||
$selfconversationsrs->close();
|
||||
|
||||
// Remove the repeated member with the higher id for all the existing self-conversations.
|
||||
if (!empty($maxids)) {
|
||||
list($insql, $inparams) = $DB->get_in_or_equal($maxids);
|
||||
$DB->delete_records_select('message_conversation_members', "id $insql", $inparams);
|
||||
}
|
||||
|
||||
// STEP 2. Migrate existing self-conversation relying on old message tables, setting the type to the new
|
||||
// MESSAGE_CONVERSATION_TYPE_SELF and the convhash to the proper one. Star them also.
|
||||
|
||||
// On the messaging legacy tables, self-conversations are only present in the 'message_read' table, so we don't need to
|
||||
// check the content in the 'message' table.
|
||||
$select = 'useridfrom = useridto AND notification = 0';
|
||||
$legacyselfmessagesrs = $DB->get_recordset_select('message_read', $select);
|
||||
foreach ($legacyselfmessagesrs as $message) {
|
||||
// Get the self-conversation or create and star it if doesn't exist.
|
||||
$conditions = [
|
||||
'type' => \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF,
|
||||
'convhash' => \core_message\helper::get_conversation_hash([$message->useridfrom])
|
||||
];
|
||||
$selfconversation = $DB->get_record('message_conversations', $conditions);
|
||||
if (empty($selfconversation)) {
|
||||
// Create the self-conversation.
|
||||
$selfconversation = new \stdClass();
|
||||
$selfconversation->type = \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF;
|
||||
$selfconversation->convhash = \core_message\helper::get_conversation_hash([$message->useridfrom]);
|
||||
$selfconversation->enabled = 1;
|
||||
$selfconversation->timecreated = time();
|
||||
$selfconversation->timemodified = $selfconversation->timecreated;
|
||||
|
||||
$selfconversation->id = $DB->insert_record('message_conversations', $selfconversation);
|
||||
|
||||
// Add user to this self-conversation.
|
||||
$member = new \stdClass();
|
||||
$member->conversationid = $selfconversation->id;
|
||||
$member->userid = $message->useridfrom;
|
||||
$member->timecreated = time();
|
||||
|
||||
$member->id = $DB->insert_record('message_conversation_members', $member);
|
||||
|
||||
// Star the self-conversation.
|
||||
$favouriterecord = new \stdClass();
|
||||
$favouriterecord->component = 'core_message';
|
||||
$favouriterecord->itemtype = 'message_conversations';
|
||||
$favouriterecord->itemid = $selfconversation->id;
|
||||
$userctx = \context_user::instance($message->useridfrom);
|
||||
$favouriterecord->contextid = $userctx->id;
|
||||
$favouriterecord->userid = $message->useridfrom;
|
||||
$favouriterecord->timecreated = time();
|
||||
$favouriterecord->timemodified = $favouriterecord->timecreated;
|
||||
|
||||
$DB->insert_record('favourite', $favouriterecord);
|
||||
}
|
||||
|
||||
// Create the object we will be inserting into the database.
|
||||
$tabledata = new \stdClass();
|
||||
$tabledata->useridfrom = $message->useridfrom;
|
||||
$tabledata->conversationid = $selfconversation->id;
|
||||
$tabledata->subject = $message->subject;
|
||||
$tabledata->fullmessage = $message->fullmessage;
|
||||
$tabledata->fullmessageformat = $message->fullmessageformat ?? FORMAT_MOODLE;
|
||||
$tabledata->fullmessagehtml = $message->fullmessagehtml;
|
||||
$tabledata->smallmessage = $message->smallmessage;
|
||||
$tabledata->timecreated = $message->timecreated;
|
||||
|
||||
$messageid = $DB->insert_record('messages', $tabledata);
|
||||
|
||||
// Check if we need to mark this message as deleted (self-conversations add this information on the
|
||||
// timeuserfromdeleted field.
|
||||
if ($message->timeuserfromdeleted) {
|
||||
$mua = new \stdClass();
|
||||
$mua->userid = $message->useridfrom;
|
||||
$mua->messageid = $messageid;
|
||||
$mua->action = \core_message\api::MESSAGE_ACTION_DELETED;
|
||||
$mua->timecreated = $message->timeuserfromdeleted;
|
||||
|
||||
$DB->insert_record('message_user_actions', $mua);
|
||||
}
|
||||
|
||||
// Mark this message as read.
|
||||
$mua = new \stdClass();
|
||||
$mua->userid = $message->useridto;
|
||||
$mua->messageid = $messageid;
|
||||
$mua->action = \core_message\api::MESSAGE_ACTION_READ;
|
||||
$mua->timecreated = $message->timeread;
|
||||
|
||||
$DB->insert_record('message_user_actions', $mua);
|
||||
}
|
||||
$legacyselfmessagesrs->close();
|
||||
|
||||
// We can now delete the records from legacy table because the self-conversations have been migrated from the legacy tables.
|
||||
$DB->delete_records_select('message_read', $select);
|
||||
|
||||
// STEP 3. For existing users without self-conversations, create and star it.
|
||||
|
||||
// Get all the users without a self-conversation.
|
||||
$sql = "SELECT u.id
|
||||
FROM {user} u
|
||||
WHERE u.id NOT IN (SELECT mcm.userid
|
||||
FROM {message_conversation_members} mcm
|
||||
INNER JOIN mdl_message_conversations mc
|
||||
ON mc.id = mcm.conversationid AND mc.type = ?
|
||||
)";
|
||||
$useridsrs = $DB->get_recordset_sql($sql, [\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF]);
|
||||
// Create the self-conversation for all these users.
|
||||
foreach ($useridsrs as $user) {
|
||||
$conditions = [
|
||||
'type' => \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF,
|
||||
'convhash' => \core_message\helper::get_conversation_hash([$user->id])
|
||||
];
|
||||
$selfconversation = $DB->get_record('message_conversations', $conditions);
|
||||
if (empty($selfconversation)) {
|
||||
// Create the self-conversation.
|
||||
$selfconversation = new \stdClass();
|
||||
$selfconversation->type = \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF;
|
||||
$selfconversation->convhash = \core_message\helper::get_conversation_hash([$user->id]);
|
||||
$selfconversation->enabled = 1;
|
||||
$selfconversation->timecreated = time();
|
||||
$selfconversation->timemodified = $selfconversation->timecreated;
|
||||
|
||||
$selfconversation->id = $DB->insert_record('message_conversations', $selfconversation);
|
||||
|
||||
// Add user to this self-conversation.
|
||||
$member = new \stdClass();
|
||||
$member->conversationid = $selfconversation->id;
|
||||
$member->userid = $user->id;
|
||||
$member->timecreated = time();
|
||||
|
||||
$member->id = $DB->insert_record('message_conversation_members', $member);
|
||||
|
||||
// Star the self-conversation.
|
||||
$favouriterecord = new \stdClass();
|
||||
$favouriterecord->component = 'core_message';
|
||||
$favouriterecord->itemtype = 'message_conversations';
|
||||
$favouriterecord->itemid = $selfconversation->id;
|
||||
$userctx = \context_user::instance($user->id);
|
||||
$favouriterecord->contextid = $userctx->id;
|
||||
$favouriterecord->userid = $user->id;
|
||||
$favouriterecord->timecreated = time();
|
||||
$favouriterecord->timemodified = $favouriterecord->timecreated;
|
||||
|
||||
$DB->insert_record('favourite', $favouriterecord);
|
||||
}
|
||||
}
|
||||
$useridsrs->close();
|
||||
|
||||
// Main savepoint reached.
|
||||
upgrade_main_savepoint(true, 2019041300.01);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -118,18 +118,30 @@ function message_send(\core\message\message $eventdata) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$conversationid = \core_message\api::get_conversation_between_users([$eventdata->userfrom->id,
|
||||
$eventdata->userto->id])) {
|
||||
$conversation = \core_message\api::create_conversation(
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
|
||||
[
|
||||
$eventdata->userfrom->id,
|
||||
$eventdata->userto->id
|
||||
]
|
||||
);
|
||||
if ($eventdata->userfrom->id == $eventdata->userto->id) {
|
||||
// It's a self conversation.
|
||||
$conversation = \core_message\api::get_self_conversation($eventdata->userfrom->id);
|
||||
if (empty($conversation)) {
|
||||
$conversation = \core_message\api::create_conversation(
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF,
|
||||
[$eventdata->userfrom->id]
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (!$conversationid = \core_message\api::get_conversation_between_users([$eventdata->userfrom->id,
|
||||
$eventdata->userto->id])) {
|
||||
// It's a private conversation between users.
|
||||
$conversation = \core_message\api::create_conversation(
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
|
||||
[
|
||||
$eventdata->userfrom->id,
|
||||
$eventdata->userto->id
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
// We either have found a conversation, or created one.
|
||||
$conversationid = $conversationid ? $conversationid : $conversation->id;
|
||||
$conversationid = !empty($conversationid) ? $conversationid : $conversation->id;
|
||||
$eventdata->convid = $conversationid;
|
||||
}
|
||||
|
||||
|
@ -819,6 +819,59 @@ class core_messagelib_testcase extends advanced_testcase {
|
||||
$sink->clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests calling message_send() with $eventdata representing a message to a self-conversation.
|
||||
*
|
||||
* This test will verify:
|
||||
* - that the 'messages' record is created.
|
||||
* - that the processors is not called (for now self-conversations are not processed).
|
||||
* - the a single event will be generated - 'message_sent'
|
||||
*
|
||||
* Note: We won't redirect/capture messages in this test because doing so causes message_send() to return early, before
|
||||
* processors and events code is called. We need to test this code here, as we generally redirect messages elsewhere and we
|
||||
* need to be sure this is covered.
|
||||
*/
|
||||
public function test_message_send_to_self_conversation() {
|
||||
global $DB;
|
||||
$this->preventResetByRollback();
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Create some users and a conversation between them.
|
||||
$user1 = $this->getDataGenerator()->create_user(array('maildisplay' => 1));
|
||||
set_config('allowedemaildomains', 'example.com');
|
||||
$conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF,
|
||||
[$user1->id]);
|
||||
|
||||
// Generate the message.
|
||||
$message = new \core\message\message();
|
||||
$message->courseid = 1;
|
||||
$message->component = 'moodle';
|
||||
$message->name = 'instantmessage';
|
||||
$message->userfrom = $user1;
|
||||
$message->convid = $conversation->id;
|
||||
$message->subject = 'message subject 1';
|
||||
$message->fullmessage = 'message body';
|
||||
$message->fullmessageformat = FORMAT_MARKDOWN;
|
||||
$message->fullmessagehtml = '<p>message body</p>';
|
||||
$message->smallmessage = 'small message';
|
||||
$message->notification = '0';
|
||||
|
||||
// Content specific to the email processor.
|
||||
$content = array('*' => array('header' => ' test ', 'footer' => ' test '));
|
||||
$message->set_additional_content('email', $content);
|
||||
|
||||
// Ensure we're going to hit the email processor for this user.
|
||||
$DB->set_field_select('message_processors', 'enabled', 0, "name <> 'email'");
|
||||
set_user_preference('message_provider_moodle_instantmessage_loggedoff', 'email', $user1);
|
||||
|
||||
// Now, send a message and verify the message processors are empty (self-conversations are not processed for now).
|
||||
$sink = $this->redirectEmails();
|
||||
$messageid = message_send($message);
|
||||
$emails = $sink->get_messages();
|
||||
$this->assertCount(0, $emails);
|
||||
$sink->clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests calling message_send() with $eventdata representing a message to an group conversation.
|
||||
*
|
||||
|
@ -30,6 +30,14 @@ attribute on forms to avoid collisions in forms loaded in AJAX requests.
|
||||
in this category. To work with list of courses use API methods in core_course_category and also 'course' form element.
|
||||
* It is possible to pass additional conditions to get_courses_search();
|
||||
core_course_category::search_courses() now allows to search only among courses with completion enabled.
|
||||
* A new conversation type has been created for self-conversations. During the upgrading process:
|
||||
- Firstly, the existing self-conversations will be starred and migrated to the new type, removing the duplicated members in the
|
||||
message_conversation_members table.
|
||||
- Secondly, the legacy self conversations will be migrated from the legacy 'message_read' table. They will be created using the
|
||||
new conversation type and will be favourited.
|
||||
- Finally, the self-conversations for all remaining users without them will be created and starred.
|
||||
Besides, from now, a self-conversation will be created and starred by default to all the new users (even when $CFG->messaging
|
||||
is disabled).
|
||||
|
||||
=== 3.6 ===
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
||||
define([],function(){var a={ACTION_ACCEPT_CONTACT_REQUEST:'[data-action="accept-contact-request"]',ACTION_CANCEL_CONFIRM:'[data-action="cancel-confirm"]',ACTION_CANCEL_EDIT_MODE:'[data-action="cancel-edit-mode"]',ACTION_CONFIRM_ADD_CONTACT:'[data-action="confirm-add-contact"]',ACTION_CONFIRM_BLOCK:'[data-action="confirm-block"]',ACTION_CONFIRM_DELETE_SELECTED_MESSAGES:'[data-action="confirm-delete-selected-messages"]',ACTION_CONFIRM_DELETE_CONVERSATION:'[data-action="confirm-delete-conversation"]',ACTION_CONFIRM_FAVOURITE:'[data-action="confirm-favourite"]',ACTION_CONFIRM_MUTE:'[data-action="confirm-mute"]',ACTION_CONFIRM_UNFAVOURITE:'[data-action="confirm-unfavourite"]',ACTION_CONFIRM_REMOVE_CONTACT:'[data-action="confirm-remove-contact"]',ACTION_CONFIRM_UNBLOCK:'[data-action="confirm-unblock"]',ACTION_CONFIRM_UNMUTE:'[data-action="confirm-unmute"]',ACTION_DECLINE_CONTACT_REQUEST:'[data-action="decline-contact-request"]',ACTION_REQUEST_ADD_CONTACT:'[data-action="request-add-contact"]',ACTION_REQUEST_BLOCK:'[data-action="request-block"]',ACTION_REQUEST_DELETE_CONVERSATION:'[data-action="request-delete-conversation"]',ACTION_REQUEST_DELETE_SELECTED_MESSAGES:'[data-action="delete-selected-messages"]',ACTION_REQUEST_REMOVE_CONTACT:'[data-action="request-remove-contact"]',ACTION_REQUEST_UNBLOCK:'[data-action="request-unblock"]',ACTION_VIEW_CONTACT:'[data-action="view-contact"]',ACTION_VIEW_GROUP_INFO:'[data-action="view-group-info"]',CAN_RECEIVE_FOCUS:'input:not([type="hidden"]), a[href], button, textarea, select, [tabindex]',CONFIRM_DIALOGUE_BUTTON_TEXT:'[data-region="dialogue-button-text"]',CONFIRM_DIALOGUE_CANCEL_BUTTON:'[data-action="cancel-confirm"]',CONFIRM_DIALOGUE_CONTAINER:'[data-region="confirm-dialogue-container"]',CONFIRM_DIALOGUE_HEADER:'[data-region="dialogue-header"]',CONFIRM_DIALOGUE_TEXT:'[data-region="dialogue-text"]',CONTACT_REQUEST_SENT_MESSAGE_CONTAINER:'[data-region="contact-request-sent-message-container"]',CONTENT_PLACEHOLDER_CONTAINER:'[data-region="content-placeholder"]',CONTENT_CONTAINER:'[data-region="content-container"]',CONTENT_MESSAGES_CONTAINER:'[data-region="content-message-container"]',CONTENT_MESSAGES_FOOTER_CONTAINER:'[data-region="content-messages-footer-container"]',CONTENT_MESSAGES_FOOTER_EDIT_MODE_CONTAINER:'[data-region="content-messages-footer-edit-mode-container"]',CONTENT_MESSAGES_FOOTER_REQUIRE_CONTACT_CONTAINER:'[data-region="content-messages-footer-require-contact-container"]',CONTENT_MESSAGES_FOOTER_REQUIRE_UNBLOCK_CONTAINER:'[data-region="content-messages-footer-require-unblock-container"]',CONTENT_MESSAGES_FOOTER_UNABLE_TO_MESSAGE_CONTAINER:'[data-region="content-messages-footer-unable-to-message"]',DAY_MESSAGES_CONTAINER:'[data-region="day-messages-container"]',FAVOURITE_ICON_CONTAINER:'[data-region="favourite-icon-container"]',FOOTER_CONTAINER:'[data-region="content-messages-footer-container"]',HEADER:'[data-region="header-content"]',HEADER_EDIT_MODE:'[data-region="header-edit-mode"]',HEADER_PLACEHOLDER_CONTAINER:'[data-region="header-placeholder"]',LOADING_ICON_CONTAINER:'[data-region="loading-icon-container"]',MESSAGE:'[data-region="message"]',MESSAGE_NOT_SELECTED:'[data-region="message"][aria-checked="false"]',MESSAGE_NOT_SELECTED_ICON:'[data-region="not-selected-icon"]',MESSAGE_SELECTED_ICON:'[data-region="selected-icon"]',MESSAGES:'[data-region="content-message-container"]',MESSAGES_CONTAINER:'[data-region="content-message-container"]',MESSAGES_SELECTED_COUNT:'[data-region="message-selected-court"]',MESSAGE_TEXT_AREA:'[data-region="send-message-txt"]',MORE_MESSAGES_LOADING_ICON_CONTAINER:'[data-region="more-messages-loading-icon-container"]',MUTED_ICON_CONTAINER:'[data-region="muted-icon-container"]',PLACEHOLDER_CONTAINER:'[data-region="placeholder-container"]',SEND_MESSAGE_BUTTON:'[data-action="send-message"]',SEND_MESSAGE_ICON_CONTAINER:'[data-region="send-icon-container"]',TEXT:'[data-region="text"]',TITLE:'[data-region="title"]'},b={HEADER_PRIVATE:"core_message/message_drawer_view_conversation_header_content_type_private",HEADER_PRIVATE_NO_CONTROLS:"core_message/message_drawer_view_conversation_header_content_type_private_no_controls",HEADER_PUBLIC:"core_message/message_drawer_view_conversation_header_content_type_public",DAY:"core_message/message_drawer_view_conversation_body_day",MESSAGE:"core_message/message_drawer_view_conversation_body_message",MESSAGES:"core_message/message_drawer_view_conversation_body_messages"},c={PRIVATE:1,PUBLIC:2};return{SELECTORS:a,TEMPLATES:b,CONVERSATION_TYPES:c,NEWEST_MESSAGES_FIRST:!0,LOAD_MESSAGE_LIMIT:100,INITIAL_NEW_MESSAGE_POLL_TIMEOUT:1e3}});
|
||||
define([],function(){var a={ACTION_ACCEPT_CONTACT_REQUEST:'[data-action="accept-contact-request"]',ACTION_CANCEL_CONFIRM:'[data-action="cancel-confirm"]',ACTION_CANCEL_EDIT_MODE:'[data-action="cancel-edit-mode"]',ACTION_CONFIRM_ADD_CONTACT:'[data-action="confirm-add-contact"]',ACTION_CONFIRM_BLOCK:'[data-action="confirm-block"]',ACTION_CONFIRM_DELETE_SELECTED_MESSAGES:'[data-action="confirm-delete-selected-messages"]',ACTION_CONFIRM_DELETE_CONVERSATION:'[data-action="confirm-delete-conversation"]',ACTION_CONFIRM_FAVOURITE:'[data-action="confirm-favourite"]',ACTION_CONFIRM_MUTE:'[data-action="confirm-mute"]',ACTION_CONFIRM_UNFAVOURITE:'[data-action="confirm-unfavourite"]',ACTION_CONFIRM_REMOVE_CONTACT:'[data-action="confirm-remove-contact"]',ACTION_CONFIRM_UNBLOCK:'[data-action="confirm-unblock"]',ACTION_CONFIRM_UNMUTE:'[data-action="confirm-unmute"]',ACTION_DECLINE_CONTACT_REQUEST:'[data-action="decline-contact-request"]',ACTION_REQUEST_ADD_CONTACT:'[data-action="request-add-contact"]',ACTION_REQUEST_BLOCK:'[data-action="request-block"]',ACTION_REQUEST_DELETE_CONVERSATION:'[data-action="request-delete-conversation"]',ACTION_REQUEST_DELETE_SELECTED_MESSAGES:'[data-action="delete-selected-messages"]',ACTION_REQUEST_REMOVE_CONTACT:'[data-action="request-remove-contact"]',ACTION_REQUEST_UNBLOCK:'[data-action="request-unblock"]',ACTION_VIEW_CONTACT:'[data-action="view-contact"]',ACTION_VIEW_GROUP_INFO:'[data-action="view-group-info"]',CAN_RECEIVE_FOCUS:'input:not([type="hidden"]), a[href], button, textarea, select, [tabindex]',CONFIRM_DIALOGUE_BUTTON_TEXT:'[data-region="dialogue-button-text"]',CONFIRM_DIALOGUE_CANCEL_BUTTON:'[data-action="cancel-confirm"]',CONFIRM_DIALOGUE_CONTAINER:'[data-region="confirm-dialogue-container"]',CONFIRM_DIALOGUE_HEADER:'[data-region="dialogue-header"]',CONFIRM_DIALOGUE_TEXT:'[data-region="dialogue-text"]',CONTACT_REQUEST_SENT_MESSAGE_CONTAINER:'[data-region="contact-request-sent-message-container"]',CONTENT_PLACEHOLDER_CONTAINER:'[data-region="content-placeholder"]',CONTENT_CONTAINER:'[data-region="content-container"]',CONTENT_MESSAGES_CONTAINER:'[data-region="content-message-container"]',CONTENT_MESSAGES_FOOTER_CONTAINER:'[data-region="content-messages-footer-container"]',CONTENT_MESSAGES_FOOTER_EDIT_MODE_CONTAINER:'[data-region="content-messages-footer-edit-mode-container"]',CONTENT_MESSAGES_FOOTER_REQUIRE_CONTACT_CONTAINER:'[data-region="content-messages-footer-require-contact-container"]',CONTENT_MESSAGES_FOOTER_REQUIRE_UNBLOCK_CONTAINER:'[data-region="content-messages-footer-require-unblock-container"]',CONTENT_MESSAGES_FOOTER_UNABLE_TO_MESSAGE_CONTAINER:'[data-region="content-messages-footer-unable-to-message"]',DAY_MESSAGES_CONTAINER:'[data-region="day-messages-container"]',FAVOURITE_ICON_CONTAINER:'[data-region="favourite-icon-container"]',FOOTER_CONTAINER:'[data-region="content-messages-footer-container"]',HEADER:'[data-region="header-content"]',HEADER_EDIT_MODE:'[data-region="header-edit-mode"]',HEADER_PLACEHOLDER_CONTAINER:'[data-region="header-placeholder"]',LOADING_ICON_CONTAINER:'[data-region="loading-icon-container"]',MESSAGE:'[data-region="message"]',MESSAGE_NOT_SELECTED:'[data-region="message"][aria-checked="false"]',MESSAGE_NOT_SELECTED_ICON:'[data-region="not-selected-icon"]',MESSAGE_SELECTED_ICON:'[data-region="selected-icon"]',MESSAGES:'[data-region="content-message-container"]',MESSAGES_CONTAINER:'[data-region="content-message-container"]',MESSAGES_SELECTED_COUNT:'[data-region="message-selected-court"]',MESSAGE_TEXT_AREA:'[data-region="send-message-txt"]',MORE_MESSAGES_LOADING_ICON_CONTAINER:'[data-region="more-messages-loading-icon-container"]',MUTED_ICON_CONTAINER:'[data-region="muted-icon-container"]',PLACEHOLDER_CONTAINER:'[data-region="placeholder-container"]',SELF_CONVERSATION_MESSAGE_CONTAINER:'[data-region="self-conversation-message-container"]',SEND_MESSAGE_BUTTON:'[data-action="send-message"]',SEND_MESSAGE_ICON_CONTAINER:'[data-region="send-icon-container"]',TEXT:'[data-region="text"]',TITLE:'[data-region="title"]'},b={HEADER_PRIVATE:"core_message/message_drawer_view_conversation_header_content_type_private",HEADER_PRIVATE_NO_CONTROLS:"core_message/message_drawer_view_conversation_header_content_type_private_no_controls",HEADER_PUBLIC:"core_message/message_drawer_view_conversation_header_content_type_public",HEADER_SELF:"core_message/message_drawer_view_conversation_header_content_type_self",DAY:"core_message/message_drawer_view_conversation_body_day",MESSAGE:"core_message/message_drawer_view_conversation_body_message",MESSAGES:"core_message/message_drawer_view_conversation_body_messages"},c={PRIVATE:1,PUBLIC:2,SELF:3},d={PRIVATE:1,PUBLIC:2,FAVOURITE:null};return{SELECTORS:a,TEMPLATES:b,CONVERSATION_TYPES:c,CONVERSATION_CATEGORY_TYPES:d,NEWEST_MESSAGES_FIRST:!0,LOAD_MESSAGE_LIMIT:100,INITIAL_NEW_MESSAGE_POLL_TIMEOUT:1e3}});
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
||||
define(["jquery","core/key_codes","core/pubsub","core/str","core_message/message_drawer_router","core_message/message_drawer_routes","core_message/message_drawer_events","core_message/message_drawer_view_overview_section","core_message/message_repository"],function(a,b,c,d,e,f,g,h,i){var j={CONTACT_REQUEST_COUNT:'[data-region="contact-request-count"]',FAVOURITES:'[data-region="view-overview-favourites"]',GROUP_MESSAGES:'[data-region="view-overview-group-messages"]',MESSAGES:'[data-region="view-overview-messages"]',SEARCH_INPUT:'[data-region="view-overview-search-input"]',SECTION_TOGGLE_BUTTON:"[data-toggle]"},k={PRIVATE:1,PUBLIC:2,FAVOURITE:null},l=null,m=function(a){return null===l&&(l=i.getAllConversationCounts(a)),l},n=function(a,b){return b===k.FAVOURITE?a.favourites:a.types[b]},o=function(a){var b=a.some(function(a){var b=a[0];return h.isVisible(b)});if(!b){a.sort(function(a,b){var c=a[1],d=a[2],e=b[1],f=b[2];return d>0&&0==f?-1:0==d&&f>0?1:c>0&&0==e?-1:0==c&&e>0?1:0});var c=a[0][0],d=c.find(j.SECTION_TOGGLE_BUTTON);d.click()}},p=function(a){return a.find(j.SEARCH_INPUT)},q=function(a){return a.attr("data-user-id")},r=function(a){return function(){var b=a.find(j.CONTACT_REQUEST_COUNT),c=parseInt(b.text(),10);c=isNaN(c)?0:c-1,c<=0?b.addClass("hidden"):b.text(c)}},s=function(a,d){var h=p(d),i=[b.tab,b.shift,b.ctrl,b.alt];h.on("click",function(){e.go(a,f.VIEW_SEARCH)}),h.on("keydown",function(b){i.indexOf(b.keyCode)<0&&"Meta"!=b.key&&e.go(a,f.VIEW_SEARCH)}),c.subscribe(g.CONTACT_REQUEST_ACCEPTED,r(d)),c.subscribe(g.CONTACT_REQUEST_DECLINED,r(d))},t=function(a,b,c){b.attr("data-init")||(s(a,b),b.attr("data-init",!0)),p(b).val("");var d=q(c),e=m(d),f=[[c.find(j.FAVOURITES),k.FAVOURITE,!0],[c.find(j.GROUP_MESSAGES),k.PUBLIC,!1],[c.find(j.MESSAGES),k.PRIVATE,!1]];return f.forEach(function(b){var c=b[0],d=b[1],f=b[2],g=e.then(function(a){return n(a.total,d)}),i=e.then(function(a){return n(a.unread,d)});h.show(a,null,c,null,d,f,g,i)}),e.then(function(a){var b=f.map(function(b){var c=b[0],d=b[1],e=n(a.total,d),f=n(a.unread,d);return[c,e,f]});return o(b)})},u=function(){return d.get_string("messagedrawerviewoverview","core_message")};return{show:t,description:u}});
|
||||
define(["jquery","core/key_codes","core/pubsub","core/str","core_message/message_drawer_router","core_message/message_drawer_routes","core_message/message_drawer_events","core_message/message_drawer_view_overview_section","core_message/message_repository","core_message/message_drawer_view_conversation_constants"],function(a,b,c,d,e,f,g,h,i,j){var k={CONTACT_REQUEST_COUNT:'[data-region="contact-request-count"]',FAVOURITES:'[data-region="view-overview-favourites"]',GROUP_MESSAGES:'[data-region="view-overview-group-messages"]',MESSAGES:'[data-region="view-overview-messages"]',SEARCH_INPUT:'[data-region="view-overview-search-input"]',SECTION_TOGGLE_BUTTON:"[data-toggle]"},l=null,m=function(a){return null===l&&(l=i.getAllConversationCounts(a)),l},n=function(a,b){var c=0;return c=b===j.CONVERSATION_CATEGORY_TYPES.PRIVATE&&a.types[j.CONVERSATION_TYPES.SELF]?a.types[j.CONVERSATION_TYPES.PRIVATE]+a.types[j.CONVERSATION_TYPES.SELF]:b===j.CONVERSATION_CATEGORY_TYPES.FAVOURITE?a.favourites:a.types[b]},o=function(a){var b=a.some(function(a){var b=a[0];return h.isVisible(b)});if(!b){a.sort(function(a,b){var c=a[1],d=a[2],e=b[1],f=b[2];return d>0&&0==f?-1:0==d&&f>0?1:c>0&&0==e?-1:0==c&&e>0?1:0});var c=a[0][0],d=c.find(k.SECTION_TOGGLE_BUTTON);d.click()}},p=function(a){return a.find(k.SEARCH_INPUT)},q=function(a){return a.attr("data-user-id")},r=function(a){return function(){var b=a.find(k.CONTACT_REQUEST_COUNT),c=parseInt(b.text(),10);c=isNaN(c)?0:c-1,c<=0?b.addClass("hidden"):b.text(c)}},s=function(a,d){var h=p(d),i=[b.tab,b.shift,b.ctrl,b.alt];h.on("click",function(){e.go(a,f.VIEW_SEARCH)}),h.on("keydown",function(b){i.indexOf(b.keyCode)<0&&"Meta"!=b.key&&e.go(a,f.VIEW_SEARCH)}),c.subscribe(g.CONTACT_REQUEST_ACCEPTED,r(d)),c.subscribe(g.CONTACT_REQUEST_DECLINED,r(d))},t=function(a,b,c){b.attr("data-init")||(s(a,b),b.attr("data-init",!0)),p(b).val("");var d=q(c),e=m(d),f=[[c.find(k.FAVOURITES),j.CONVERSATION_CATEGORY_TYPES.FAVOURITE,!0],[c.find(k.GROUP_MESSAGES),j.CONVERSATION_CATEGORY_TYPES.PUBLIC,!1],[c.find(k.MESSAGES),j.CONVERSATION_CATEGORY_TYPES.PRIVATE,!1]];return f.forEach(function(b){var c=b[0],d=b[1],f=b[2],g=e.then(function(a){return n(a.total,d)}),i=e.then(function(a){return n(a.unread,d)});h.show(a,null,c,null,d,f,g,i)}),e.then(function(a){var b=f.map(function(b){var c=b[0],d=b[1],e=n(a.total,d),f=n(a.unread,d);return[c,e,f]});return o(b)})},u=function(){return d.get_string("messagedrawerviewoverview","core_message")};return{show:t,description:u}});
|
File diff suppressed because one or more lines are too long
2
message/amd/build/message_repository.min.js
vendored
2
message/amd/build/message_repository.min.js
vendored
File diff suppressed because one or more lines are too long
@ -120,11 +120,16 @@ function(
|
||||
* @return {Number} Userid.
|
||||
*/
|
||||
var getOtherUserId = function() {
|
||||
if (!viewState || viewState.type != CONVERSATION_TYPES.PRIVATE) {
|
||||
if (!viewState || (viewState.type != CONVERSATION_TYPES.PRIVATE && viewState.type != CONVERSATION_TYPES.SELF)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var loggedInUserId = viewState.loggedInUserId;
|
||||
if (viewState.type == CONVERSATION_TYPES.SELF) {
|
||||
// It's a self-conversation, so the other user is the one logged in.
|
||||
return loggedInUserId;
|
||||
}
|
||||
|
||||
var otherUserIds = Object.keys(viewState.members).filter(function(userId) {
|
||||
return loggedInUserId != userId;
|
||||
});
|
||||
@ -144,7 +149,7 @@ function(
|
||||
if (!carry) {
|
||||
var state = stateCache[id].state;
|
||||
|
||||
if (state.type == CONVERSATION_TYPES.PRIVATE) {
|
||||
if (state.type == CONVERSATION_TYPES.PRIVATE || state.type == CONVERSATION_TYPES.SELF) {
|
||||
if (userId in state.members) {
|
||||
// We've found a cached conversation for this user!
|
||||
carry = state.id;
|
||||
@ -287,7 +292,7 @@ function(
|
||||
newState = StateManager.setLoadingMembers(newState, false);
|
||||
newState = StateManager.setLoadingMessages(newState, false);
|
||||
newState = StateManager.setName(newState, profile.fullname);
|
||||
newState = StateManager.setType(newState, 1);
|
||||
newState = StateManager.setType(newState, CONVERSATION_TYPES.PRIVATE);
|
||||
newState = StateManager.setImageUrl(newState, profile.profileimageurl);
|
||||
newState = StateManager.setTotalMemberCount(newState, 2);
|
||||
return render(newState)
|
||||
@ -302,6 +307,50 @@ function(
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Load up an empty self-conversation for the logged in user.
|
||||
* Sets all of the conversation details based on the current user.
|
||||
*
|
||||
* A conversation isn't created until the user sends the first message.
|
||||
*
|
||||
* @param {Object} loggedInUserProfile The logged in user profile.
|
||||
* @return {Object} Profile returned from repository.
|
||||
*/
|
||||
var loadEmptySelfConversation = function(loggedInUserProfile) {
|
||||
var loggedInUserId = loggedInUserProfile.id;
|
||||
var newState = StateManager.setLoadingMembers(viewState, true);
|
||||
newState = StateManager.setLoadingMessages(newState, true);
|
||||
return render(newState)
|
||||
.then(function() {
|
||||
return Repository.getMemberInfo(loggedInUserId, [loggedInUserId], true, true);
|
||||
})
|
||||
.then(function(profiles) {
|
||||
if (profiles.length) {
|
||||
return profiles[0];
|
||||
} else {
|
||||
throw new Error('Unable to load other user profile');
|
||||
}
|
||||
})
|
||||
.then(function(profile) {
|
||||
var newState = StateManager.addMembers(viewState, [profile, loggedInUserProfile]);
|
||||
newState = StateManager.setLoadingMembers(newState, false);
|
||||
newState = StateManager.setLoadingMessages(newState, false);
|
||||
newState = StateManager.setName(newState, profile.fullname);
|
||||
newState = StateManager.setType(newState, CONVERSATION_TYPES.SELF);
|
||||
newState = StateManager.setImageUrl(newState, profile.profileimageurl);
|
||||
newState = StateManager.setTotalMemberCount(newState, 1);
|
||||
return render(newState)
|
||||
.then(function() {
|
||||
return profile;
|
||||
});
|
||||
})
|
||||
.catch(function(error) {
|
||||
var newState = StateManager.setLoadingMembers(viewState, false);
|
||||
render(newState);
|
||||
Notification.exception(error);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new state from a conversation object.
|
||||
*
|
||||
@ -310,14 +359,21 @@ function(
|
||||
* @return {Object} new state.
|
||||
*/
|
||||
var updateStateFromConversation = function(conversation, loggedInUserId) {
|
||||
var otherUsers = conversation.members.filter(function(member) {
|
||||
return member.id != loggedInUserId;
|
||||
});
|
||||
var otherUser = otherUsers.length ? otherUsers[0] : null;
|
||||
var otherUser = null;
|
||||
if (conversation.type == CONVERSATION_TYPES.PRIVATE) {
|
||||
// For private conversations, remove current logged in user from the members list to get the other user.
|
||||
var otherUsers = conversation.members.filter(function(member) {
|
||||
return member.id != loggedInUserId;
|
||||
});
|
||||
otherUser = otherUsers.length ? otherUsers[0] : null;
|
||||
} else if (conversation.type == CONVERSATION_TYPES.SELF) {
|
||||
// Self-conversations have only one member.
|
||||
otherUser = conversation.members[0];
|
||||
}
|
||||
|
||||
var name = conversation.name;
|
||||
var imageUrl = conversation.imageurl;
|
||||
|
||||
if (conversation.type == CONVERSATION_TYPES.PRIVATE) {
|
||||
if (conversation.type == CONVERSATION_TYPES.PRIVATE || conversation.type == CONVERSATION_TYPES.SELF) {
|
||||
name = name || otherUser ? otherUser.fullname : '';
|
||||
imageUrl = imageUrl || otherUser ? otherUser.profileimageurl : '';
|
||||
}
|
||||
@ -921,6 +977,7 @@ function(
|
||||
newState = StateManager.setPendingDeleteConversation(newState, false);
|
||||
newState = StateManager.setLoadingConfirmAction(newState, false);
|
||||
PubSub.publish(MessageDrawerEvents.CONVERSATION_DELETED, newState.id);
|
||||
|
||||
return render(newState);
|
||||
});
|
||||
};
|
||||
@ -1019,7 +1076,8 @@ function(
|
||||
var newConversationId = null;
|
||||
return render(newState)
|
||||
.then(function() {
|
||||
if (!conversationId && viewState.type == CONVERSATION_TYPES.PRIVATE) {
|
||||
if (!conversationId &&
|
||||
(viewState.type == CONVERSATION_TYPES.PRIVATE || viewState.type == CONVERSATION_TYPES.SELF)) {
|
||||
// If it's a new private conversation then we need to use the old
|
||||
// web service function to create the conversation.
|
||||
var otherUserId = getOtherUserId();
|
||||
@ -1471,7 +1529,7 @@ function(
|
||||
};
|
||||
|
||||
/**
|
||||
* Load a new empty private conversation between two users.
|
||||
* Load a new empty private conversation between two users or self-conversation.
|
||||
*
|
||||
* @param {Object} body Conversation body container element.
|
||||
* @param {Object} loggedInUserProfile The logged in user's profile.
|
||||
@ -1481,28 +1539,50 @@ function(
|
||||
var resetNoConversation = function(body, loggedInUserProfile, otherUserId) {
|
||||
// Always reset the state back to the initial state so that the
|
||||
// state manager and patcher can work correctly.
|
||||
return resetState(body, null, loggedInUserProfile)
|
||||
.then(function() {
|
||||
return Repository.getConversationBetweenUsers(
|
||||
loggedInUserProfile.id,
|
||||
otherUserId,
|
||||
true,
|
||||
true,
|
||||
0,
|
||||
0,
|
||||
LOAD_MESSAGE_LIMIT,
|
||||
0,
|
||||
NEWEST_FIRST
|
||||
)
|
||||
.then(function(conversation) {
|
||||
// Looks like we have a conversation after all! Let's use that.
|
||||
return resetByConversation(body, conversation, loggedInUserProfile);
|
||||
})
|
||||
.catch(function() {
|
||||
// Can't find a conversation. Oh well. Just load up a blank one.
|
||||
return loadEmptyPrivateConversation(loggedInUserProfile, otherUserId);
|
||||
});
|
||||
});
|
||||
if (loggedInUserProfile.id != otherUserId) {
|
||||
// This is a private conversation between two users.
|
||||
return resetState(body, null, loggedInUserProfile)
|
||||
.then(function() {
|
||||
return Repository.getConversationBetweenUsers(
|
||||
loggedInUserProfile.id,
|
||||
otherUserId,
|
||||
true,
|
||||
true,
|
||||
0,
|
||||
0,
|
||||
LOAD_MESSAGE_LIMIT,
|
||||
0,
|
||||
NEWEST_FIRST
|
||||
)
|
||||
.then(function(conversation) {
|
||||
// Looks like we have a conversation after all! Let's use that.
|
||||
return resetByConversation(body, conversation, loggedInUserProfile);
|
||||
})
|
||||
.catch(function() {
|
||||
// Can't find a conversation. Oh well. Just load up a blank one.
|
||||
return loadEmptyPrivateConversation(loggedInUserProfile, otherUserId);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// This is a self-conversation.
|
||||
return resetState(body, null, loggedInUserProfile)
|
||||
.then(function() {
|
||||
return Repository.getSelfConversation(
|
||||
loggedInUserProfile.id,
|
||||
LOAD_MESSAGE_LIMIT,
|
||||
0,
|
||||
NEWEST_FIRST
|
||||
)
|
||||
.then(function(conversation) {
|
||||
// Looks like we have a conversation after all! Let's use that.
|
||||
return resetByConversation(body, conversation, loggedInUserProfile);
|
||||
})
|
||||
.catch(function() {
|
||||
// Can't find a conversation. Oh well. Just load up a blank one.
|
||||
return loadEmptySelfConversation(loggedInUserProfile);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -78,6 +78,7 @@ define([], function() {
|
||||
MORE_MESSAGES_LOADING_ICON_CONTAINER: '[data-region="more-messages-loading-icon-container"]',
|
||||
MUTED_ICON_CONTAINER: '[data-region="muted-icon-container"]',
|
||||
PLACEHOLDER_CONTAINER: '[data-region="placeholder-container"]',
|
||||
SELF_CONVERSATION_MESSAGE_CONTAINER: '[data-region="self-conversation-message-container"]',
|
||||
SEND_MESSAGE_BUTTON: '[data-action="send-message"]',
|
||||
SEND_MESSAGE_ICON_CONTAINER: '[data-region="send-icon-container"]',
|
||||
TEXT: '[data-region="text"]',
|
||||
@ -88,20 +89,32 @@ define([], function() {
|
||||
HEADER_PRIVATE: 'core_message/message_drawer_view_conversation_header_content_type_private',
|
||||
HEADER_PRIVATE_NO_CONTROLS: 'core_message/message_drawer_view_conversation_header_content_type_private_no_controls',
|
||||
HEADER_PUBLIC: 'core_message/message_drawer_view_conversation_header_content_type_public',
|
||||
HEADER_SELF: 'core_message/message_drawer_view_conversation_header_content_type_self',
|
||||
DAY: 'core_message/message_drawer_view_conversation_body_day',
|
||||
MESSAGE: 'core_message/message_drawer_view_conversation_body_message',
|
||||
MESSAGES: 'core_message/message_drawer_view_conversation_body_messages'
|
||||
};
|
||||
|
||||
// Conversation types. They must have the same values defined in \core_message\api.
|
||||
var CONVERSATION_TYPES = {
|
||||
PRIVATE: 1,
|
||||
PUBLIC: 2
|
||||
PUBLIC: 2,
|
||||
SELF: 3
|
||||
};
|
||||
|
||||
// Categories displayed in the message drawer. Some methods (such as filterCountsByType) are expecting their value
|
||||
// will be the same as the defined in the CONVERSATION_TYPES, except for the favourite.
|
||||
var CONVERSATION_CATEGORY_TYPES = {
|
||||
PRIVATE: 1,
|
||||
PUBLIC: 2,
|
||||
FAVOURITE: null
|
||||
};
|
||||
|
||||
return {
|
||||
SELECTORS: SELECTORS,
|
||||
TEMPLATES: TEMPLATES,
|
||||
CONVERSATION_TYPES: CONVERSATION_TYPES,
|
||||
CONVERSATION_CATEGORY_TYPES: CONVERSATION_CATEGORY_TYPES,
|
||||
NEWEST_MESSAGES_FIRST: true,
|
||||
LOAD_MESSAGE_LIMIT: 100,
|
||||
INITIAL_NEW_MESSAGE_POLL_TIMEOUT: 1000
|
||||
|
@ -313,6 +313,37 @@ function(
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Build a patch for the header of this conversation. Check if this conversation
|
||||
* is a group conversation.
|
||||
*
|
||||
* @param {Object} state The current state.
|
||||
* @param {Object} newState The new state.
|
||||
* @return {Object} patch
|
||||
*/
|
||||
var buildHeaderPatchTypeSelf = function(state, newState) {
|
||||
var shouldRenderHeader = (state.name === null);
|
||||
|
||||
if (shouldRenderHeader) {
|
||||
return {
|
||||
type: Constants.CONVERSATION_TYPES.SELF,
|
||||
// Don't display the controls for the self-conversations.
|
||||
showControls: false,
|
||||
context: {
|
||||
id: newState.id,
|
||||
name: newState.name,
|
||||
subname: newState.subname,
|
||||
imageurl: newState.imageUrl,
|
||||
isfavourite: newState.isFavourite,
|
||||
// Don't show favouriting if we don't have a conversation.
|
||||
showfavourite: newState.id !== null,
|
||||
showonlinestatus: true,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Build a patch for the header of this conversation. Check if this conversation
|
||||
@ -531,11 +562,11 @@ function(
|
||||
*
|
||||
* @param {Object} state The current state.
|
||||
* @param {Object} newState The new state.
|
||||
* @return {Bool|Null}
|
||||
* @return {int|Null} The conversation type of the messages to be deleted.
|
||||
*/
|
||||
var buildConfirmDeleteSelectedMessages = function(state, newState) {
|
||||
if (newState.pendingDeleteMessageIds.length) {
|
||||
return true;
|
||||
return newState.type;
|
||||
} else if (state.pendingDeleteMessageIds.length) {
|
||||
return false;
|
||||
}
|
||||
@ -548,11 +579,11 @@ function(
|
||||
*
|
||||
* @param {Object} state The current state.
|
||||
* @param {Object} newState The new state.
|
||||
* @return {Bool|Null}
|
||||
* @return {int|Null} The conversation type to be deleted.
|
||||
*/
|
||||
var buildConfirmDeleteConversation = function(state, newState) {
|
||||
if (!state.pendingDeleteConversation && newState.pendingDeleteConversation) {
|
||||
return true;
|
||||
return newState.type;
|
||||
} else if (state.pendingDeleteConversation && !newState.pendingDeleteConversation) {
|
||||
return false;
|
||||
}
|
||||
@ -948,6 +979,11 @@ function(
|
||||
var oldOtherUser = getOtherUserFromState(state);
|
||||
var newOtherUser = getOtherUserFromState(newState);
|
||||
|
||||
if (newState.type == Constants.CONVERSATION_TYPES.SELF) {
|
||||
// Users always can send message themselves on self-conversations.
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!oldOtherUser && !newOtherUser) {
|
||||
return null;
|
||||
} else if (oldOtherUser && !newOtherUser) {
|
||||
@ -1104,6 +1140,19 @@ function(
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* We should show this message always, for all the self-conversations.
|
||||
*
|
||||
* The message should be hidden when it's not a self-conversation.
|
||||
*
|
||||
* @param {Object} state The current state.
|
||||
* @param {Object} newState The new state.
|
||||
* @return {bool}
|
||||
*/
|
||||
var buildSelfConversationMessage = function(state, newState) {
|
||||
return (newState.type == Constants.CONVERSATION_TYPES.SELF);
|
||||
};
|
||||
|
||||
/**
|
||||
* We should show the contact request sent message if the user just sent
|
||||
* a contact request to the other user and there are no messages in the
|
||||
@ -1190,6 +1239,13 @@ function(
|
||||
header: buildHeaderPatchTypePublic,
|
||||
footer: buildFooterPatchTypePublic,
|
||||
};
|
||||
// These build functions are only applicable to self-conversations.
|
||||
config[Constants.CONVERSATION_TYPES.SELF] = {
|
||||
header: buildHeaderPatchTypeSelf,
|
||||
footer: buildFooterPatchTypePublic,
|
||||
confirmDeleteConversation: buildConfirmDeleteConversation,
|
||||
selfConversationMessage: buildSelfConversationMessage
|
||||
};
|
||||
|
||||
var patchConfig = $.extend({}, config.all);
|
||||
if (newState.type && newState.type in config) {
|
||||
|
@ -75,6 +75,26 @@ function(
|
||||
getMessagesContainer(body).addClass('hidden');
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the self-conversation message container element.
|
||||
*
|
||||
* @param {Object} body Conversation body container element.
|
||||
* @return {Object} The messages container element.
|
||||
*/
|
||||
var getSelfConversationMessageContainer = function(body) {
|
||||
return body.find(SELECTORS.SELF_CONVERSATION_MESSAGE_CONTAINER);
|
||||
};
|
||||
|
||||
/**
|
||||
* Hide the self-conversation message container element.
|
||||
*
|
||||
* @param {Object} body Conversation body container element.
|
||||
* @return {Object} The messages container element.
|
||||
*/
|
||||
var hideSelfConversationMessageContainer = function(body) {
|
||||
return getSelfConversationMessageContainer(body).addClass('hidden');
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the contact request sent container element.
|
||||
*
|
||||
@ -783,6 +803,8 @@ function(
|
||||
|
||||
if (data.type == CONVERSATION_TYPES.PRIVATE) {
|
||||
template = data.showControls ? TEMPLATES.HEADER_PRIVATE : TEMPLATES.HEADER_PRIVATE_NO_CONTROLS;
|
||||
} else if (data.type == CONVERSATION_TYPES.SELF) {
|
||||
template = TEMPLATES.HEADER_SELF;
|
||||
}
|
||||
|
||||
return Templates.render(template, data.context)
|
||||
@ -1121,12 +1143,21 @@ function(
|
||||
* @param {Object} header The header container element.
|
||||
* @param {Object} body The body container element.
|
||||
* @param {Object} footer The footer container element.
|
||||
* @param {Bool} show If the dialogue should show.
|
||||
* @param {int|Null} type The messages conversation type to be removed.
|
||||
* @return {Object} jQuery promise
|
||||
*/
|
||||
var renderConfirmDeleteSelectedMessages = function(header, body, footer, show) {
|
||||
if (show) {
|
||||
return Str.get_string('deleteselectedmessagesconfirm', 'core_message')
|
||||
var renderConfirmDeleteSelectedMessages = function(header, body, footer, type) {
|
||||
var showmessage = null;
|
||||
if (type == CONVERSATION_TYPES.SELF) {
|
||||
// Message displayed to self-conversations is slighly different.
|
||||
showmessage = 'deleteselectedmessagesconfirmselfconversation';
|
||||
} else if (type) {
|
||||
// This other message should be displayed.
|
||||
showmessage = 'deleteselectedmessagesconfirm';
|
||||
}
|
||||
|
||||
if (showmessage) {
|
||||
return Str.get_string(showmessage, 'core_message')
|
||||
.then(function(string) {
|
||||
return showConfirmDialogue(
|
||||
header,
|
||||
@ -1150,12 +1181,21 @@ function(
|
||||
* @param {Object} header The header container element.
|
||||
* @param {Object} body The body container element.
|
||||
* @param {Object} footer The footer container element.
|
||||
* @param {Bool} show If the dialogue should show
|
||||
* @param {int|Null} type The conversation type to be removed.
|
||||
* @return {Object} jQuery promise
|
||||
*/
|
||||
var renderConfirmDeleteConversation = function(header, body, footer, show) {
|
||||
if (show) {
|
||||
return Str.get_string('deleteallconfirm', 'core_message')
|
||||
var renderConfirmDeleteConversation = function(header, body, footer, type) {
|
||||
var showmessage = null;
|
||||
if (type == CONVERSATION_TYPES.SELF) {
|
||||
// Message displayed to self-conversations is slighly different.
|
||||
showmessage = 'deleteallselfconfirm';
|
||||
} else if (type) {
|
||||
// This other message should be displayed.
|
||||
showmessage = 'deleteallconfirm';
|
||||
}
|
||||
|
||||
if (showmessage) {
|
||||
return Str.get_string(showmessage, 'core_message')
|
||||
.then(function(string) {
|
||||
return showConfirmDialogue(
|
||||
header,
|
||||
@ -1437,6 +1477,25 @@ function(
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Show or hide the self-conversation message.
|
||||
*
|
||||
* @param {Object} header The header container element.
|
||||
* @param {Object} body The body container element.
|
||||
* @param {Object} footer The footer container element.
|
||||
* @param {Object} displayMessage should the message be displayed?.
|
||||
* @return {Object|true} jQuery promise
|
||||
*/
|
||||
var renderSelfConversationMessage = function(header, body, footer, displayMessage) {
|
||||
var container = getSelfConversationMessageContainer(body);
|
||||
if (displayMessage) {
|
||||
container.removeClass('hidden');
|
||||
} else {
|
||||
container.addClass('hidden');
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Show or hide the require add contact panel.
|
||||
*
|
||||
@ -1472,6 +1531,7 @@ function(
|
||||
var renderReset = function(header, body, footer) {
|
||||
hideConfirmDialogue(header, body, footer);
|
||||
hideContactRequestSentContainer(body);
|
||||
hideSelfConversationMessageContainer(body);
|
||||
hideAllHeaderElements(header);
|
||||
showHeaderPlaceholder(header);
|
||||
hideAllFooterElements(footer);
|
||||
@ -1499,6 +1559,7 @@ function(
|
||||
confirmDeleteConversation: renderConfirmDeleteConversation,
|
||||
confirmContactRequest: renderConfirmContactRequest,
|
||||
requireAddContact: renderRequireAddContact,
|
||||
selfConversationMessage: renderSelfConversationMessage,
|
||||
contactRequestSent: renderContactRequestSent
|
||||
},
|
||||
{
|
||||
|
@ -30,7 +30,8 @@ define(
|
||||
'core_message/message_drawer_routes',
|
||||
'core_message/message_drawer_events',
|
||||
'core_message/message_drawer_view_overview_section',
|
||||
'core_message/message_repository'
|
||||
'core_message/message_repository',
|
||||
'core_message/message_drawer_view_conversation_constants'
|
||||
],
|
||||
function(
|
||||
$,
|
||||
@ -41,7 +42,8 @@ function(
|
||||
Routes,
|
||||
MessageDrawerEvents,
|
||||
Section,
|
||||
MessageRepository
|
||||
MessageRepository,
|
||||
Constants
|
||||
) {
|
||||
|
||||
var SELECTORS = {
|
||||
@ -53,12 +55,6 @@ function(
|
||||
SECTION_TOGGLE_BUTTON: '[data-toggle]'
|
||||
};
|
||||
|
||||
var CONVERSATION_TYPES = {
|
||||
PRIVATE: 1,
|
||||
PUBLIC: 2,
|
||||
FAVOURITE: null
|
||||
};
|
||||
|
||||
var loadAllCountsPromise = null;
|
||||
|
||||
/**
|
||||
@ -89,7 +85,15 @@ function(
|
||||
* @return {Number}
|
||||
*/
|
||||
var filterCountsByType = function(counts, type) {
|
||||
return type === CONVERSATION_TYPES.FAVOURITE ? counts.favourites : counts.types[type];
|
||||
var total = 0;
|
||||
if (type === Constants.CONVERSATION_CATEGORY_TYPES.PRIVATE && counts.types[Constants.CONVERSATION_TYPES.SELF]) {
|
||||
// As private and self conversations are displayed together, we need to add the counts for the self-conversations
|
||||
// to the private ones, when there is any self-conversation.
|
||||
total = counts.types[Constants.CONVERSATION_TYPES.PRIVATE] + counts.types[Constants.CONVERSATION_TYPES.SELF];
|
||||
} else {
|
||||
total = type === Constants.CONVERSATION_CATEGORY_TYPES.FAVOURITE ? counts.favourites : counts.types[type];
|
||||
}
|
||||
return total;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -226,11 +230,11 @@ function(
|
||||
|
||||
var sections = [
|
||||
// Favourite conversations section.
|
||||
[body.find(SELECTORS.FAVOURITES), CONVERSATION_TYPES.FAVOURITE, true],
|
||||
[body.find(SELECTORS.FAVOURITES), Constants.CONVERSATION_CATEGORY_TYPES.FAVOURITE, true],
|
||||
// Group conversations section.
|
||||
[body.find(SELECTORS.GROUP_MESSAGES), CONVERSATION_TYPES.PUBLIC, false],
|
||||
[body.find(SELECTORS.GROUP_MESSAGES), Constants.CONVERSATION_CATEGORY_TYPES.PUBLIC, false],
|
||||
// Private conversations section.
|
||||
[body.find(SELECTORS.MESSAGES), CONVERSATION_TYPES.PRIVATE, false]
|
||||
[body.find(SELECTORS.MESSAGES), Constants.CONVERSATION_CATEGORY_TYPES.PRIVATE, false]
|
||||
];
|
||||
|
||||
sections.forEach(function(args) {
|
||||
|
@ -183,14 +183,21 @@ function(
|
||||
lastmessage: lastMessage ? $(lastMessage.text).text() || lastMessage.text : null
|
||||
};
|
||||
|
||||
if (conversation.type == MessageDrawerViewConversationContants.CONVERSATION_TYPES.PRIVATE) {
|
||||
var otherUser = conversation.members.reduce(function(carry, member) {
|
||||
var otherUser = null;
|
||||
if (conversation.type == MessageDrawerViewConversationContants.CONVERSATION_TYPES.SELF) {
|
||||
// Self-conversations have only one member.
|
||||
otherUser = conversation.members[0];
|
||||
} else if (conversation.type == MessageDrawerViewConversationContants.CONVERSATION_TYPES.PRIVATE) {
|
||||
// For private conversations, remove the current userId from the members to get the other user.
|
||||
otherUser = conversation.members.reduce(function(carry, member) {
|
||||
if (!carry && member.id != userId) {
|
||||
carry = member;
|
||||
}
|
||||
return carry;
|
||||
}, null);
|
||||
}
|
||||
|
||||
if (otherUser !== null) {
|
||||
formattedConversation.userid = otherUser.id;
|
||||
formattedConversation.showonlinestatus = otherUser.showonlinestatus;
|
||||
formattedConversation.isonline = otherUser.isonline;
|
||||
@ -238,7 +245,8 @@ function(
|
||||
type,
|
||||
LOAD_LIMIT + 1,
|
||||
offset,
|
||||
includeFavourites
|
||||
includeFavourites,
|
||||
true // Always merge self-conversations with private conversations, to display them together.
|
||||
)
|
||||
.then(function(response) {
|
||||
var conversations = response.conversations;
|
||||
@ -575,8 +583,13 @@ function(
|
||||
});
|
||||
|
||||
PubSub.subscribe(MessageDrawerEvents.CONVERSATION_NEW_LAST_MESSAGE, function(conversation) {
|
||||
// Self-conversations could be displayed as private conversations when they are not starred. So we need to exclude
|
||||
// them from the following check to make sure last messages are updated properly for them.
|
||||
if (
|
||||
(type && conversation.type != type) ||
|
||||
(type && conversation.type == MessageDrawerViewConversationContants.CONVERSATION_TYPES.SELF &&
|
||||
type != MessageDrawerViewConversationContants.CONVERSATION_TYPES.PRIVATE && !conversation.isFavourite) ||
|
||||
(type && conversation.type != MessageDrawerViewConversationContants.CONVERSATION_TYPES.SELF &&
|
||||
type != conversation.type) ||
|
||||
(includeFavourites && !conversation.isFavourite) ||
|
||||
(!includeFavourites && conversation.isFavourite)
|
||||
) {
|
||||
@ -613,7 +626,11 @@ function(
|
||||
if (!conversationElement.length) {
|
||||
createNewConversation(root, conversation);
|
||||
}
|
||||
} else if (type == conversation.type) {
|
||||
} else if (type == conversation.type ||
|
||||
(type == MessageDrawerViewConversationContants.CONVERSATION_TYPES.PRIVATE &&
|
||||
conversation.type == MessageDrawerViewConversationContants.CONVERSATION_TYPES.SELF)) {
|
||||
// Self-conversations are displayed in the private conversations section, so they should be removed from
|
||||
// there when they are favourited.
|
||||
conversationElement = getConversationElement(root, conversation.id);
|
||||
if (conversationElement.length) {
|
||||
deleteConversation(root, conversationElement);
|
||||
@ -628,7 +645,11 @@ function(
|
||||
if (conversationElement.length) {
|
||||
deleteConversation(root, conversationElement);
|
||||
}
|
||||
} else if (type == conversation.type) {
|
||||
} else if (type == conversation.type ||
|
||||
(type == MessageDrawerViewConversationContants.CONVERSATION_TYPES.PRIVATE &&
|
||||
conversation.type == MessageDrawerViewConversationContants.CONVERSATION_TYPES.SELF)) {
|
||||
// Self-conversations are displayed in the private conversations section, so they should be added
|
||||
// there when they are unfavourited.
|
||||
conversationElement = getConversationElement(root, conversation.id);
|
||||
if (!conversationElement.length) {
|
||||
createNewConversation(root, conversation);
|
||||
|
@ -22,12 +22,19 @@
|
||||
* @copyright 2016 Ryan Wyllie <ryan@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery', 'core/ajax', 'core/notification'], function($, Ajax, Notification) {
|
||||
define(
|
||||
[
|
||||
'jquery',
|
||||
'core/ajax',
|
||||
'core/notification',
|
||||
'core_message/message_drawer_view_conversation_constants'
|
||||
], function(
|
||||
$,
|
||||
Ajax,
|
||||
Notification,
|
||||
Constants) {
|
||||
|
||||
var CONVERSATION_TYPES = {
|
||||
PRIVATE: 1,
|
||||
PUBLIC: 2
|
||||
};
|
||||
var CONVERSATION_TYPES = Constants.CONVERSATION_TYPES;
|
||||
|
||||
/**
|
||||
* Retrieve a list of messages from the server.
|
||||
@ -771,6 +778,45 @@ define(['jquery', 'core/ajax', 'core/notification'], function($, Ajax, Notificat
|
||||
return Ajax.call([request])[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a self-conversation.
|
||||
*
|
||||
* @param {int} loggedInUserId The logged in user
|
||||
* @param {int} messageLimit Limit for messages
|
||||
* @param {int} messageOffset Offset for messages
|
||||
* @param {bool} newestMessagesFirst Order the messages by newest first
|
||||
* @return {object} jQuery promise
|
||||
*/
|
||||
var getSelfConversation = function(
|
||||
loggedInUserId,
|
||||
messageLimit,
|
||||
messageOffset,
|
||||
newestMessagesFirst
|
||||
) {
|
||||
var args = {
|
||||
userid: loggedInUserId
|
||||
};
|
||||
|
||||
if (typeof messageLimit != 'undefined' && messageLimit !== null) {
|
||||
args.messagelimit = messageLimit;
|
||||
}
|
||||
|
||||
if (typeof messageOffset != 'undefined' && messageOffset !== null) {
|
||||
args.messageoffset = messageOffset;
|
||||
}
|
||||
|
||||
if (typeof newestMessagesFirst != 'undefined' && newestMessagesFirst !== null) {
|
||||
args.newestmessagesfirst = newestMessagesFirst;
|
||||
}
|
||||
|
||||
var request = {
|
||||
methodname: 'core_message_get_self_conversation',
|
||||
args: args
|
||||
};
|
||||
|
||||
return Ajax.call([request])[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the conversations for a user.
|
||||
*
|
||||
@ -786,7 +832,8 @@ define(['jquery', 'core/ajax', 'core/notification'], function($, Ajax, Notificat
|
||||
type,
|
||||
limit,
|
||||
offset,
|
||||
favourites
|
||||
favourites,
|
||||
mergeself
|
||||
) {
|
||||
var args = {
|
||||
userid: userId,
|
||||
@ -805,6 +852,10 @@ define(['jquery', 'core/ajax', 'core/notification'], function($, Ajax, Notificat
|
||||
args.favourites = favourites;
|
||||
}
|
||||
|
||||
if (typeof mergeself != 'undefined' && mergeself !== null) {
|
||||
args.mergeself = mergeself;
|
||||
}
|
||||
|
||||
var request = {
|
||||
methodname: 'core_message_get_conversations',
|
||||
args: args
|
||||
@ -814,7 +865,7 @@ define(['jquery', 'core/ajax', 'core/notification'], function($, Ajax, Notificat
|
||||
.then(function(result) {
|
||||
if (result.conversations.length) {
|
||||
result.conversations = result.conversations.map(function(conversation) {
|
||||
if (conversation.type == CONVERSATION_TYPES.PRIVATE) {
|
||||
if (conversation.type == CONVERSATION_TYPES.PRIVATE || conversation.type == CONVERSATION_TYPES.SELF) {
|
||||
var otherUser = conversation.members.length ? conversation.members[0] : null;
|
||||
|
||||
if (otherUser) {
|
||||
@ -1093,6 +1144,7 @@ define(['jquery', 'core/ajax', 'core/notification'], function($, Ajax, Notificat
|
||||
declineContactRequest: declineContactRequest,
|
||||
getConversation: getConversation,
|
||||
getConversationBetweenUsers: getConversationBetweenUsers,
|
||||
getSelfConversation: getSelfConversation,
|
||||
getConversations: getConversations,
|
||||
getConversationMembers: getConversationMembers,
|
||||
setFavouriteConversations: setFavouriteConversations,
|
||||
|
@ -78,6 +78,11 @@ class api {
|
||||
*/
|
||||
const MESSAGE_CONVERSATION_TYPE_GROUP = 2;
|
||||
|
||||
/**
|
||||
* A self conversation.
|
||||
*/
|
||||
const MESSAGE_CONVERSATION_TYPE_SELF = 3;
|
||||
|
||||
/**
|
||||
* The state for an enabled conversation area.
|
||||
*/
|
||||
@ -125,14 +130,15 @@ class api {
|
||||
LEFT JOIN {message_user_actions} mua
|
||||
ON (mua.messageid = m.id AND mua.userid = ? AND mua.action = ?)
|
||||
WHERE (m.useridfrom = ? OR mcm.userid = ?)
|
||||
AND m.useridfrom != mcm.userid
|
||||
AND (m.useridfrom != mcm.userid OR mc.type = ?)
|
||||
AND u.deleted = 0
|
||||
AND u2.deleted = 0
|
||||
AND mua.id is NULL
|
||||
AND " . $DB->sql_like('smallmessage', '?', false) . "
|
||||
ORDER BY timecreated DESC";
|
||||
|
||||
$params = array($userid, $userid, $userid, self::MESSAGE_ACTION_DELETED, $userid, $userid, '%' . $search . '%');
|
||||
$params = array($userid, $userid, $userid, self::MESSAGE_ACTION_DELETED, $userid, $userid,
|
||||
self::MESSAGE_CONVERSATION_TYPE_SELF, '%' . $search . '%');
|
||||
|
||||
// Convert the messages into searchable contacts with their last message being the message that was searched.
|
||||
$conversations = array();
|
||||
@ -316,7 +322,11 @@ class api {
|
||||
$fullname = $DB->sql_fullname();
|
||||
|
||||
// Users not to include.
|
||||
$excludeusers = array($userid, $CFG->siteguest);
|
||||
$excludeusers = array($CFG->siteguest);
|
||||
if (!$selfconversation = self::get_self_conversation($userid)) {
|
||||
// Userid should only be excluded when she hasn't a self-conversation.
|
||||
$excludeusers[] = $userid;
|
||||
}
|
||||
list($exclude, $excludeparams) = $DB->get_in_or_equal($excludeusers, SQL_PARAMS_NAMED, 'param', false);
|
||||
|
||||
$params = array('search' => '%' . $DB->sql_like_escape($search) . '%', 'userid1' => $userid, 'userid2' => $userid);
|
||||
@ -427,7 +437,12 @@ class api {
|
||||
if (!empty($foundusers)) {
|
||||
$noncontacts = helper::get_member_info($userid, array_keys($foundusers));
|
||||
foreach ($noncontacts as $memberuserid => $memberinfo) {
|
||||
$noncontacts[$memberuserid]->conversations = self::get_conversations_between_users($userid, $memberuserid, 0, 1000);
|
||||
if ($memberuserid !== $userid) {
|
||||
$noncontacts[$memberuserid]->conversations = self::get_conversations_between_users($userid, $memberuserid, 0,
|
||||
1000);
|
||||
} else {
|
||||
$noncontacts[$memberuserid]->conversations[$selfconversation->id] = $selfconversation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -514,15 +529,17 @@ class api {
|
||||
* @param int $limitnum
|
||||
* @param int $type the type of the conversation, if you wish to filter to a certain type (see api constants).
|
||||
* @param bool $favourites whether to include NO favourites (false) or ONLY favourites (true), or null to ignore this setting.
|
||||
* @param bool $mergeself whether to include self-conversations (true) or ONLY private conversations (false)
|
||||
* when private conversations are requested.
|
||||
* @return array the array of conversations
|
||||
* @throws \moodle_exception
|
||||
*/
|
||||
public static function get_conversations($userid, $limitfrom = 0, $limitnum = 20, int $type = null,
|
||||
bool $favourites = null) {
|
||||
bool $favourites = null, bool $mergeself = false) {
|
||||
global $DB;
|
||||
|
||||
if (!is_null($type) && !in_array($type, [self::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
|
||||
self::MESSAGE_CONVERSATION_TYPE_GROUP])) {
|
||||
self::MESSAGE_CONVERSATION_TYPE_GROUP, self::MESSAGE_CONVERSATION_TYPE_SELF])) {
|
||||
throw new \moodle_exception("Invalid value ($type) for type param, please see api constants.");
|
||||
}
|
||||
|
||||
@ -553,7 +570,18 @@ class api {
|
||||
}
|
||||
|
||||
// If we need to restrict type, generate the SQL snippet.
|
||||
$typesql = !is_null($type) ? " AND mc.type = :convtype " : "";
|
||||
$typesql = "";
|
||||
$typeparams = [];
|
||||
if (!is_null($type)) {
|
||||
if ($mergeself && $type == self::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL) {
|
||||
// When $megerself is set to true, the self-conversations are returned also with the private conversations.
|
||||
$typesql = " AND (mc.type = :convtype1 OR mc.type = :convtype2) ";
|
||||
$typeparams = ['convtype1' => $type, 'convtype2' => self::MESSAGE_CONVERSATION_TYPE_SELF];
|
||||
} else {
|
||||
$typesql = " AND mc.type = :convtype ";
|
||||
$typeparams = ['convtype' => $type];
|
||||
}
|
||||
}
|
||||
|
||||
$sql = "SELECT m.id as messageid, mc.id as id, mc.name as conversationname, mc.type as conversationtype, m.useridfrom,
|
||||
m.smallmessage, m.fullmessage, m.fullmessageformat, m.fullmessagetrust, m.fullmessagehtml, m.timecreated,
|
||||
@ -587,16 +615,16 @@ class api {
|
||||
AND mc.enabled = 1 $typesql $favouritesql
|
||||
ORDER BY (CASE WHEN m.timecreated IS NULL THEN 0 ELSE 1 END) DESC, m.timecreated DESC, id DESC";
|
||||
|
||||
$params = array_merge($favouriteparams, ['userid' => $userid, 'action' => self::MESSAGE_ACTION_DELETED,
|
||||
'userid2' => $userid, 'userid3' => $userid, 'userid4' => $userid, 'convaction' => self::CONVERSATION_ACTION_MUTED,
|
||||
'convtype' => $type]);
|
||||
$params = array_merge($favouriteparams, $typeparams, ['userid' => $userid, 'action' => self::MESSAGE_ACTION_DELETED,
|
||||
'userid2' => $userid, 'userid3' => $userid, 'userid4' => $userid, 'convaction' => self::CONVERSATION_ACTION_MUTED]);
|
||||
$conversationset = $DB->get_recordset_sql($sql, $params, $limitfrom, $limitnum);
|
||||
|
||||
$conversations = [];
|
||||
$selfconversations = []; // Used to track legacy conversations with one's self (both conv members the same user).
|
||||
$selfconversations = []; // Used to track conversations with one's self.
|
||||
$members = [];
|
||||
$individualmembers = [];
|
||||
$groupmembers = [];
|
||||
$selfmembers = [];
|
||||
foreach ($conversationset as $conversation) {
|
||||
$conversations[$conversation->id] = $conversation;
|
||||
$members[$conversation->id] = [];
|
||||
@ -621,13 +649,12 @@ class api {
|
||||
//
|
||||
// For 'individual' type conversations between 2 users, regardless of who sent the last message,
|
||||
// we want the details of the other member in the conversation (i.e. not the current user).
|
||||
// The only exception to the 'not the current user' rule is for 'self' conversations - a legacy construct in which a user
|
||||
// can message themselves via user bulk actions. Subsequently, there are 2 records for the same user created in the members
|
||||
// table.
|
||||
//
|
||||
// For 'group' type conversations, we want the details of the member who sent the last message, if there is one.
|
||||
// This can be the current user or another group member, but for groups without messages, this will be empty.
|
||||
//
|
||||
// For 'self' type conversations, we want the details of the current user.
|
||||
//
|
||||
// This also means that if type filtering is specified and only group conversations are returned, we don't need this extra
|
||||
// query to get the 'other' user as we already have that information.
|
||||
|
||||
@ -647,6 +674,10 @@ class api {
|
||||
$members[$conversation->id][$conversation->useridfrom] = $conversation->useridfrom;
|
||||
$groupmembers[$conversation->useridfrom] = $conversation->useridfrom;
|
||||
}
|
||||
} else if ($conversation->conversationtype == self::MESSAGE_CONVERSATION_TYPE_SELF) {
|
||||
$selfconversations[$conversation->id] = $conversation->id;
|
||||
$members[$conversation->id][$userid] = $userid;
|
||||
$selfmembers[$userid] = $userid;
|
||||
}
|
||||
}
|
||||
// If we need to fetch any member information for any of the individual conversations.
|
||||
@ -665,23 +696,6 @@ class api {
|
||||
$members[$member->conversationid][$member->userid] = $member->userid;
|
||||
$individualmembers[$member->userid] = $member->userid;
|
||||
}
|
||||
|
||||
// Self conversations: If any of the individual conversations which were missing members are still missing members,
|
||||
// we know these must be 'self' conversations. This is a legacy scenario, created via user bulk actions.
|
||||
// In such cases, the member returned should be the current user.
|
||||
//
|
||||
// NOTE: Currently, these conversations are not returned by this method, however,
|
||||
// identifying them is important for future reference.
|
||||
foreach ($individualconversations as $indconvid) {
|
||||
if (empty($members[$indconvid])) {
|
||||
// Keep track of the self conversation (for future use).
|
||||
$selfconversations[$indconvid] = $indconvid;
|
||||
|
||||
// Set the member to the current user.
|
||||
$members[$indconvid][$userid] = $userid;
|
||||
$individualmembers[$userid] = $userid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We could fail early here if we're sure that:
|
||||
@ -692,7 +706,7 @@ class api {
|
||||
// needs to be done in a separate query to avoid doing a join on the messages tables and the user
|
||||
// tables because on large sites these tables are massive which results in extremely slow
|
||||
// performance (typically due to join buffer exhaustion).
|
||||
if (!empty($individualmembers) || !empty($groupmembers)) {
|
||||
if (!empty($individualmembers) || !empty($groupmembers) || !empty($selfmembers)) {
|
||||
// Now, we want to remove any duplicates from the group members array. For individual members we will
|
||||
// be doing a more extensive call as we want their contact requests as well as privacy information,
|
||||
// which is not necessary for group conversations.
|
||||
@ -700,9 +714,10 @@ class api {
|
||||
|
||||
$individualmemberinfo = helper::get_member_info($userid, $individualmembers, true, true);
|
||||
$groupmemberinfo = helper::get_member_info($userid, $diffgroupmembers);
|
||||
$selfmemberinfo = helper::get_member_info($userid, $selfmembers);
|
||||
|
||||
// Don't use array_merge, as we lose array keys.
|
||||
$memberinfo = $individualmemberinfo + $groupmemberinfo;
|
||||
$memberinfo = $individualmemberinfo + $groupmemberinfo + $selfmemberinfo;
|
||||
|
||||
if (empty($memberinfo)) {
|
||||
return [];
|
||||
@ -766,6 +781,17 @@ class api {
|
||||
$unreadcounts = $DB->get_records_sql($unreadcountssql, [$userid, self::MESSAGE_ACTION_READ, self::MESSAGE_ACTION_DELETED,
|
||||
$userid, $userid]);
|
||||
|
||||
// For the self-conversations, get the total number of messages (to know if the conversation is new or it has been emptied).
|
||||
$selfmessagessql = "SELECT COUNT(m.id)
|
||||
FROM {messages} m
|
||||
INNER JOIN {message_conversations} mc
|
||||
ON mc.id = m.conversationid
|
||||
WHERE mc.type = ? AND convhash = ?";
|
||||
$selfmessagestotal = $DB->count_records_sql(
|
||||
$selfmessagessql,
|
||||
[self::MESSAGE_CONVERSATION_TYPE_SELF, helper::get_conversation_hash([$userid])]
|
||||
);
|
||||
|
||||
// Because we'll be calling format_string on each conversation name and passing contexts, we preload them here.
|
||||
// This warms the cache and saves potentially hitting the DB once for each context fetch below.
|
||||
\context_helper::preload_contexts_by_id(array_column($conversations, 'contextid'));
|
||||
@ -773,16 +799,14 @@ class api {
|
||||
// Now, create the final return structure.
|
||||
$arrconversations = [];
|
||||
foreach ($conversations as $conversation) {
|
||||
// Do not include any individual conversations which do not contain a recent message for the user.
|
||||
// Do not include any individual which do not contain a recent message for the user.
|
||||
// This happens if the user has deleted all messages.
|
||||
// Exclude the self-conversations with messages but without a recent message because the user has deleted all them.
|
||||
// Self-conversations without any message should be included, to display them first time they are created.
|
||||
// Group conversations with deleted users or no messages are always returned.
|
||||
if ($conversation->conversationtype == self::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL
|
||||
&& (empty($conversation->messageid))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Exclude 'self' conversations for now.
|
||||
if (isset($selfconversations[$conversation->id])) {
|
||||
if ($conversation->conversationtype == self::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL && empty($conversation->messageid) ||
|
||||
($conversation->conversationtype == self::MESSAGE_CONVERSATION_TYPE_SELF && empty($conversation->messageid)
|
||||
&& $selfmessagestotal > 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -923,10 +947,12 @@ class api {
|
||||
$memberoffset,
|
||||
$memberlimit
|
||||
);
|
||||
// Strip out the requesting user to match what get_conversations does.
|
||||
$members = array_filter($members, function($member) use ($userid) {
|
||||
return $member->id != $userid;
|
||||
});
|
||||
if ($conversation->type != self::MESSAGE_CONVERSATION_TYPE_SELF) {
|
||||
// Strip out the requesting user to match what get_conversations does, except for self-conversations.
|
||||
$members = array_filter($members, function($member) use ($userid) {
|
||||
return $member->id != $userid;
|
||||
});
|
||||
}
|
||||
|
||||
$messages = self::get_conversation_messages(
|
||||
$userid,
|
||||
@ -1570,7 +1596,8 @@ class api {
|
||||
// Some restrictions we need to be aware of:
|
||||
// - Individual conversations containing soft-deleted user must be counted.
|
||||
// - Individual conversations containing only deleted messages must NOT be counted.
|
||||
// - Individual conversations which are legacy 'self' conversations (2 members, both the same user) must NOT be counted.
|
||||
// - Self-conversations with 0 messages must be counted.
|
||||
// - Self-conversations containing only deleted messages must NOT be counted.
|
||||
// - Group conversations with 0 messages must be counted.
|
||||
// - Linked conversations which are disabled (enabled = 0) must NOT be counted.
|
||||
// - Any type of conversation can be included in the favourites count, however, the type counts and the favourites count
|
||||
@ -1582,21 +1609,10 @@ class api {
|
||||
$favservice = \core_favourites\service_factory::get_service_for_user_context($usercontext);
|
||||
list($favsql, $favparams) = $favservice->get_join_sql_by_type('core_message', 'message_conversations', 'fav', 'mc.id');
|
||||
|
||||
$sql = "SELECT mc.type, fav.itemtype, COUNT(DISTINCT mc.id) as count
|
||||
$sql = "SELECT mc.type, fav.itemtype, COUNT(DISTINCT mc.id) as count, MAX(maxvisibleconvmessage.convid) as maxconvidmessage
|
||||
FROM {message_conversations} mc
|
||||
INNER JOIN {message_conversation_members} mcm
|
||||
ON mcm.conversationid = mc.id
|
||||
INNER JOIN (
|
||||
SELECT mcm.conversationid, count(distinct mcm.userid) as membercount
|
||||
FROM {message_conversation_members} mcm
|
||||
WHERE mcm.conversationid IN (
|
||||
SELECT DISTINCT conversationid
|
||||
FROM {message_conversation_members} mcm2
|
||||
WHERE userid = :userid5
|
||||
)
|
||||
GROUP BY mcm.conversationid
|
||||
) uniquemembercount
|
||||
ON uniquemembercount.conversationid = mc.id
|
||||
LEFT JOIN (
|
||||
SELECT m.conversationid as convid, MAX(m.timecreated) as maxtime
|
||||
FROM {messages} m
|
||||
@ -1613,8 +1629,9 @@ class api {
|
||||
WHERE mcm.userid = :userid3
|
||||
AND mc.enabled = :enabled
|
||||
AND (
|
||||
(mc.type = :individualtype AND maxvisibleconvmessage.convid IS NOT NULL AND membercount > 1) OR
|
||||
(mc.type = :grouptype)
|
||||
(mc.type = :individualtype AND maxvisibleconvmessage.convid IS NOT NULL) OR
|
||||
(mc.type = :grouptype) OR
|
||||
(mc.type = :selftype)
|
||||
)
|
||||
GROUP BY mc.type, fav.itemtype
|
||||
ORDER BY mc.type ASC";
|
||||
@ -1629,6 +1646,7 @@ class api {
|
||||
'enabled' => self::MESSAGE_CONVERSATION_ENABLED,
|
||||
'individualtype' => self::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
|
||||
'grouptype' => self::MESSAGE_CONVERSATION_TYPE_GROUP,
|
||||
'selftype' => self::MESSAGE_CONVERSATION_TYPE_SELF,
|
||||
] + $favparams;
|
||||
|
||||
// Assemble the return array.
|
||||
@ -1636,12 +1654,28 @@ class api {
|
||||
'favourites' => 0,
|
||||
'types' => [
|
||||
self::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
self::MESSAGE_CONVERSATION_TYPE_GROUP => 0
|
||||
self::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
|
||||
self::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]
|
||||
];
|
||||
|
||||
// For the self-conversations, get the total number of messages (to know if the conversation is new or it has been emptied).
|
||||
$selfmessagessql = "SELECT COUNT(m.id)
|
||||
FROM {messages} m
|
||||
INNER JOIN {message_conversations} mc
|
||||
ON mc.id = m.conversationid
|
||||
WHERE mc.type = ? AND convhash = ?";
|
||||
$selfmessagestotal = $DB->count_records_sql(
|
||||
$selfmessagessql,
|
||||
[self::MESSAGE_CONVERSATION_TYPE_SELF, helper::get_conversation_hash([$userid])]
|
||||
);
|
||||
|
||||
$countsrs = $DB->get_recordset_sql($sql, $params);
|
||||
foreach ($countsrs as $key => $val) {
|
||||
// Empty self-conversations with deleted messages should be excluded.
|
||||
if ($val->type == self::MESSAGE_CONVERSATION_TYPE_SELF && empty($val->maxconvidmessage) && $selfmessagestotal > 0) {
|
||||
continue;
|
||||
}
|
||||
if (!empty($val->itemtype)) {
|
||||
$counts['favourites'] += $val->count;
|
||||
continue;
|
||||
@ -1862,7 +1896,8 @@ class api {
|
||||
// User can post messages and is in the conversation, but we need to check the conversation type to
|
||||
// know whether or not to check the user privacy settings via can_contact_user().
|
||||
$conversation = $DB->get_record('message_conversations', ['id' => $conversationid], '*', MUST_EXIST);
|
||||
if ($conversation->type == self::MESSAGE_CONVERSATION_TYPE_GROUP) {
|
||||
if ($conversation->type == self::MESSAGE_CONVERSATION_TYPE_GROUP ||
|
||||
$conversation->type == self::MESSAGE_CONVERSATION_TYPE_SELF) {
|
||||
return true;
|
||||
} else if ($conversation->type == self::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL) {
|
||||
// Get the other user in the conversation.
|
||||
@ -2382,6 +2417,23 @@ class api {
|
||||
return $conversations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the self conversation for a user.
|
||||
*
|
||||
* @param int $userid The user id to get the self-conversations
|
||||
* @return \stdClass|false The self-conversation object or false if it doesn't exist
|
||||
* @since Moodle 3.7
|
||||
*/
|
||||
public static function get_self_conversation(int $userid) {
|
||||
global $DB;
|
||||
|
||||
$conditions = [
|
||||
'type' => self::MESSAGE_CONVERSATION_TYPE_SELF,
|
||||
'convhash' => helper::get_conversation_hash([$userid])
|
||||
];
|
||||
return $DB->get_record('message_conversations', $conditions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a conversation between two users.
|
||||
*
|
||||
@ -2420,7 +2472,8 @@ class api {
|
||||
|
||||
$validtypes = [
|
||||
self::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
|
||||
self::MESSAGE_CONVERSATION_TYPE_GROUP
|
||||
self::MESSAGE_CONVERSATION_TYPE_GROUP,
|
||||
self::MESSAGE_CONVERSATION_TYPE_SELF
|
||||
];
|
||||
|
||||
if (!in_array($type, $validtypes)) {
|
||||
@ -2432,13 +2485,20 @@ class api {
|
||||
if (count($userids) > 2) {
|
||||
throw new \moodle_exception('An individual conversation can not have more than two users.');
|
||||
}
|
||||
if ($userids[0] == $userids[1]) {
|
||||
throw new \moodle_exception('Trying to create an individual conversation instead of a self conversation.');
|
||||
}
|
||||
} else if ($type == self::MESSAGE_CONVERSATION_TYPE_SELF) {
|
||||
if (count($userids) != 1) {
|
||||
throw new \moodle_exception('A self conversation can not have more than one user.');
|
||||
}
|
||||
}
|
||||
|
||||
$conversation = new \stdClass();
|
||||
$conversation->type = $type;
|
||||
$conversation->name = $name;
|
||||
$conversation->convhash = null;
|
||||
if ($type == self::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL) {
|
||||
if ($type == self::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL || $type == self::MESSAGE_CONVERSATION_TYPE_SELF) {
|
||||
$conversation->convhash = helper::get_conversation_hash($userids);
|
||||
}
|
||||
$conversation->component = $component;
|
||||
@ -2840,8 +2900,9 @@ class api {
|
||||
* @return bool true if recipient hasn't blocked sender and sender can contact to recipient, false otherwise.
|
||||
*/
|
||||
protected static function can_contact_user(int $recipientid, int $senderid) : bool {
|
||||
if (has_capability('moodle/site:messageanyuser', \context_system::instance(), $senderid)) {
|
||||
// The sender has the ability to contact any user across the entire site.
|
||||
if (has_capability('moodle/site:messageanyuser', \context_system::instance(), $senderid) ||
|
||||
$recipientid == $senderid) {
|
||||
// The sender has the ability to contact any user across the entire site or themselves.
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3146,7 +3207,8 @@ class api {
|
||||
// Assemble the return array.
|
||||
$counts = ['favourites' => 0, 'types' => [
|
||||
self::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
self::MESSAGE_CONVERSATION_TYPE_GROUP => 0
|
||||
self::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
|
||||
self::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]];
|
||||
foreach ($unreadcounts as $convid => $info) {
|
||||
if (isset($favouriteconvids[$convid])) {
|
||||
|
@ -949,14 +949,19 @@ class provider implements
|
||||
// Get subcontext.
|
||||
if (empty($conversation->contextid)) {
|
||||
// Conversations without context are stored in 'Messages | <Other user id>'.
|
||||
$members = $DB->get_records('message_conversation_members', ['conversationid' => $conversation->id]);
|
||||
$members = array_filter($members, function ($member) use ($userid) {
|
||||
return $member->userid != $userid;
|
||||
});
|
||||
if ($otheruser = reset($members)) {
|
||||
$otherusertext = $otheruser->userid;
|
||||
if ($conversation->type == \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF) {
|
||||
// This is a self-conversation. The other user is the same userid.
|
||||
$otherusertext = $userid;
|
||||
} else {
|
||||
$otherusertext = get_string('unknownuser', 'core_message') . '_' . $conversation->id;
|
||||
$members = $DB->get_records('message_conversation_members', ['conversationid' => $conversation->id]);
|
||||
$members = array_filter($members, function ($member) use ($userid) {
|
||||
return $member->userid != $userid;
|
||||
});
|
||||
if ($otheruser = reset($members)) {
|
||||
$otherusertext = $otheruser->userid;
|
||||
} else {
|
||||
$otherusertext = get_string('unknownuser', 'core_message') . '_' . $conversation->id;
|
||||
}
|
||||
}
|
||||
|
||||
$subcontext = array_merge(
|
||||
|
@ -122,7 +122,18 @@ class migrate_message_data extends \core\task\adhoc_task {
|
||||
private function migrate_data($userid, $otheruserid) {
|
||||
global $DB;
|
||||
|
||||
if (!$conversationid = \core_message\api::get_conversation_between_users([$userid, $otheruserid])) {
|
||||
if ($userid == $otheruserid) {
|
||||
// Since 3.7, pending self-conversations should be migrated during the upgrading process so shouldn't be any
|
||||
// self-conversations on the legacy tables. However, this extra-check has been added just in case.
|
||||
$conversation = \core_message\api::get_self_conversation($userid);
|
||||
if (empty($conversation)) {
|
||||
$conversation = \core_message\api::create_conversation(
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF,
|
||||
[$userid]
|
||||
);
|
||||
}
|
||||
$conversationid = $conversation->id;
|
||||
} else if (!$conversationid = \core_message\api::get_conversation_between_users([$userid, $otheruserid])) {
|
||||
$conversation = \core_message\api::create_conversation(
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
|
||||
[
|
||||
|
@ -1247,7 +1247,7 @@ class core_message_external extends external_api {
|
||||
'name' => new external_value(PARAM_TEXT, 'The conversation name, if set', VALUE_DEFAULT, null),
|
||||
'subname' => new external_value(PARAM_TEXT, 'A subtitle for the conversation name, if set', VALUE_DEFAULT, null),
|
||||
'imageurl' => new external_value(PARAM_URL, 'A link to the conversation picture, if set', VALUE_DEFAULT, null),
|
||||
'type' => new external_value(PARAM_INT, 'The type of the conversation (1=individual,2=group)'),
|
||||
'type' => new external_value(PARAM_INT, 'The type of the conversation (1=individual,2=group,3=self)'),
|
||||
'membercount' => new external_value(PARAM_INT, 'Total number of conversation members'),
|
||||
'ismuted' => new external_value(PARAM_BOOL, 'If the user muted this conversation'),
|
||||
'isfavourite' => new external_value(PARAM_BOOL, 'If the user marked this conversation as a favourite'),
|
||||
@ -1752,7 +1752,9 @@ class core_message_external extends external_api {
|
||||
'favourites' => new external_value(PARAM_BOOL, 'Whether to restrict the results to contain NO favourite
|
||||
conversations (false), ONLY favourite conversation (true), or ignore any restriction altogether (null)',
|
||||
VALUE_DEFAULT, null),
|
||||
|
||||
'mergeself' => new external_value(PARAM_BOOL, 'Whether to include self-conversations (true) or ONLY private
|
||||
conversations (false) when private conversations are requested.',
|
||||
VALUE_DEFAULT, false),
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -1765,11 +1767,14 @@ class core_message_external extends external_api {
|
||||
* @param int $limitnum
|
||||
* @param int|null $type
|
||||
* @param bool|null $favourites
|
||||
* @param bool $mergeself whether to include self-conversations (true) or ONLY private conversations (false)
|
||||
* when private conversations are requested.
|
||||
* @return stdClass
|
||||
* @throws \moodle_exception if the messaging feature is disabled on the site.
|
||||
* @since 3.2
|
||||
*/
|
||||
public static function get_conversations($userid, $limitfrom = 0, $limitnum = 0, int $type = null, bool $favourites = null) {
|
||||
public static function get_conversations($userid, $limitfrom = 0, $limitnum = 0, int $type = null, bool $favourites = null,
|
||||
bool $mergeself = false) {
|
||||
global $CFG, $USER;
|
||||
|
||||
// All the standard BL checks.
|
||||
@ -1782,7 +1787,8 @@ class core_message_external extends external_api {
|
||||
'limitfrom' => $limitfrom,
|
||||
'limitnum' => $limitnum,
|
||||
'type' => $type,
|
||||
'favourites' => $favourites
|
||||
'favourites' => $favourites,
|
||||
'mergeself' => $mergeself
|
||||
);
|
||||
$params = self::validate_parameters(self::get_conversations_parameters(), $params);
|
||||
|
||||
@ -1798,7 +1804,8 @@ class core_message_external extends external_api {
|
||||
$params['limitfrom'],
|
||||
$params['limitnum'],
|
||||
$params['type'],
|
||||
$params['favourites']
|
||||
$params['favourites'],
|
||||
$params['mergeself']
|
||||
);
|
||||
|
||||
return (object) ['conversations' => $conversations];
|
||||
@ -2025,6 +2032,91 @@ class core_message_external extends external_api {
|
||||
return self::get_conversation_structure(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get self-conversation parameters.
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function get_self_conversation_parameters() {
|
||||
return new external_function_parameters(
|
||||
array(
|
||||
'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing self-conversations for'),
|
||||
'messagelimit' => new external_value(PARAM_INT, 'Limit for number of messages', VALUE_DEFAULT, 100),
|
||||
'messageoffset' => new external_value(PARAM_INT, 'Offset for messages list', VALUE_DEFAULT, 0),
|
||||
'newestmessagesfirst' => new external_value(PARAM_BOOL, 'Order messages by newest first', VALUE_DEFAULT, true)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single self-conversation.
|
||||
*
|
||||
* @param int $userid The user id to get the self-conversation for
|
||||
* @param int $messagelimit Limit number of messages to load
|
||||
* @param int $messageoffset Offset the messages
|
||||
* @param bool $newestmessagesfirst Order messages by newest first
|
||||
* @return stdClass
|
||||
* @throws \moodle_exception if the messaging feature is disabled on the site.
|
||||
* @since Moodle 3.7
|
||||
*/
|
||||
public static function get_self_conversation(
|
||||
int $userid,
|
||||
int $messagelimit = 0,
|
||||
int $messageoffset = 0,
|
||||
bool $newestmessagesfirst = true
|
||||
) {
|
||||
global $CFG;
|
||||
|
||||
// All the standard BL checks.
|
||||
if (empty($CFG->messaging)) {
|
||||
throw new moodle_exception('disabled', 'message');
|
||||
}
|
||||
|
||||
$params = [
|
||||
'userid' => $userid,
|
||||
'messagelimit' => $messagelimit,
|
||||
'messageoffset' => $messageoffset,
|
||||
'newestmessagesfirst' => $newestmessagesfirst
|
||||
];
|
||||
self::validate_parameters(self::get_self_conversation_parameters(), $params);
|
||||
|
||||
$systemcontext = context_system::instance();
|
||||
self::validate_context($systemcontext);
|
||||
|
||||
$conversation = \core_message\api::get_self_conversation($params['userid']);
|
||||
|
||||
if ($conversation) {
|
||||
$conversation = \core_message\api::get_conversation(
|
||||
$params['userid'],
|
||||
$conversation->id,
|
||||
false,
|
||||
false,
|
||||
0,
|
||||
0,
|
||||
$params['messagelimit'],
|
||||
$params['messageoffset'],
|
||||
$params['newestmessagesfirst']
|
||||
);
|
||||
}
|
||||
|
||||
if ($conversation) {
|
||||
return $conversation;
|
||||
} else {
|
||||
// We have to throw an exception here because the external functions annoyingly
|
||||
// don't accept null to be returned for a single structure.
|
||||
throw new \moodle_exception('errorconversationdoesnotexist', 'message');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get conversation returns.
|
||||
*
|
||||
* @return external_single_structure
|
||||
*/
|
||||
public static function get_self_conversation_returns() {
|
||||
return self::get_conversation_structure();
|
||||
}
|
||||
|
||||
/**
|
||||
* The messagearea conversations parameters.
|
||||
*
|
||||
@ -4625,6 +4717,8 @@ class core_message_external extends external_api {
|
||||
'Total number of individual conversations'),
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => new external_value(PARAM_INT,
|
||||
'Total number of group conversations'),
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => new external_value(PARAM_INT,
|
||||
'Total number of self conversations'),
|
||||
]
|
||||
),
|
||||
]
|
||||
@ -4700,6 +4794,8 @@ class core_message_external extends external_api {
|
||||
'Total number of unread individual conversations'),
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => new external_value(PARAM_INT,
|
||||
'Total number of unread group conversations'),
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => new external_value(PARAM_INT,
|
||||
'Total number of unread self conversations'),
|
||||
]
|
||||
),
|
||||
]
|
||||
|
@ -43,6 +43,10 @@
|
||||
style="overflow-y: auto; overflow-x: hidden"
|
||||
>
|
||||
<div class="position-relative h-100" data-region="content-container" style="overflow-y: auto; overflow-x: hidden">
|
||||
<div class="p-3 text-center hidden" data-region="self-conversation-message-container">
|
||||
<p class="m-0">{{#str}} selfconversation, core_message {{/str}}</p>
|
||||
<p class="font-italic font-weight-light" data-region="text">{{#str}} selfconversationdefaultmessage, core_message {{/str}}</p>
|
||||
</div>
|
||||
<div class="p-3 text-center hidden" data-region="contact-request-sent-message-container">
|
||||
<p class="m-0">{{#str}} contactrequestsent, core_message {{/str}}</p>
|
||||
<p class="font-italic font-weight-light" data-region="text"></p>
|
||||
|
@ -0,0 +1,91 @@
|
||||
{{!
|
||||
This file is part of Moodle - http://moodle.org/
|
||||
|
||||
Moodle is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Moodle is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
@template core_message/message_drawer_view_conversation_header_content_type_self
|
||||
|
||||
This template will render the header content of the conversation page in
|
||||
the message message drawer.
|
||||
|
||||
Classes required for JS:
|
||||
* none
|
||||
|
||||
Data attributes required for JS:
|
||||
* All data attributes are required
|
||||
|
||||
Context variables required for this template:
|
||||
* urls The URLs for the popover
|
||||
* name
|
||||
* subname
|
||||
* imageurl
|
||||
* isfavourite
|
||||
* showonlinestatus
|
||||
|
||||
|
||||
Example context (json):
|
||||
{}
|
||||
|
||||
}}
|
||||
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="align-self-stretch" >
|
||||
<a class="h-100 mr-2 d-flex align-items-center" href="#" data-route-back>
|
||||
{{> core_message/message_drawer_icon_back }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="d-flex text-truncate">
|
||||
{{#imageurl}}
|
||||
<div class="d-flex align-items-center">
|
||||
<img
|
||||
class="rounded-circle"
|
||||
src="{{{.}}}"
|
||||
alt="{{name}}"
|
||||
aria-hidden="true"
|
||||
style="height: 38px"
|
||||
>
|
||||
</div>
|
||||
{{/imageurl}}
|
||||
<div class="w-100 text-truncate ml-2">
|
||||
<div class="d-flex">
|
||||
<strong class="m-0 text-truncate">{{name}}</strong>
|
||||
<span class="{{^isfavourite}}hidden{{/isfavourite}} ml-1 text-primary" data-region="favourite-icon-container">
|
||||
{{#pix}} i/star-rating, core {{/pix}}
|
||||
</span>
|
||||
</div>
|
||||
{{#showonlinestatus}}
|
||||
<p class="m-0 font-weight-light text-truncate">
|
||||
{{#str}} loggedin, core_message {{/str}}
|
||||
</p>
|
||||
{{/showonlinestatus}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ml-auto dropdown">
|
||||
<button class="btn btn-link btn-icon icon-size-3" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
{{#pix}} i/moremenu, core {{/pix}}
|
||||
</button>
|
||||
<div class="dropdown-menu pull-right">
|
||||
<a class="dropdown-item {{#isfavourite}}hidden{{/isfavourite}} {{^showfavourite}}hidden{{/showfavourite}}" href="#" data-action="confirm-favourite">
|
||||
{{#str}} addtofavourites, core_message {{/str}}
|
||||
</a>
|
||||
<a class="dropdown-item {{^isfavourite}}hidden{{/isfavourite}} {{^showfavourite}}hidden{{/showfavourite}}" href="#" data-action="confirm-unfavourite">
|
||||
{{#str}} removefromfavourites, core_message {{/str}}
|
||||
</a>
|
||||
<a class="dropdown-item" href="#" data-action="request-delete-conversation">
|
||||
{{#str}} deleteconversation, core_message {{/str}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -476,6 +476,35 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
$this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[3]->conversations[$gc1->id]->type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify searching for users find themselves when they have self-conversations.
|
||||
*/
|
||||
public function test_message_search_users_self_conversations() {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Create some users.
|
||||
$user1 = new stdClass();
|
||||
$user1->firstname = 'User';
|
||||
$user1->lastname = 'One';
|
||||
$user1 = $this->getDataGenerator()->create_user($user1);
|
||||
$user2 = new stdClass();
|
||||
$user2->firstname = 'User';
|
||||
$user2->lastname = 'Two';
|
||||
$user2 = $this->getDataGenerator()->create_user($user2);
|
||||
|
||||
// Create self-conversation for user1.
|
||||
$sc1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF, [$user1->id]);
|
||||
testhelper::send_fake_message_to_conversation($user1, $sc1->id, 'Hi myself!');
|
||||
|
||||
// Perform a search as user1.
|
||||
$this->setUser($user1);
|
||||
$result = \core_message\api::message_search_users($user1->id, 'One');
|
||||
|
||||
// Check user1 is found as non-contacts.
|
||||
$this->assertCount(0, $result[0]);
|
||||
$this->assertCount(1, $result[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify searching for users works even if no matching users from either contacts, or non-contacts can be found.
|
||||
*/
|
||||
@ -712,6 +741,62 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
$this->assertCount(0, \core_message\api::get_conversations_between_users($user6->id, $user1->id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests getting self-conversations.
|
||||
*/
|
||||
public function test_get_self_conversation() {
|
||||
// Create some users.
|
||||
$user1 = new stdClass();
|
||||
$user1->firstname = 'User';
|
||||
$user1->lastname = 'One';
|
||||
$user1 = self::getDataGenerator()->create_user($user1);
|
||||
|
||||
$user2 = new stdClass();
|
||||
$user2->firstname = 'User';
|
||||
$user2->lastname = 'Two';
|
||||
$user2 = self::getDataGenerator()->create_user($user2);
|
||||
|
||||
$user3 = new stdClass();
|
||||
$user3->firstname = 'User search';
|
||||
$user3->lastname = 'Three';
|
||||
$user3 = self::getDataGenerator()->create_user($user3);
|
||||
|
||||
// Add some users as contacts.
|
||||
\core_message\api::add_contact($user1->id, $user2->id);
|
||||
\core_message\api::add_contact($user3->id, $user1->id);
|
||||
|
||||
// Create private conversations with some users.
|
||||
\core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
|
||||
array($user1->id, $user2->id));
|
||||
\core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
|
||||
array($user3->id, $user1->id));
|
||||
|
||||
// Create a group conversation with users.
|
||||
$gc = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
|
||||
array($user1->id, $user2->id, $user3->id),
|
||||
'Project chat');
|
||||
|
||||
// Create self-conversations.
|
||||
$sc1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF,
|
||||
array($user1->id));
|
||||
$sc2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF,
|
||||
array($user2->id));
|
||||
|
||||
// Send message to self-conversation.
|
||||
testhelper::send_fake_message_to_conversation($user1, $sc1->id, 'Message to myself!');
|
||||
|
||||
$rsc1 = \core_message\api::get_self_conversation($user1->id);
|
||||
$rsc2 = \core_message\api::get_self_conversation($user2->id);
|
||||
$rsc3 = \core_message\api::get_self_conversation($user3->id);
|
||||
|
||||
// Check that we retrieved the correct conversations.
|
||||
$this->assertEquals($sc1->id, $rsc1->id);
|
||||
$this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF, $sc1->type);
|
||||
$this->assertEquals($sc2->id, $rsc2->id);
|
||||
$this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF, $sc2->type);
|
||||
$this->assertFalse($rsc3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests searching messages.
|
||||
*/
|
||||
@ -726,6 +811,9 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
// The person doing the search.
|
||||
$this->setUser($user1);
|
||||
|
||||
// Create self-conversation.
|
||||
$sc = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF, [$user1->id]);
|
||||
|
||||
// Create group conversation.
|
||||
$gc = \core_message\api::create_conversation(
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
|
||||
@ -734,12 +822,13 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
|
||||
// Send some messages back and forth.
|
||||
$time = 1;
|
||||
testhelper::send_fake_message_to_conversation($user1, $gc->id, 'My hero!', $time);
|
||||
$this->send_fake_message($user3, $user1, 'Don\'t block me.', 0, $time + 1);
|
||||
$this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 2);
|
||||
$this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 3);
|
||||
$this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 4);
|
||||
$this->send_fake_message($user2, $user1, 'Word.', 0, $time + 5);
|
||||
testhelper::send_fake_message_to_conversation($user1, $sc->id, 'Test message to self!', $time);
|
||||
testhelper::send_fake_message_to_conversation($user1, $gc->id, 'My hero!', $time + 1);
|
||||
$this->send_fake_message($user3, $user1, 'Don\'t block me.', 0, $time + 2);
|
||||
$this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 3);
|
||||
$this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 4);
|
||||
$this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 5);
|
||||
$this->send_fake_message($user2, $user1, 'Word.', 0, $time + 6);
|
||||
|
||||
$convid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
|
||||
$conv2id = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]);
|
||||
@ -751,12 +840,12 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
$messages = \core_message\api::search_messages($user1->id, 'o');
|
||||
|
||||
// Confirm the data is correct.
|
||||
$this->assertEquals(4, count($messages));
|
||||
|
||||
$this->assertEquals(5, count($messages));
|
||||
$message1 = $messages[0];
|
||||
$message2 = $messages[1];
|
||||
$message3 = $messages[2];
|
||||
$message4 = $messages[3];
|
||||
$message5 = $messages[4];
|
||||
|
||||
$this->assertEquals($user2->id, $message1->userid);
|
||||
$this->assertEquals($user2->id, $message1->useridfrom);
|
||||
@ -805,6 +894,18 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
$this->assertTrue($message4->isread);
|
||||
$this->assertNull($message4->unreadcount);
|
||||
$this->assertEquals($gc->id, $message4->conversationid);
|
||||
|
||||
$this->assertEquals($user1->id, $message5->userid);
|
||||
$this->assertEquals($user1->id, $message5->useridfrom);
|
||||
$this->assertEquals(fullname($user1), $message5->fullname);
|
||||
$this->assertTrue($message5->ismessaging);
|
||||
$this->assertEquals('Test message to self!', $message5->lastmessage);
|
||||
$this->assertNotEmpty($message5->messageid);
|
||||
$this->assertFalse($message5->isonline);
|
||||
$this->assertTrue($message5->isread);
|
||||
$this->assertFalse($message5->isblocked);
|
||||
$this->assertNull($message5->unreadcount);
|
||||
$this->assertEquals($sc->id, $message5->conversationid);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1431,28 +1532,64 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests retrieving conversations when a legacy 'self' conversation exists.
|
||||
* Tests retrieving conversations when a 'self' conversation exists.
|
||||
*/
|
||||
public function test_get_conversations_legacy_self_conversations() {
|
||||
public function test_get_conversations_self_conversations() {
|
||||
global $DB;
|
||||
|
||||
// Create a legacy conversation between one user and themself.
|
||||
// Create a conversation between one user and themself.
|
||||
$user1 = self::getDataGenerator()->create_user();
|
||||
$conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
|
||||
[$user1->id, $user1->id]);
|
||||
testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Test message to self!');
|
||||
$user2 = self::getDataGenerator()->create_user();
|
||||
$user3 = self::getDataGenerator()->create_user();
|
||||
$user4 = self::getDataGenerator()->create_user();
|
||||
|
||||
// Create some individual conversations.
|
||||
$ic1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
|
||||
[$user1->id, $user2->id]);
|
||||
$ic2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
|
||||
[$user1->id, $user3->id]);
|
||||
testhelper::send_fake_message_to_conversation($user1, $ic1->id, 'Message from user1 to user2');
|
||||
|
||||
// Create some self-conversations.
|
||||
$sc1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF, [$user1->id]);
|
||||
$sc4 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF, [$user4->id]);
|
||||
testhelper::send_fake_message_to_conversation($user1, $sc1->id, 'Test message to self 1!');
|
||||
|
||||
// Verify we are in a 'self' conversation state.
|
||||
$members = $DB->get_records('message_conversation_members', ['conversationid' => $conversation->id]);
|
||||
$this->assertCount(2, $members);
|
||||
$member = array_pop($members);
|
||||
$this->assertEquals($user1->id, $member->userid);
|
||||
$members = $DB->get_records('message_conversation_members', ['conversationid' => $sc1->id]);
|
||||
$this->assertCount(1, $members);
|
||||
$member = array_pop($members);
|
||||
$this->assertEquals($user1->id, $member->userid);
|
||||
|
||||
// Verify this conversation is not returned by the method.
|
||||
$conversations = \core_message\api::get_conversations($user1->id);
|
||||
$this->assertCount(0, $conversations);
|
||||
// Verify the self-conversations are returned by the method.
|
||||
$conversations = \core_message\api::get_conversations($user1->id, 0, 20, \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF);
|
||||
$this->assertCount(1, $conversations);
|
||||
$conversation = array_pop($conversations);
|
||||
$this->assertEquals($conversation->id, $sc1->id);
|
||||
|
||||
$conversations = \core_message\api::get_conversations($user4->id);
|
||||
// The self-conversation.
|
||||
$this->assertCount(1, $conversations);
|
||||
|
||||
// Get only private conversations for user1 (empty conversations, like $ic2, are not returned).
|
||||
$conversations = \core_message\api::get_conversations($user1->id, 0, 20,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL);
|
||||
$this->assertCount(1, $conversations);
|
||||
|
||||
// Merge self with private conversations for user1.
|
||||
$conversations = \core_message\api::get_conversations($user1->id, 0, 20,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, null, true);
|
||||
$this->assertCount(2, $conversations);
|
||||
|
||||
// Get only private conversations for user2.
|
||||
$conversations = \core_message\api::get_conversations($user2->id, 0, 20,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL);
|
||||
$this->assertCount(1, $conversations);
|
||||
|
||||
// Merge self with private conversations for user2 (is the same result than before because user2 hasn't self-conversations).
|
||||
$conversations = \core_message\api::get_conversations($user2->id, 0, 20,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, null, true);
|
||||
$this->assertCount(1, $conversations);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3033,15 +3170,22 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
// The person doing the search.
|
||||
$this->setUser($user1);
|
||||
|
||||
// Create self-conversation.
|
||||
$sc1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF, [$user1->id]);
|
||||
$sc2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF, [$user2->id]);
|
||||
|
||||
// Send some messages back and forth.
|
||||
$time = 1;
|
||||
$m1id = $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
|
||||
$m2id = $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
|
||||
$m3id = $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
|
||||
$m4id = $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
|
||||
$m5id = testhelper::send_fake_message_to_conversation($user1, $sc1->id, 'Hi to myself!', $time + 5);
|
||||
$m6id = testhelper::send_fake_message_to_conversation($user2, $sc2->id, 'I am talking with myself', $time + 6);
|
||||
|
||||
// Delete the conversation as user 1.
|
||||
$conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
|
||||
|
||||
// Delete the individual conversation between user1 and user2 (only for user1).
|
||||
\core_message\api::delete_conversation_by_id($user1->id, $conversationid);
|
||||
|
||||
$muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC');
|
||||
@ -3069,6 +3213,26 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
$this->assertEquals($user1->id, $mua4->userid);
|
||||
$this->assertEquals($m4id, $mua4->messageid);
|
||||
$this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua4->action);
|
||||
|
||||
// Delete the self-conversation as user 1.
|
||||
\core_message\api::delete_conversation_by_id($user1->id, $sc1->id);
|
||||
|
||||
$muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC');
|
||||
$this->assertCount(5, $muas);
|
||||
|
||||
// Sort by id.
|
||||
ksort($muas);
|
||||
|
||||
$mua1 = array_shift($muas);
|
||||
$mua2 = array_shift($muas);
|
||||
$mua3 = array_shift($muas);
|
||||
$mua4 = array_shift($muas);
|
||||
$mua5 = array_shift($muas);
|
||||
|
||||
// Check only messages in self-conversion for user1 are deleted (self-conversation for user2 shouldn't be removed).
|
||||
$this->assertEquals($user1->id, $mua5->userid);
|
||||
$this->assertEquals($m5id, $mua5->messageid);
|
||||
$this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua5->action);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3386,9 +3550,18 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
]
|
||||
);
|
||||
|
||||
// Create a self-conversation for user1.
|
||||
$sc1 = \core_message\api::create_conversation(
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF,
|
||||
[$user1->id]
|
||||
);
|
||||
|
||||
// For group conversations, there are no user privacy checks, so only membership in the conversation is needed.
|
||||
$this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
|
||||
|
||||
// For self conversations, there are no user privacy checks, so only membership in the conversation is needed.
|
||||
$this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $sc1->id));
|
||||
|
||||
// For individual conversations, the default privacy setting of 'only contacts and course members' applies.
|
||||
// Users are not in the same course, nor are they contacts, so messages cannot be sent.
|
||||
$this->assertFalse(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
|
||||
@ -3538,9 +3711,16 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
]
|
||||
);
|
||||
|
||||
// Create a self-conversation for user1.
|
||||
$sc1 = \core_message\api::create_conversation(
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF,
|
||||
[$user1->id]
|
||||
);
|
||||
|
||||
// Verify, non members cannot send a message.
|
||||
$this->assertFalse(\core_message\api::can_send_message_to_conversation($user4->id, $gc1->id));
|
||||
$this->assertFalse(\core_message\api::can_send_message_to_conversation($user4->id, $ic1->id));
|
||||
$this->assertFalse(\core_message\api::can_send_message_to_conversation($user4->id, $sc1->id));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -5776,6 +5956,34 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
$this->assertEquals($user3->id, $request1->requesteduserid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test returning members of a self conversation.
|
||||
*/
|
||||
public function test_get_conversation_members_with_self_conversation() {
|
||||
$lastaccess = new stdClass();
|
||||
$lastaccess->lastaccess = time();
|
||||
|
||||
$user1 = self::getDataGenerator()->create_user($lastaccess);
|
||||
|
||||
$selfconversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF,
|
||||
[$user1->id]);
|
||||
testhelper::send_fake_message_to_conversation($user1, $selfconversation->id, 'This is a self-message!');
|
||||
|
||||
// Get the members for the self-conversation.
|
||||
$members = \core_message\api::get_conversation_members($user1->id, $selfconversation->id);
|
||||
$this->assertCount(1, $members);
|
||||
|
||||
$member1 = array_shift($members);
|
||||
|
||||
// Confirm the standard fields are OK.
|
||||
$this->assertEquals($user1->id, $member1->id);
|
||||
$this->assertEquals(fullname($user1), $member1->fullname);
|
||||
$this->assertEquals(true, $member1->isonline);
|
||||
$this->assertEquals(true, $member1->showonlinestatus);
|
||||
$this->assertEquals(false, $member1->iscontact);
|
||||
$this->assertEquals(false, $member1->isblocked);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test verifying that messages can be sent to existing individual conversations.
|
||||
*/
|
||||
@ -5948,6 +6156,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
public function test_get_conversation_counts_test_cases() {
|
||||
$typeindividual = \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL;
|
||||
$typegroup = \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP;
|
||||
$typeself = \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF;
|
||||
list($user1, $user2, $user3, $user4, $user5, $user6, $user7, $user8) = [0, 1, 2, 3, 4, 5, 6, 7];
|
||||
$conversations = [
|
||||
[
|
||||
@ -5986,11 +6195,11 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
'enabled' => false
|
||||
],
|
||||
[
|
||||
'type' => $typeindividual,
|
||||
'users' => [$user8, $user8],
|
||||
'messages' => [$user8, $user8],
|
||||
'type' => $typeself,
|
||||
'users' => [$user8],
|
||||
'messages' => [$user8],
|
||||
'favourites' => [],
|
||||
'enabled' => null // Individual conversations cannot be disabled.
|
||||
'enabled' => null // Self-conversations cannot be disabled.
|
||||
],
|
||||
];
|
||||
|
||||
@ -6002,11 +6211,13 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
'arguments' => [$user5],
|
||||
'expectedcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6017,11 +6228,13 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
'arguments' => [$user4],
|
||||
'expectedcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6032,11 +6245,13 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
'arguments' => [$user1],
|
||||
'expectedcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6047,11 +6262,13 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
'arguments' => [$user2],
|
||||
'expectedcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6062,11 +6279,13 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
'arguments' => [$user4],
|
||||
'expectedcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6077,11 +6296,13 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
'arguments' => [$user1],
|
||||
'expectedcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6092,11 +6313,13 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
'arguments' => [$user1],
|
||||
'expectedcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6107,11 +6330,13 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
'arguments' => [$user1],
|
||||
'expectedcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6122,11 +6347,13 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
'arguments' => [$user1],
|
||||
'expectedcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6137,11 +6364,13 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
'arguments' => [$user2],
|
||||
'expectedcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6152,11 +6381,13 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
'arguments' => [$user3],
|
||||
'expectedcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6167,11 +6398,13 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
'arguments' => [$user1],
|
||||
'expectedcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6182,11 +6415,13 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
'arguments' => [$user1],
|
||||
'expectedcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6197,11 +6432,13 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
'arguments' => [$user1],
|
||||
'expectedcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => [$user2]
|
||||
],
|
||||
@ -6212,11 +6449,13 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
'arguments' => [$user1],
|
||||
'expectedcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => [$user2, $user3, $user4]
|
||||
],
|
||||
@ -6227,11 +6466,13 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
'arguments' => [$user6],
|
||||
'expectedcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6242,11 +6483,13 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
'arguments' => [$user7],
|
||||
'expectedcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6257,11 +6500,13 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
'arguments' => [$user8],
|
||||
'expectedcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 1
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6347,6 +6592,8 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
$counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL]);
|
||||
$this->assertEquals($expectedcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP],
|
||||
$counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP]);
|
||||
$this->assertEquals($expectedcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF],
|
||||
$counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -6459,6 +6706,8 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
$counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL]);
|
||||
$this->assertEquals($expectedunreadcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP],
|
||||
$counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP]);
|
||||
$this->assertEquals($expectedunreadcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF],
|
||||
$counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF]);
|
||||
}
|
||||
|
||||
public function test_delete_all_conversation_data() {
|
||||
|
@ -2719,6 +2719,36 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
$this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[3]['conversations'][0]['type']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify searching for users find themselves when they have self-conversations.
|
||||
*/
|
||||
public function test_message_search_users_self_conversations() {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Create some users.
|
||||
$user1 = new stdClass();
|
||||
$user1->firstname = 'User';
|
||||
$user1->lastname = 'One';
|
||||
$user1 = $this->getDataGenerator()->create_user($user1);
|
||||
$user2 = new stdClass();
|
||||
$user2->firstname = 'User';
|
||||
$user2->lastname = 'Two';
|
||||
$user2 = $this->getDataGenerator()->create_user($user2);
|
||||
|
||||
// Create self-conversation for user1.
|
||||
$sc1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF, [$user1->id]);
|
||||
testhelper::send_fake_message_to_conversation($user1, $sc1->id, 'Hi myself!');
|
||||
|
||||
// Perform a search as user1.
|
||||
$this->setUser($user1);
|
||||
$result = core_message_external::message_search_users($user1->id, 'One');
|
||||
$result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
|
||||
|
||||
// Check results are empty.
|
||||
$this->assertCount(0, $result['contacts']);
|
||||
$this->assertCount(1, $result['noncontacts']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify searching for users works even if no matching users from either contacts, or non-contacts can be found.
|
||||
*/
|
||||
@ -5496,32 +5526,30 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests retrieving conversations when a legacy 'self' conversation exists.
|
||||
* Tests retrieving conversations when a 'self' conversation exists.
|
||||
*/
|
||||
public function test_get_conversations_legacy_self_conversations() {
|
||||
public function test_get_conversations_self_conversations() {
|
||||
global $DB;
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Create a legacy conversation between one user and themself.
|
||||
// Create a conversation between one user and themself.
|
||||
$user1 = self::getDataGenerator()->create_user();
|
||||
$conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
|
||||
[$user1->id, $user1->id]);
|
||||
$conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF,
|
||||
[$user1->id]);
|
||||
testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Test message to self!');
|
||||
|
||||
// Verify we are in a 'self' conversation state.
|
||||
$members = $DB->get_records('message_conversation_members', ['conversationid' => $conversation->id]);
|
||||
$this->assertCount(2, $members);
|
||||
$member = array_pop($members);
|
||||
$this->assertEquals($user1->id, $member->userid);
|
||||
$this->assertCount(1, $members);
|
||||
$member = array_pop($members);
|
||||
$this->assertEquals($user1->id, $member->userid);
|
||||
|
||||
// Verify this conversation is not returned by the method.
|
||||
// Verify this conversation is returned by the method.
|
||||
$this->setUser($user1);
|
||||
$result = core_message_external::get_conversations($user1->id, 0, 20);
|
||||
$result = external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result);
|
||||
$conversations = $result['conversations'];
|
||||
$this->assertCount(0, $conversations);
|
||||
$this->assertCount(1, $conversations);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -6531,6 +6559,7 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
public function test_get_conversation_counts_test_cases() {
|
||||
$typeindividual = \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL;
|
||||
$typegroup = \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP;
|
||||
$typeself = \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF;
|
||||
list($user1, $user2, $user3, $user4, $user5, $user6, $user7, $user8) = [0, 1, 2, 3, 4, 5, 6, 7];
|
||||
$conversations = [
|
||||
[
|
||||
@ -6569,9 +6598,9 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
'enabled' => false
|
||||
],
|
||||
[
|
||||
'type' => $typeindividual,
|
||||
'users' => [$user8, $user8],
|
||||
'messages' => [$user8, $user8],
|
||||
'type' => $typeself,
|
||||
'users' => [$user8],
|
||||
'messages' => [$user8],
|
||||
'favourites' => [],
|
||||
'enabled' => null // Individual conversations cannot be disabled.
|
||||
],
|
||||
@ -6585,11 +6614,13 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
'arguments' => [$user5],
|
||||
'expectedcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6600,11 +6631,13 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
'arguments' => [$user4],
|
||||
'expectedcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6615,11 +6648,13 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
'arguments' => [$user1],
|
||||
'expectedcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6630,11 +6665,13 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
'arguments' => [$user2],
|
||||
'expectedcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6645,11 +6682,13 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
'arguments' => [$user4],
|
||||
'expectedcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6660,11 +6699,13 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
'arguments' => [$user1],
|
||||
'expectedcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6675,11 +6716,13 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
'arguments' => [$user1],
|
||||
'expectedcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6690,11 +6733,13 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
'arguments' => [$user1],
|
||||
'expectedcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6705,11 +6750,13 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
'arguments' => [$user1],
|
||||
'expectedcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6720,11 +6767,13 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
'arguments' => [$user2],
|
||||
'expectedcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6735,11 +6784,13 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
'arguments' => [$user3],
|
||||
'expectedcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6750,11 +6801,13 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
'arguments' => [$user1],
|
||||
'expectedcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6765,11 +6818,13 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
'arguments' => [$user1],
|
||||
'expectedcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6780,11 +6835,13 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
'arguments' => [$user1],
|
||||
'expectedcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => [$user2]
|
||||
],
|
||||
@ -6795,11 +6852,13 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
'arguments' => [$user1],
|
||||
'expectedcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 1, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => [$user2, $user3, $user4]
|
||||
],
|
||||
@ -6810,11 +6869,13 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
'arguments' => [$user6],
|
||||
'expectedcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6825,11 +6886,13 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
'arguments' => [$user7],
|
||||
'expectedcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6840,11 +6903,13 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
'arguments' => [$user8],
|
||||
'expectedcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 1
|
||||
]],
|
||||
'expectedunreadcounts' => ['favourites' => 0, 'types' => [
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
|
||||
]],
|
||||
'deletedusers' => []
|
||||
],
|
||||
@ -6933,6 +6998,8 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
$counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL]);
|
||||
$this->assertEquals($expectedcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP],
|
||||
$counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP]);
|
||||
$this->assertEquals($expectedcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF],
|
||||
$counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -7017,5 +7084,7 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
$counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL]);
|
||||
$this->assertEquals($expectedunreadcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP],
|
||||
$counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP]);
|
||||
$this->assertEquals($expectedunreadcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF],
|
||||
$counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF]);
|
||||
}
|
||||
}
|
||||
|
@ -87,7 +87,18 @@ class core_message_messagelib_testcase extends advanced_testcase {
|
||||
return $DB->insert_record('notifications', $record);
|
||||
}
|
||||
|
||||
if (!$conversationid = \core_message\api::get_conversation_between_users([$userfrom->id, $userto->id])) {
|
||||
if ($userfrom->id == $userto->id) {
|
||||
// It's a self conversation.
|
||||
$conversation = \core_message\api::get_self_conversation($userfrom->id);
|
||||
if (empty($conversation)) {
|
||||
$conversation = \core_message\api::create_conversation(
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF,
|
||||
[$userfrom->id]
|
||||
);
|
||||
}
|
||||
$conversationid = $conversation->id;
|
||||
} else if (!$conversationid = \core_message\api::get_conversation_between_users([$userfrom->id, $userto->id])) {
|
||||
// It's an individual conversation between two different users.
|
||||
$conversation = \core_message\api::create_conversation(
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
|
||||
[
|
||||
|
@ -9,6 +9,9 @@ information provided here is intended especially for developers.
|
||||
functionality and remove all the legacy code (see MDL-63915).
|
||||
Note - It's still possible to view another user's messages if you have the right capabilities and are able to
|
||||
'log-in as' them.
|
||||
* A new parameter 'mergeself' has been added to the methods \core_message\api::get_conversations() and
|
||||
core_message_external::get_conversations(), to decide whether the self-conversations should be included or not when the
|
||||
private ones are requested, to display them together.
|
||||
|
||||
=== 3.6 ===
|
||||
|
||||
|
@ -126,6 +126,10 @@ function user_create_user($user, $updatepassword = true, $triggerevent = true) {
|
||||
\core\event\user_created::create_from_userid($newuserid)->trigger();
|
||||
}
|
||||
|
||||
// All new users must have a starred self-conversation.
|
||||
$selfconversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF, [$newuserid]);
|
||||
\core_message\api::set_favourite_conversation($selfconversation->id, $newuserid);
|
||||
|
||||
// Purge the associated caches for the current user only.
|
||||
$presignupcache = \cache::make('core', 'presignup');
|
||||
$presignupcache->purge_current_user();
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$version = 2019041300.00; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
$version = 2019041300.01; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
// RR = release increments - 00 in DEV branches.
|
||||
// .XX = incremental changes.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user