diff --git a/lang/en/cache.php b/lang/en/cache.php
index ae490cbaadb..b97ae2b189e 100644
--- a/lang/en/cache.php
+++ b/lang/en/cache.php
@@ -52,7 +52,7 @@ $string['cachedef_suspended_userids'] = 'List of suspended users per course';
$string['cachedef_groupdata'] = 'Course group information';
$string['cachedef_htmlpurifier'] = 'HTML Purifier - cleaned content';
$string['cachedef_langmenu'] = 'List of available languages';
-$string['cachedef_message_last_created'] = 'Time created for most recent message between users';
+$string['cachedef_message_time_last_message_between_users'] = 'Time created for most recent message between users';
$string['cachedef_locking'] = 'Locking';
$string['cachedef_message_processors_enabled'] = "Message processors enabled status";
$string['cachedef_navigation_expandcourse'] = 'Navigation expandable courses';
diff --git a/lib/amd/build/backoff_timer.min.js b/lib/amd/build/backoff_timer.min.js
index b1d81162ea1..bb80b45d123 100644
--- a/lib/amd/build/backoff_timer.min.js
+++ b/lib/amd/build/backoff_timer.min.js
@@ -1 +1 @@
-define(function(){var a=1e3,b=function(b,c){if(!b)return a;if(c.length){var d=c[c.length-1];return b+d}return a},c=function(a){this.reset(),this.setCallback(a),this.setBackOffFunction(b)};return c.prototype.setCallback=function(a){return this.callback=a,this},c.prototype.getCallback=function(){return this.callback},c.prototype.setBackOffFunction=function(a){return this.backOffFunction=a,this},c.prototype.getBackOffFunction=function(){return this.backOffFunction},c.prototype.generateNextTime=function(){var a=this.getBackOffFunction().call(this.getBackOffFunction(),this.time,this.previousTimes);return this.previousTimes.push(this.time),this.time=a,a},c.prototype.reset=function(){return this.time=null,this.previousTimes=[],this.stop(),this},c.prototype.stop=function(){return this.timeout&&(window.clearTimeout(this.timeout),this.timeout=null),this},c.prototype.start=function(){if(!this.timeout){var a=this.generateNextTime();this.timeout=window.setTimeout(function(){this.getCallback().call(),this.stop(),this.start()}.bind(this),a)}return this},c.prototype.restart=function(){return this.reset().start()},c});
\ No newline at end of file
+define(function(){var a=function(a,b){this.callback=a,this.backOffFunction=b};return a.prototype.callback=null,a.prototype.backOffFunction=null,a.prototype.time=null,a.prototype.timeout=null,a.prototype.generateNextTime=function(){var a=this.backOffFunction(this.time);return this.time=a,a},a.prototype.reset=function(){return this.time=null,this.stop(),this},a.prototype.stop=function(){return this.timeout&&(window.clearTimeout(this.timeout),this.timeout=null),this},a.prototype.start=function(){if(!this.timeout){var a=this.generateNextTime();this.timeout=window.setTimeout(function(){this.callback(),this.stop(),this.start()}.bind(this),a)}return this},a.prototype.restart=function(){return this.reset().start()},a.getIncrementalCallback=function(a,b,c,d){return function(e){return e?e+b>c?d:e+b:a}},a});
\ No newline at end of file
diff --git a/lib/amd/src/backoff_timer.js b/lib/amd/src/backoff_timer.js
index 992a322d706..da0fabdb086 100644
--- a/lib/amd/src/backoff_timer.js
+++ b/lib/amd/src/backoff_timer.js
@@ -25,92 +25,36 @@
*/
define(function() {
- // Default to one second.
- var DEFAULT_TIME = 1000;
-
- /**
- * The default back off function for the timer. It uses the Fibonacci
- * sequence to determine what the next timeout value should be.
- *
- * @param {(int|null)} time The current timeout value or null if none set
- * @param {array} previousTimes An array containing all previous timeout values
- * @return {int} The new timeout value
- */
- var fibonacciBackOff = function(time, previousTimes) {
- if (!time) {
- return DEFAULT_TIME;
- }
-
- if (previousTimes.length) {
- var lastTime = previousTimes[previousTimes.length - 1];
- return time + lastTime;
- } else {
- return DEFAULT_TIME;
- }
- };
-
/**
* Constructor for the back off timer.
*
* @param {function} callback The function to execute after each tick
+ * @param {function} backoffFunction The function to determine what the next timeout value should be
*/
- var Timer = function(callback) {
- this.reset();
- this.setCallback(callback);
- // Set the default backoff function to be the Fibonacci sequence.
- this.setBackOffFunction(fibonacciBackOff);
- };
-
- /**
- * Set the callback function to be executed after each tick of the
- * timer.
- *
- * @method setCallback
- * @param {function} callback The callback function
- * @return {object} this
- */
- Timer.prototype.setCallback = function(callback) {
+ var BackoffTimer = function(callback, backoffFunction) {
this.callback = callback;
-
- return this;
+ this.backOffFunction = backoffFunction;
};
/**
- * Get the callback function for this timer.
- *
- * @method getCallback
- * @return {function}
+ * @type {function} callback The function to execute after each tick
*/
- Timer.prototype.getCallback = function() {
- return this.callback;
- };
+ BackoffTimer.prototype.callback = null;
/**
- * Set the function to be used when calculating the back off time
- * for each tick of the timer.
- *
- * The back off function will be given two parameters: the current
- * time and an array containing all previous times.
- *
- * @method setBackOffFunction
- * @param {function} backOffFunction The function to calculate back off times
- * @return {object} this
+ * @type {function} backoffFunction The function to determine what the next timeout value should be
*/
- Timer.prototype.setBackOffFunction = function(backOffFunction) {
- this.backOffFunction = backOffFunction;
-
- return this;
- };
+ BackoffTimer.prototype.backOffFunction = null;
/**
- * Get the current back off function.
- *
- * @method getBackOffFunction
- * @return {function}
+ * @type {int} time The timeout value to use
*/
- Timer.prototype.getBackOffFunction = function() {
- return this.backOffFunction;
- };
+ BackoffTimer.prototype.time = null;
+
+ /**
+ * @type {numeric} timeout The timeout identifier
+ */
+ BackoffTimer.prototype.timeout = null;
/**
* Generate the next timeout in the back off time sequence
@@ -122,13 +66,8 @@ define(function() {
* @method generateNextTime
* @return {int} The new timeout value (in milliseconds)
*/
- Timer.prototype.generateNextTime = function() {
- var newTime = this.getBackOffFunction().call(
- this.getBackOffFunction(),
- this.time,
- this.previousTimes
- );
- this.previousTimes.push(this.time);
+ BackoffTimer.prototype.generateNextTime = function() {
+ var newTime = this.backOffFunction(this.time);
this.time = newTime;
return newTime;
@@ -140,9 +79,8 @@ define(function() {
* @method reset
* @return {object} this
*/
- Timer.prototype.reset = function() {
+ BackoffTimer.prototype.reset = function() {
this.time = null;
- this.previousTimes = [];
this.stop();
return this;
@@ -154,7 +92,7 @@ define(function() {
* @method stop
* @return {object} this
*/
- Timer.prototype.stop = function() {
+ BackoffTimer.prototype.stop = function() {
if (this.timeout) {
window.clearTimeout(this.timeout);
this.timeout = null;
@@ -175,12 +113,12 @@ define(function() {
* @method start
* @return {object} this
*/
- Timer.prototype.start = function() {
+ BackoffTimer.prototype.start = function() {
// If we haven't already started.
if (!this.timeout) {
var time = this.generateNextTime();
this.timeout = window.setTimeout(function() {
- this.getCallback().call();
+ this.callback();
// Clear the existing timer.
this.stop();
// Start the next timer.
@@ -198,9 +136,40 @@ define(function() {
* @method restart
* @return {object} this
*/
- Timer.prototype.restart = function() {
+ BackoffTimer.prototype.restart = function() {
return this.reset().start();
};
- return Timer;
+ /**
+ * Returns an incremental function for the timer.
+ *
+ * @param {int} minamount The minimum amount of time we wait before checking
+ * @param {int} incrementamount The amount to increment the timer by
+ * @param {int} maxamount The max amount to ever increment to
+ * @param {int} timeoutamount The timeout to use once we reach the max amount
+ * @return {function}
+ */
+ BackoffTimer.getIncrementalCallback = function(minamount, incrementamount, maxamount, timeoutamount) {
+
+ /**
+ * An incremental function for the timer.
+ *
+ * @param {(int|null)} time The current timeout value or null if none set
+ * @return {int} The new timeout value
+ */
+ return function(time) {
+ if (!time) {
+ return minamount;
+ }
+
+ // Don't go over the max amount.
+ if (time + incrementamount > maxamount) {
+ return timeoutamount;
+ }
+
+ return time + incrementamount;
+ };
+ };
+
+ return BackoffTimer;
});
diff --git a/lib/db/caches.php b/lib/db/caches.php
index 49e509a8186..9a8e9f24e5d 100644
--- a/lib/db/caches.php
+++ b/lib/db/caches.php
@@ -302,12 +302,11 @@ $definitions = array(
'staticaccelerationsize' => 3
),
- // Cache for storing the user's last received message time.
- 'message_last_created' => array(
+ // Caches the time of the last message between two users.
+ 'message_time_last_message_between_users' => array(
'mode' => cache_store::MODE_APPLICATION,
'simplekeys' => true, // The id of the sender and recipient is used.
'simplevalues' => true,
- 'datasource' => 'message_last_created_cache_source',
- 'datasourcefile' => 'message/classes/message_last_created_cache_source.php'
+ 'datasource' => '\core_message\time_last_message_between_users',
),
);
diff --git a/lib/messagelib.php b/lib/messagelib.php
index 9bfad534db6..5347f173b61 100644
--- a/lib/messagelib.php
+++ b/lib/messagelib.php
@@ -237,10 +237,9 @@ function message_send($eventdata) {
// Only cache messages, not notifications.
if (empty($savemessage->notification)) {
// Cache the timecreated value of the last message between these two users.
- $cache = cache::make('core', 'message_last_created');
- $ids = [$savemessage->useridfrom, $savemessage->useridto];
- sort($ids);
- $key = implode('_', $ids);
+ $cache = cache::make('core', 'message_time_last_message_between_users');
+ $key = \core_message\helper::get_last_message_time_created_cache_key($savemessage->useridfrom,
+ $savemessage->useridto);
$cache->set($key, $savemessage->timecreated);
}
diff --git a/message/amd/build/message_area.min.js b/message/amd/build/message_area.min.js
index 942dc1cb22d..b117ee3e361 100644
--- a/message/amd/build/message_area.min.js
+++ b/message/amd/build/message_area.min.js
@@ -1 +1 @@
-define(["jquery","core_message/message_area_contacts","core_message/message_area_messages","core_message/message_area_profile","core_message/message_area_tabs","core_message/message_area_search"],function(a,b,c,d,e,f){function g(b){this.node=a(b),this._init()}return g.prototype.node=null,g.prototype._init=function(){new b(this),new c(this),new d(this),new e(this),new f(this)},g.prototype.onDelegateEvent=function(a,b,c){this.node.on(a,b,c)},g.prototype.onCustomEvent=function(a,b){this.node.on(a,b)},g.prototype.trigger=function(a,b){"undefined"==typeof b&&(b=""),this.node.trigger(a,b)},g.prototype.find=function(a){return this.node.find(a)},g.prototype.getCurrentUserId=function(){return this.node.data("userid")},g});
\ No newline at end of file
+define(["jquery","core_message/message_area_contacts","core_message/message_area_messages","core_message/message_area_profile","core_message/message_area_tabs","core_message/message_area_search"],function(a,b,c,d,e,f){function g(b,c,d,e){this.node=a(b),this.pollmin=c,this.pollmax=d,this.polltimeout=e,this._init()}return g.prototype.node=null,g.prototype.pollmin=null,g.prototype.pollmax=null,g.prototype.polltimeout=null,g.prototype._init=function(){new b(this),new c(this),new d(this),new e(this),new f(this)},g.prototype.onDelegateEvent=function(a,b,c){this.node.on(a,b,c)},g.prototype.onCustomEvent=function(a,b){this.node.on(a,b)},g.prototype.trigger=function(a,b){"undefined"==typeof b&&(b=""),this.node.trigger(a,b)},g.prototype.find=function(a){return this.node.find(a)},g.prototype.getCurrentUserId=function(){return this.node.data("userid")},g});
\ No newline at end of file
diff --git a/message/amd/build/message_area_messages.min.js b/message/amd/build/message_area_messages.min.js
index 4ba61b0677a..09a54373a3f 100644
--- a/message/amd/build/message_area_messages.min.js
+++ b/message/amd/build/message_area_messages.min.js
@@ -1 +1 @@
-define(["jquery","core/ajax","core/templates","core/notification","core/custom_interaction_events","core/auto_rows","core_message/message_area_actions","core/modal_factory","core/modal_events","core/str","core_message/message_area_events","core/backoff_timer"],function(a,b,c,d,e,f,g,h,i,j,k,l){function m(a){this.messageArea=a,this._init()}var n=500,o=50,p={BLOCKTIME:"[data-region='blocktime']",CANCELDELETEMESSAGES:"[data-action='cancel-delete-messages']",CONTACT:"[data-region='contact']",CONVERSATIONS:"[data-region='contacts'][data-region-content='conversations']",DELETEALLMESSAGES:"[data-action='delete-all-messages']",DELETEMESSAGES:"[data-action='delete-messages']",LOADINGICON:".loading-icon",MESSAGE:"[data-region='message']",MESSAGERESPONSE:"[data-region='response']",MESSAGES:"[data-region='messages']",MESSAGESAREA:"[data-region='messages-area']",MESSAGINGAREA:"[data-region='messaging-area']",SENDMESSAGE:"[data-action='send-message']",SENDMESSAGETEXT:"[data-region='send-message-txt']",SHOWCONTACTS:"[data-action='show-contacts']",STARTDELETEMESSAGES:"[data-action='start-delete-messages']"};return m.prototype._isSendingMessage=!1,m.prototype._isLoadingMessages=!1,m.prototype._numMessagesDisplayed=0,m.prototype._numMessagesToRetrieve=20,m.prototype._confirmationModal=null,m.prototype._earliestMessageTimestamp=0,m.prototype._timer=null,m.prototype.messageArea=null,m.prototype._init=function(){e.define(this.messageArea.node,[e.events.activate,e.events.up,e.events.down,e.events.enter]),a(window).height()<=670&&(n=400),f.init(this.messageArea.node),this.messageArea.onCustomEvent(k.CONVERSATIONSELECTED,this._viewMessages.bind(this)),this.messageArea.onCustomEvent(k.SENDMESSAGE,this._viewMessages.bind(this)),this.messageArea.onCustomEvent(k.CHOOSEMESSAGESTODELETE,this._chooseMessagesToDelete.bind(this)),this.messageArea.onCustomEvent(k.CANCELDELETEMESSAGES,this._hideDeleteAction.bind(this)),this.messageArea.onDelegateEvent(e.events.activate,p.SENDMESSAGE,this._sendMessage.bind(this)),this.messageArea.onDelegateEvent(e.events.activate,p.STARTDELETEMESSAGES,this._startDeleting.bind(this)),this.messageArea.onDelegateEvent(e.events.activate,p.DELETEMESSAGES,this._deleteMessages.bind(this)),this.messageArea.onDelegateEvent(e.events.activate,p.DELETEALLMESSAGES,this._deleteAllMessages.bind(this)),this.messageArea.onDelegateEvent(e.events.activate,p.CANCELDELETEMESSAGES,this._triggerCancelMessagesToDelete.bind(this)),this.messageArea.onDelegateEvent(e.events.activate,p.MESSAGE,this._toggleMessage.bind(this)),this.messageArea.onDelegateEvent(e.events.activate,p.SHOWCONTACTS,this._hideMessagingArea.bind(this)),this.messageArea.onDelegateEvent(e.events.up,p.MESSAGE,this._selectPreviousMessage.bind(this)),this.messageArea.onDelegateEvent(e.events.down,p.MESSAGE,this._selectNextMessage.bind(this)),this.messageArea.onDelegateEvent("focus",p.SENDMESSAGETEXT,this._setMessaging.bind(this)),this.messageArea.onDelegateEvent("blur",p.SENDMESSAGETEXT,this._clearMessaging.bind(this)),this.messageArea.onDelegateEvent(e.events.enter,p.SENDMESSAGETEXT,this._sendMessageHandler.bind(this)),a(document).on(f.events.ROW_CHANGE,this._adjustMessagesAreaHeight.bind(this));var b=this.messageArea.find(p.MESSAGES);b.length&&this._addScrollEventListener(b.find(p.MESSAGE).length),this._timer=new l(function(){this._loadNewMessages()}.bind(this)),this._timer.start()},m.prototype._viewMessages=function(e,f){this._numMessagesDisplayed=0,this._timer.stop(),this._earliestMessageTimestamp=0;var g=b.call([{methodname:"core_message_mark_all_messages_as_read",args:{useridto:this.messageArea.getCurrentUserId(),useridfrom:f}}]),h=0;return c.render("core/loading",{}).then(function(a,b){return c.replaceNodeContents(this.messageArea.find(p.MESSAGESAREA),a,b),g[0]}.bind(this)).then(function(){var b=this.messageArea.find(p.CONVERSATIONS+" "+p.CONTACT+"[data-userid='"+f+"']");return b.hasClass("unread")&&(b.removeClass("unread"),a(document).trigger("messagearea:conversationselected",f)),this._getMessages(f)}.bind(this)).then(function(a){return h=a.messages.length,c.render("core_message/message_area_messages_area",a)}).then(function(a,b){c.replaceNodeContents(this.messageArea.find(p.MESSAGESAREA),a,b),this._addScrollEventListener(h),this._timer.restart()}.bind(this)).fail(d.exception)},m.prototype._loadMessages=function(){if(this._isLoadingMessages)return!1;this._isLoadingMessages=!0;var b=0;return c.render("core/loading",{}).then(function(a,b){return c.prependNodeContents(this.messageArea.find(p.MESSAGES),"
"+a+"
",b),this._getMessages(this._getUserId())}.bind(this)).then(function(a){return b=a.messages.length,c.render("core_message/message_area_messages",a)}).then(function(d,e){if(this.messageArea.find(p.MESSAGES+" "+p.LOADINGICON).remove(),b>0){var f=this.messageArea.node.find(p.BLOCKTIME+":first"),g=a(d).find(p.BLOCKTIME+":first").addBack();f.html()==g.html()&&f.remove();var h=this.messageArea.find(p.MESSAGES)[0].scrollHeight;c.prependNodeContents(this.messageArea.find(p.MESSAGES),d,e);var i=this.messageArea.find(p.MESSAGES)[0].scrollHeight;this.messageArea.find(p.MESSAGES).scrollTop(i-h),this._numMessagesDisplayed+=b}this._isLoadingMessages=!1}.bind(this)).fail(d.exception)},m.prototype._loadNewMessages=function(){if(this._isLoadingMessages)return!1;if(!this._getUserId())return!1;this._isLoadingMessages=!0;var b=!1,e=this.messageArea.find(p.MESSAGES);if(0!==e.length){var f=e.scrollTop(),g=e.innerHeight(),h=e[0].scrollHeight;f+g>=h&&(b=!0)}var i=0;return this._getMessages(this._getUserId(),!0).then(function(a){var b=this.messageArea.find(p.MESSAGES);return a.messages=a.messages.filter(function(a){var c=""+a.id+a.isread,d=b.find(p.MESSAGE+'[data-id="'+c+'"]');return!d.length}),i=a.messages.length,c.render("core_message/message_area_messages",a)}.bind(this)).then(function(d,e){i>0&&(d=a(d),d.find(p.BLOCKTIME).remove(),c.appendNodeContents(this.messageArea.find(p.MESSAGES),d,e),b&&this._scrollBottom(),this._numMessagesDisplayed+=i,this._timer.restart())}.bind(this)).always(function(){this._isLoadingMessages=!1}.bind(this)).fail(d.exception)},m.prototype._getMessages=function(a,c){var e={currentuserid:this.messageArea.getCurrentUserId(),otheruserid:a,limitfrom:this._numMessagesDisplayed,limitnum:this._numMessagesToRetrieve,newest:!0};c&&(e.createdfrom=this._earliestMessageTimestamp,e.limitfrom=0,e.limitnum=0);var f=b.call([{methodname:"core_message_data_for_messagearea_messages",args:e}]);return f[0].then(function(a){var b=a.messages;if(b&&b.length){var c=b[b.length-1];this._earliestMessageTimestamp?c.timecreated0?b.call(f)[f.length-1].then(function(){var b=null,c=this.messageArea.find(p.MESSAGE),d=c.last(),e=g[g.length-1];a.each(g,function(a,b){b.remove()}),d.data("id")===e.data("id")&&(b=this.messageArea.find(p.MESSAGE).last()),a.each(g,function(a,b){var c=b.data("blocktime");0===this.messageArea.find(p.MESSAGE+"[data-blocktime='"+c+"']").length&&this.messageArea.find(p.BLOCKTIME+"[data-blocktime='"+c+"']").remove()}.bind(this)),0===this.messageArea.find(p.MESSAGE).length&&this.messageArea.find(p.CONVERSATIONS+" "+p.CONTACT+"[data-userid='"+this._getUserId()+"']").remove(),this.messageArea.trigger(k.MESSAGESDELETED,[this._getUserId(),b])}.bind(this),d.exception):this.messageArea.trigger(k.MESSAGESDELETED,this._getUserId()),this._hideDeleteAction()},m.prototype._addScrollEventListener=function(a){this._scrollBottom(),this._numMessagesDisplayed=a,e.define(this.messageArea.find(p.MESSAGES),[e.events.scrollTop]),this.messageArea.onCustomEvent(e.events.scrollTop,this._loadMessages.bind(this))},m.prototype._deleteAllMessages=function(){this._confirmationModal?this._confirmationModal.show():j.get_strings([{key:"confirm"},{key:"deleteallconfirm",component:"message"}]).done(function(a){h.create({title:a[0],type:h.types.CONFIRM,body:a[1]},this.messageArea.find(p.DELETEALLMESSAGES)).done(function(a){this._confirmationModal=a,a.getRoot().on(i.yes,function(){var a=this._getUserId(),c={methodname:"core_message_delete_conversation",args:{userid:this.messageArea.getCurrentUserId(),otheruserid:a}};b.call([c])[0].then(function(){this.messageArea.find(p.MESSAGESAREA).empty(),this.messageArea.trigger(k.CONVERSATIONDELETED,a),this._hideDeleteAction()}.bind(this),d.exception)}.bind(this)),a.show()}.bind(this))}.bind(this))},m.prototype._hideDeleteAction=function(){this.messageArea.find(p.MESSAGE).removeAttr("role").removeAttr("aria-checked"),this.messageArea.find(p.MESSAGESAREA).removeClass("editing")},m.prototype._triggerCancelMessagesToDelete=function(){this.messageArea.trigger(k.CANCELDELETEMESSAGES)},m.prototype._addMessageToDom=function(){var a=b.call([{methodname:"core_message_data_for_messagearea_get_most_recent_message",args:{currentuserid:this.messageArea.getCurrentUserId(),otheruserid:this._getUserId()}}]);return a[0].then(function(a){return c.render("core_message/message_area_message",a)}).then(function(a,b){c.appendNodeContents(this.messageArea.find(p.MESSAGES),a,b),this.messageArea.find(p.SENDMESSAGETEXT).val("").trigger("input"),this._scrollBottom()}.bind(this)).fail(d.exception)},m.prototype._getUserId=function(){return this.messageArea.find(p.MESSAGES).data("userid")},m.prototype._scrollBottom=function(){var a=this.messageArea.find(p.MESSAGES);0!==a.length&&a.scrollTop(a[0].scrollHeight)},m.prototype._selectPreviousMessage=function(b,c){var d=a(b.target).closest(p.MESSAGE);do d=d.prev();while(d.length&&!d.is(p.MESSAGE));d.focus(),c.originalEvent.preventDefault(),c.originalEvent.stopPropagation()},m.prototype._selectNextMessage=function(b,c){var d=a(b.target).closest(p.MESSAGE);do d=d.next();while(d.length&&!d.is(p.MESSAGE));d.focus(),c.originalEvent.preventDefault(),c.originalEvent.stopPropagation()},m.prototype._setMessaging=function(b){a(b.target).closest(p.MESSAGERESPONSE).addClass("messaging")},m.prototype._clearMessaging=function(b){a(b.target).closest(p.MESSAGERESPONSE).removeClass("messaging")},m.prototype._startDeleting=function(a){var b=new g(this.messageArea);b.chooseMessagesToDelete(),a.preventDefault()},m.prototype._isEditing=function(){return this.messageArea.find(p.MESSAGESAREA).hasClass("editing")},m.prototype._toggleMessage=function(b){if(this._isEditing()){var c=a(b.target).closest(p.MESSAGE);"true"===c.attr("aria-checked")?c.attr("aria-checked","false"):c.attr("aria-checked","true")}},m.prototype._adjustMessagesAreaHeight=function(){var a=this.messageArea.find(p.MESSAGES),b=this.messageArea.find(p.MESSAGERESPONSE),c=b.outerHeight(),d=c-o,e=n-d;a.outerHeight(e)},m.prototype._sendMessageHandler=function(a,b){b.originalEvent.preventDefault(),this._sendMessage()},m.prototype._hideMessagingArea=function(){this.messageArea.find(p.MESSAGINGAREA).removeClass("show-messages").addClass("hide-messages")},m});
\ No newline at end of file
+define(["jquery","core/ajax","core/templates","core/notification","core/custom_interaction_events","core/auto_rows","core_message/message_area_actions","core/modal_factory","core/modal_events","core/str","core_message/message_area_events","core/backoff_timer"],function(a,b,c,d,e,f,g,h,i,j,k,l){function m(a){this.messageArea=a,this._init()}var n=500,o=50,p={BLOCKTIME:"[data-region='blocktime']",CANCELDELETEMESSAGES:"[data-action='cancel-delete-messages']",CONTACT:"[data-region='contact']",CONVERSATIONS:"[data-region='contacts'][data-region-content='conversations']",DELETEALLMESSAGES:"[data-action='delete-all-messages']",DELETEMESSAGES:"[data-action='delete-messages']",LOADINGICON:".loading-icon",MESSAGE:"[data-region='message']",MESSAGERESPONSE:"[data-region='response']",MESSAGES:"[data-region='messages']",MESSAGESAREA:"[data-region='messages-area']",MESSAGINGAREA:"[data-region='messaging-area']",SENDMESSAGE:"[data-action='send-message']",SENDMESSAGETEXT:"[data-region='send-message-txt']",SHOWCONTACTS:"[data-action='show-contacts']",STARTDELETEMESSAGES:"[data-action='start-delete-messages']"},q=1e3;return m.prototype._isSendingMessage=!1,m.prototype._isLoadingMessages=!1,m.prototype._numMessagesDisplayed=0,m.prototype._numMessagesToRetrieve=20,m.prototype._confirmationModal=null,m.prototype._earliestMessageTimestamp=0,m.prototype._backoffTimer=null,m.prototype.messageArea=null,m.prototype._init=function(){e.define(this.messageArea.node,[e.events.activate,e.events.up,e.events.down,e.events.enter]),a(window).height()<=670&&(n=400),f.init(this.messageArea.node),this.messageArea.onCustomEvent(k.CONVERSATIONSELECTED,this._viewMessages.bind(this)),this.messageArea.onCustomEvent(k.SENDMESSAGE,this._viewMessages.bind(this)),this.messageArea.onCustomEvent(k.CHOOSEMESSAGESTODELETE,this._chooseMessagesToDelete.bind(this)),this.messageArea.onCustomEvent(k.CANCELDELETEMESSAGES,this._hideDeleteAction.bind(this)),this.messageArea.onDelegateEvent(e.events.activate,p.SENDMESSAGE,this._sendMessage.bind(this)),this.messageArea.onDelegateEvent(e.events.activate,p.STARTDELETEMESSAGES,this._startDeleting.bind(this)),this.messageArea.onDelegateEvent(e.events.activate,p.DELETEMESSAGES,this._deleteMessages.bind(this)),this.messageArea.onDelegateEvent(e.events.activate,p.DELETEALLMESSAGES,this._deleteAllMessages.bind(this)),this.messageArea.onDelegateEvent(e.events.activate,p.CANCELDELETEMESSAGES,this._triggerCancelMessagesToDelete.bind(this)),this.messageArea.onDelegateEvent(e.events.activate,p.MESSAGE,this._toggleMessage.bind(this)),this.messageArea.onDelegateEvent(e.events.activate,p.SHOWCONTACTS,this._hideMessagingArea.bind(this)),this.messageArea.onDelegateEvent(e.events.up,p.MESSAGE,this._selectPreviousMessage.bind(this)),this.messageArea.onDelegateEvent(e.events.down,p.MESSAGE,this._selectNextMessage.bind(this)),this.messageArea.onDelegateEvent("focus",p.SENDMESSAGETEXT,this._setMessaging.bind(this)),this.messageArea.onDelegateEvent("blur",p.SENDMESSAGETEXT,this._clearMessaging.bind(this)),this.messageArea.onDelegateEvent(e.events.enter,p.SENDMESSAGETEXT,this._sendMessageHandler.bind(this)),a(document).on(f.events.ROW_CHANGE,this._adjustMessagesAreaHeight.bind(this));var b=this.messageArea.find(p.MESSAGES);b.length&&this._addScrollEventListener(b.find(p.MESSAGE).length),this._backoffTimer=new l(this._loadNewMessages.bind(this),l.getIncrementalCallback(this.messageArea.pollmin*q,q,this.messageArea.pollmax*q,this.messageArea.polltimeout*q)),this._backoffTimer.start()},m.prototype._viewMessages=function(e,f){this._numMessagesDisplayed=0,this._backoffTimer.stop(),this._earliestMessageTimestamp=0;var g=b.call([{methodname:"core_message_mark_all_messages_as_read",args:{useridto:this.messageArea.getCurrentUserId(),useridfrom:f}}]),h=0;return c.render("core/loading",{}).then(function(a,b){return c.replaceNodeContents(this.messageArea.find(p.MESSAGESAREA),a,b),g[0]}.bind(this)).then(function(){var b=this.messageArea.find(p.CONVERSATIONS+" "+p.CONTACT+"[data-userid='"+f+"']");return b.hasClass("unread")&&(b.removeClass("unread"),a(document).trigger("messagearea:conversationselected",f)),this._getMessages(f)}.bind(this)).then(function(a){return h=a.messages.length,c.render("core_message/message_area_messages_area",a)}).then(function(a,b){c.replaceNodeContents(this.messageArea.find(p.MESSAGESAREA),a,b),this._addScrollEventListener(h),this._backoffTimer.restart()}.bind(this)).fail(d.exception)},m.prototype._loadMessages=function(){if(this._isLoadingMessages)return!1;this._isLoadingMessages=!0;var b=0;return c.render("core/loading",{}).then(function(a,b){return c.prependNodeContents(this.messageArea.find(p.MESSAGES),""+a+"
",b),this._getMessages(this._getUserId())}.bind(this)).then(function(a){return b=a.messages.length,c.render("core_message/message_area_messages",a)}).then(function(d,e){if(this.messageArea.find(p.MESSAGES+" "+p.LOADINGICON).remove(),b>0){var f=this.messageArea.node.find(p.BLOCKTIME+":first"),g=a(d).find(p.BLOCKTIME+":first").addBack();f.html()==g.html()&&f.remove();var h=this.messageArea.find(p.MESSAGES)[0].scrollHeight;c.prependNodeContents(this.messageArea.find(p.MESSAGES),d,e);var i=this.messageArea.find(p.MESSAGES)[0].scrollHeight;this.messageArea.find(p.MESSAGES).scrollTop(i-h),this._numMessagesDisplayed+=b}this._isLoadingMessages=!1}.bind(this)).fail(d.exception)},m.prototype._loadNewMessages=function(){if(this._isLoadingMessages)return!1;if(!this._getUserId())return!1;this._isLoadingMessages=!0;var b=!1,e=this.messageArea.find(p.MESSAGES);if(0!==e.length){var f=e.scrollTop(),g=e.innerHeight(),h=e[0].scrollHeight;f+g>=h&&(b=!0)}var i=0;return this._getMessages(this._getUserId(),!0).then(function(a){var b=this.messageArea.find(p.MESSAGES);return a.messages=a.messages.filter(function(a){var c=""+a.id+a.isread,d=b.find(p.MESSAGE+'[data-id="'+c+'"]');return!d.length}),i=a.messages.length,c.render("core_message/message_area_messages",a)}.bind(this)).then(function(d,e){i>0&&(d=a(d),d.find(p.BLOCKTIME).remove(),c.appendNodeContents(this.messageArea.find(p.MESSAGES),d,e),b&&this._scrollBottom(),this._numMessagesDisplayed+=i,this._backoffTimer.restart())}.bind(this)).always(function(){this._isLoadingMessages=!1}.bind(this)).fail(d.exception)},m.prototype._getMessages=function(a,c){var e={currentuserid:this.messageArea.getCurrentUserId(),otheruserid:a,limitfrom:this._numMessagesDisplayed,limitnum:this._numMessagesToRetrieve,newest:!0};c&&(e.timefrom=this._earliestMessageTimestamp,e.limitfrom=0,e.limitnum=0);var f=b.call([{methodname:"core_message_data_for_messagearea_messages",args:e}]);return f[0].then(function(a){var b=a.messages;if(b&&b.length){var c=b[b.length-1];this._earliestMessageTimestamp?c.timecreated0?b.call(f)[f.length-1].then(function(){var b=null,c=this.messageArea.find(p.MESSAGE),d=c.last(),e=g[g.length-1];a.each(g,function(a,b){b.remove()}),d.data("id")===e.data("id")&&(b=this.messageArea.find(p.MESSAGE).last()),a.each(g,function(a,b){var c=b.data("blocktime");0===this.messageArea.find(p.MESSAGE+"[data-blocktime='"+c+"']").length&&this.messageArea.find(p.BLOCKTIME+"[data-blocktime='"+c+"']").remove()}.bind(this)),0===this.messageArea.find(p.MESSAGE).length&&this.messageArea.find(p.CONVERSATIONS+" "+p.CONTACT+"[data-userid='"+this._getUserId()+"']").remove(),this.messageArea.trigger(k.MESSAGESDELETED,[this._getUserId(),b])}.bind(this),d.exception):this.messageArea.trigger(k.MESSAGESDELETED,this._getUserId()),this._hideDeleteAction()},m.prototype._addScrollEventListener=function(a){this._scrollBottom(),this._numMessagesDisplayed=a,e.define(this.messageArea.find(p.MESSAGES),[e.events.scrollTop]),this.messageArea.onCustomEvent(e.events.scrollTop,this._loadMessages.bind(this))},m.prototype._deleteAllMessages=function(){this._confirmationModal?this._confirmationModal.show():j.get_strings([{key:"confirm"},{key:"deleteallconfirm",component:"message"}]).done(function(a){h.create({title:a[0],type:h.types.CONFIRM,body:a[1]},this.messageArea.find(p.DELETEALLMESSAGES)).done(function(a){this._confirmationModal=a,a.getRoot().on(i.yes,function(){var a=this._getUserId(),c={methodname:"core_message_delete_conversation",args:{userid:this.messageArea.getCurrentUserId(),otheruserid:a}};b.call([c])[0].then(function(){this.messageArea.find(p.MESSAGESAREA).empty(),this.messageArea.trigger(k.CONVERSATIONDELETED,a),this._hideDeleteAction()}.bind(this),d.exception)}.bind(this)),a.show()}.bind(this))}.bind(this))},m.prototype._hideDeleteAction=function(){this.messageArea.find(p.MESSAGE).removeAttr("role").removeAttr("aria-checked"),this.messageArea.find(p.MESSAGESAREA).removeClass("editing")},m.prototype._triggerCancelMessagesToDelete=function(){this.messageArea.trigger(k.CANCELDELETEMESSAGES)},m.prototype._addMessageToDom=function(){var a=b.call([{methodname:"core_message_data_for_messagearea_get_most_recent_message",args:{currentuserid:this.messageArea.getCurrentUserId(),otheruserid:this._getUserId()}}]);return a[0].then(function(a){return c.render("core_message/message_area_message",a)}).then(function(a,b){c.appendNodeContents(this.messageArea.find(p.MESSAGES),a,b),this.messageArea.find(p.SENDMESSAGETEXT).val("").trigger("input"),this._scrollBottom()}.bind(this)).fail(d.exception)},m.prototype._getUserId=function(){return this.messageArea.find(p.MESSAGES).data("userid")},m.prototype._scrollBottom=function(){var a=this.messageArea.find(p.MESSAGES);0!==a.length&&a.scrollTop(a[0].scrollHeight)},m.prototype._selectPreviousMessage=function(b,c){var d=a(b.target).closest(p.MESSAGE);do d=d.prev();while(d.length&&!d.is(p.MESSAGE));d.focus(),c.originalEvent.preventDefault(),c.originalEvent.stopPropagation()},m.prototype._selectNextMessage=function(b,c){var d=a(b.target).closest(p.MESSAGE);do d=d.next();while(d.length&&!d.is(p.MESSAGE));d.focus(),c.originalEvent.preventDefault(),c.originalEvent.stopPropagation()},m.prototype._setMessaging=function(b){a(b.target).closest(p.MESSAGERESPONSE).addClass("messaging")},m.prototype._clearMessaging=function(b){a(b.target).closest(p.MESSAGERESPONSE).removeClass("messaging")},m.prototype._startDeleting=function(a){var b=new g(this.messageArea);b.chooseMessagesToDelete(),a.preventDefault()},m.prototype._isEditing=function(){return this.messageArea.find(p.MESSAGESAREA).hasClass("editing")},m.prototype._toggleMessage=function(b){if(this._isEditing()){var c=a(b.target).closest(p.MESSAGE);"true"===c.attr("aria-checked")?c.attr("aria-checked","false"):c.attr("aria-checked","true")}},m.prototype._adjustMessagesAreaHeight=function(){var a=this.messageArea.find(p.MESSAGES),b=this.messageArea.find(p.MESSAGERESPONSE),c=b.outerHeight(),d=c-o,e=n-d;a.outerHeight(e)},m.prototype._sendMessageHandler=function(a,b){b.originalEvent.preventDefault(),this._sendMessage()},m.prototype._hideMessagingArea=function(){this.messageArea.find(p.MESSAGINGAREA).removeClass("show-messages").addClass("hide-messages")},m});
\ No newline at end of file
diff --git a/message/amd/src/message_area.js b/message/amd/src/message_area.js
index 681712ac441..73bad76ce66 100644
--- a/message/amd/src/message_area.js
+++ b/message/amd/src/message_area.js
@@ -29,15 +29,30 @@ define(['jquery', 'core_message/message_area_contacts', 'core_message/message_ar
* Messagearea class.
*
* @param {String} selector The selector for the page region containing the message area.
+ * @param {int} pollmin
+ * @param {int} pollmax
+ * @param {int} polltimeout
*/
- function Messagearea(selector) {
+ function Messagearea(selector, pollmin, pollmax, polltimeout) {
this.node = $(selector);
+ this.pollmin = pollmin;
+ this.pollmax = pollmax;
+ this.polltimeout = polltimeout;
this._init();
}
/** @type {jQuery} The jQuery node for the page region containing the message area. */
Messagearea.prototype.node = null;
+ /** @type {int} The minimum time to poll for messages. */
+ Messagearea.prototype.pollmin = null;
+
+ /** @type {int} The maximum time to poll for messages. */
+ Messagearea.prototype.pollmax = null;
+
+ /** @type {int} The time used once we have reached the maximum polling time. */
+ Messagearea.prototype.polltimeout = null;
+
/**
* Initialise the other objects we require.
*/
diff --git a/message/amd/src/message_area_messages.js b/message/amd/src/message_area_messages.js
index a24ef0b0990..24d3c8ad60c 100644
--- a/message/amd/src/message_area_messages.js
+++ b/message/amd/src/message_area_messages.js
@@ -53,6 +53,9 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/cust
STARTDELETEMESSAGES: "[data-action='start-delete-messages']"
};
+ /** @type {int} The number of milliseconds in a second. */
+ var MILLISECONDSINSEC = 1000;
+
/**
* Messages class.
*
@@ -81,8 +84,8 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/cust
/** @type {int} the timestamp for the earliest visible message */
Messages.prototype._earliestMessageTimestamp = 0;
- /** @type {BackOffTime} the backoff timer */
- Messages.prototype._timer = null;
+ /** @type {BackOffTimer} the backoff timer */
+ Messages.prototype._backoffTimer = null;
/** @type {Messagearea} The messaging area object. */
Messages.prototype.messageArea = null;
@@ -146,12 +149,12 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/cust
}
// Create a timer to poll the server for new messages.
- this._timer = new BackOffTimer(function() {
- this._loadNewMessages();
- }.bind(this));
+ this._backoffTimer = new BackOffTimer(this._loadNewMessages.bind(this),
+ BackOffTimer.getIncrementalCallback(this.messageArea.pollmin * MILLISECONDSINSEC, MILLISECONDSINSEC,
+ this.messageArea.pollmax * MILLISECONDSINSEC, this.messageArea.polltimeout * MILLISECONDSINSEC));
// Start the timer.
- this._timer.start();
+ this._backoffTimer.start();
};
/**
@@ -166,7 +169,7 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/cust
// We are viewing another user, or re-loading the panel, so set number of messages displayed to 0.
this._numMessagesDisplayed = 0;
// Stop the existing timer so we can set up the new user's messages.
- this._timer.stop();
+ this._backoffTimer.stop();
// Reset the earliest timestamp when we change the messages view.
this._earliestMessageTimestamp = 0;
@@ -203,7 +206,7 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/cust
Templates.replaceNodeContents(this.messageArea.find(SELECTORS.MESSAGESAREA), html, js);
this._addScrollEventListener(numberreceived);
// Restart the poll timer.
- this._timer.restart();
+ this._backoffTimer.restart();
}.bind(this)).fail(Notification.exception);
};
@@ -321,7 +324,7 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/cust
// Increment the number of messages displayed.
this._numMessagesDisplayed += numberreceived;
// Reset the poll timer because the user may be active.
- this._timer.restart();
+ this._backoffTimer.restart();
}
}.bind(this)).always(function() {
// Mark that we are no longer busy loading data.
@@ -349,7 +352,7 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/cust
// If we're trying to load new messages since the message UI was
// rendered. Used for ajax polling while user is on the message UI.
if (fromTimestamp) {
- args.createdfrom = this._earliestMessageTimestamp;
+ args.timefrom = this._earliestMessageTimestamp;
// Remove limit and offset. We want all new messages.
args.limitfrom = 0;
args.limitnum = 0;
@@ -381,10 +384,11 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/cust
}
return data;
- }.bind(this)).fail(function() {
+ }.bind(this)).fail(function(ex) {
// Stop the timer if we received an error so that we don't keep spamming the server.
- this._timer.stop();
- }.bind(this)).fail(Notification.exception);
+ this._backoffTimer.stop();
+ Notification.exception(ex);
+ }.bind(this));
};
/**
diff --git a/message/classes/api.php b/message/classes/api.php
index 2d6150f0386..25910dae2ba 100644
--- a/message/classes/api.php
+++ b/message/classes/api.php
@@ -291,31 +291,29 @@ class api {
* @param int $limitfrom
* @param int $limitnum
* @param string $sort
- * @param int $createdfrom the timestamp from which the messages were created
- * @param int $createdto the time up until which the message was created
+ * @param int $timefrom the time from the message being sent
+ * @param int $timeto the time up until the message being sent
* @return array
*/
public static function get_messages($userid, $otheruserid, $limitfrom = 0, $limitnum = 0,
- $sort = 'timecreated ASC', $createdfrom = 0, $createdto = 0) {
+ $sort = 'timecreated ASC', $timefrom = 0, $timeto = 0) {
- if (!empty($createdfrom)) {
+ if (!empty($timefrom)) {
// Check the cache to see if we even need to do a DB query.
- $cache = \cache::make('core', 'message_last_created');
- $ids = [$otheruserid, $userid];
- sort($ids);
- $key = implode('_', $ids);
+ $cache = \cache::make('core', 'message_time_last_message_between_users');
+ $key = helper::get_last_message_time_created_cache_key($otheruserid, $userid);
$lastcreated = $cache->get($key);
// The last known message time is earlier than the one being requested so we can
// just return an empty result set rather than having to query the DB.
- if ($lastcreated && $lastcreated < $createdfrom) {
+ if ($lastcreated && $lastcreated < $timefrom) {
return [];
}
}
$arrmessages = array();
if ($messages = helper::get_messages($userid, $otheruserid, 0, $limitfrom, $limitnum,
- $sort, $createdfrom, $createdto)) {
+ $sort, $timefrom, $timeto)) {
$arrmessages = helper::create_messages($userid, $messages);
}
diff --git a/message/classes/helper.php b/message/classes/helper.php
index 3a4c70d730d..8ae5ea67172 100644
--- a/message/classes/helper.php
+++ b/message/classes/helper.php
@@ -43,12 +43,12 @@ class helper {
* @param int $limitfrom
* @param int $limitnum
* @param string $sort
- * @param int $createdfrom the time from which the message was created
- * @param int $createdto the time up until which the message was created
+ * @param int $timefrom the time from the message being sent
+ * @param int $timeto the time up until the message being sent
* @return array of messages
*/
public static function get_messages($userid, $otheruserid, $timedeleted = 0, $limitfrom = 0, $limitnum = 0,
- $sort = 'timecreated ASC', $createdfrom = 0, $createdto = 0) {
+ $sort = 'timecreated ASC', $timefrom = 0, $timeto = 0) {
global $DB;
$messageid = $DB->sql_concat("'message_'", 'id');
@@ -77,16 +77,16 @@ class helper {
$otheruserid, $userid, $timedeleted);
$where = array();
- if (!empty($createdfrom)) {
+ if (!empty($timefrom)) {
$where[] = 'AND timecreated >= ?';
- $params1[] = $createdfrom;
- $params2[] = $createdfrom;
+ $params1[] = $timefrom;
+ $params2[] = $timefrom;
}
- if (!empty($createdto)) {
+ if (!empty($timeto)) {
$where[] = 'AND timecreated <= ?';
- $params1[] = $createdto;
- $params2[] = $createdto;
+ $params1[] = $timeto;
+ $params2[] = $timeto;
}
$sql = str_replace('%where%', implode(' ', $where), $sql);
@@ -270,4 +270,17 @@ class helper {
return $params;
}
+
+ /**
+ * Returns the cache key for the time created value of the last message between two users.
+ *
+ * @param int $userid
+ * @param int $user2id
+ * @return string
+ */
+ public static function get_last_message_time_created_cache_key($userid, $user2id) {
+ $ids = [$userid, $user2id];
+ sort($ids);
+ return implode('_', $ids);
+ }
}
diff --git a/message/classes/output/messagearea/message_area.php b/message/classes/output/messagearea/message_area.php
index a3dd242de31..3c765917710 100644
--- a/message/classes/output/messagearea/message_area.php
+++ b/message/classes/output/messagearea/message_area.php
@@ -63,6 +63,21 @@ class message_area implements templatable, renderable {
*/
public $requestedconversation;
+ /**
+ * @var int The minimum time to poll for messages.
+ */
+ public $pollmin;
+
+ /**
+ * @var int The maximum time to poll for messages.
+ */
+ public $pollmax;
+
+ /**
+ * @var int The time used once we have reached the maximum polling time.
+ */
+ public $polltimeout;
+
/**
* Constructor.
*
@@ -71,13 +86,20 @@ class message_area implements templatable, renderable {
* @param array $contacts
* @param array|null $messages
* @param bool $requestedconversation
+ * @param int $pollmin
+ * @param int $pollmax
+ * @param int $polltimeout
*/
- public function __construct($userid, $otheruserid, $contacts, $messages, $requestedconversation) {
+ public function __construct($userid, $otheruserid, $contacts, $messages, $requestedconversation, $pollmin, $pollmax,
+ $polltimeout) {
$this->userid = $userid;
$this->otheruserid = $otheruserid;
$this->contacts = $contacts;
$this->messages = $messages;
$this->requestedconversation = $requestedconversation;
+ $this->pollmin = $pollmin;
+ $this->pollmax = $pollmax;
+ $this->polltimeout = $polltimeout;
}
public function export_for_template(\renderer_base $output) {
@@ -89,6 +111,9 @@ class message_area implements templatable, renderable {
$data->messages = $messages->export_for_template($output);
$data->isconversation = true;
$data->requestedconversation = $this->requestedconversation;
+ $data->pollmin = $this->pollmin;
+ $data->pollmax = $this->pollmax;
+ $data->polltimeout = $this->polltimeout;
return $data;
}
diff --git a/message/classes/message_last_created_cache_source.php b/message/classes/time_last_message_between_users.php
similarity index 79%
rename from message/classes/message_last_created_cache_source.php
rename to message/classes/time_last_message_between_users.php
index ea0cd05df1b..750a552dbbf 100644
--- a/message/classes/message_last_created_cache_source.php
+++ b/message/classes/time_last_message_between_users.php
@@ -15,7 +15,7 @@
// along with Moodle. If not, see .
/**
- * Cache data source for the last created message between users.
+ * Cache data source for the time of the last message between users.
*
* @package core_message
* @category cache
@@ -23,32 +23,33 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+namespace core_message;
defined('MOODLE_INTERNAL') || die();
/**
- * Cache data source for the last created message between users.
+ * Cache data source for the time of the last message between users.
*
* @package core_message
* @category cache
* @copyright 2016 Ryan Wyllie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class message_last_created_cache_source implements \cache_data_source {
+class time_last_message_between_users implements \cache_data_source {
- /** @var message_last_created_cache_source the singleton instance of this class. */
+ /** @var time_last_message_between_users the singleton instance of this class. */
protected static $instance = null;
/**
* Returns an instance of the data source class that the cache can use for loading data using the other methods
* specified by the cache_data_source interface.
*
- * @param cache_definition $definition
+ * @param \cache_definition $definition
* @return object
*/
- public static function get_instance_for_cache(cache_definition $definition) {
+ public static function get_instance_for_cache(\cache_definition $definition) {
if (is_null(self::$instance)) {
- self::$instance = new message_last_created_cache_source();
+ self::$instance = new time_last_message_between_users();
}
return self::$instance;
}
@@ -62,7 +63,7 @@ class message_last_created_cache_source implements \cache_data_source {
public function load_for_cache($key) {
list($userid1, $userid2) = explode('_', $key);
- $message = \core_message\api::get_most_recent_message($userid1, $userid2);
+ $message = api::get_most_recent_message($userid1, $userid2);
if ($message) {
return $message->timecreated;
diff --git a/message/externallib.php b/message/externallib.php
index 98b5634c9d6..a3b4247b746 100644
--- a/message/externallib.php
+++ b/message/externallib.php
@@ -901,7 +901,7 @@ class core_message_external extends external_api {
'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0),
'newest' => new external_value(PARAM_BOOL, 'Newest first?', VALUE_DEFAULT, false),
- 'createdfrom' => new external_value(PARAM_INT,
+ 'timefrom' => new external_value(PARAM_INT,
'The timestamp from which the messages were created', VALUE_DEFAULT, 0),
)
);
@@ -920,7 +920,7 @@ class core_message_external extends external_api {
* @since 3.2
*/
public static function data_for_messagearea_messages($currentuserid, $otheruserid, $limitfrom = 0, $limitnum = 0,
- $newest = false, $createdfrom = 0) {
+ $newest = false, $timefrom = 0) {
global $CFG, $PAGE, $USER;
// Check if messaging is enabled.
@@ -936,7 +936,7 @@ class core_message_external extends external_api {
'limitfrom' => $limitfrom,
'limitnum' => $limitnum,
'newest' => $newest,
- 'createdfrom' => $createdfrom,
+ 'timefrom' => $timefrom,
);
self::validate_parameters(self::data_for_messagearea_messages_parameters(), $params);
self::validate_context($systemcontext);
@@ -959,18 +959,18 @@ class core_message_external extends external_api {
// case those messages will be lost.
//
// Instead we ignore the current time in the result set to ensure that second is allowed to finish.
- if (!empty($createdfrom)) {
- $createdto = time() - 1;
+ if (!empty($timefrom)) {
+ $timeto = time() - 1;
} else {
- $createdto = 0;
+ $timeto = 0;
}
// No requesting messages from the current time, as stated above.
- if ($createdfrom == time()) {
- $mesages = [];
+ if ($timefrom == time()) {
+ $messages = [];
} else {
$messages = \core_message\api::get_messages($currentuserid, $otheruserid, $limitfrom,
- $limitnum, $sort, $createdfrom, $createdto);
+ $limitnum, $sort, $timefrom, $timeto);
}
$messages = new \core_message\output\messagearea\messages($currentuserid, $otheruserid, $messages);
diff --git a/message/index.php b/message/index.php
index 0f834a88a05..5789216570f 100644
--- a/message/index.php
+++ b/message/index.php
@@ -127,8 +127,11 @@ if (!empty($user2->id)) {
$messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 20, 'timecreated DESC');
}
+$pollmin = !empty($CFG->messagingminpoll) ? $CFG->messagingminpoll : MESSAGE_DEFAULT_MIN_POLL_IN_SECONDS;
+$pollmax = !empty($CFG->messagingmaxpoll) ? $CFG->messagingmaxpoll : MESSAGE_DEFAULT_MAX_POLL_IN_SECONDS;
+$polltimeout = !empty($CFG->messagingtimeoutpoll) ? $CFG->messagingtimeoutpoll : MESSAGE_DEFAULT_TIMEOUT_POLL_IN_SECONDS;
$messagearea = new \core_message\output\messagearea\message_area($user1->id, $user2->id, $conversations, $messages,
- $requestedconversation);
+ $requestedconversation, $pollmin, $pollmax, $polltimeout);
// Now the page contents.
echo $OUTPUT->header();
diff --git a/message/lib.php b/message/lib.php
index 34431beabbe..f3820c39cea 100644
--- a/message/lib.php
+++ b/message/lib.php
@@ -76,6 +76,13 @@ define('MESSAGE_PERMITTED_MASK', 0x0c); // 1100
*/
define('MESSAGE_DEFAULT_PERMITTED', 'permitted');
+/**
+ * Set default values for polling.
+ */
+define('MESSAGE_DEFAULT_MIN_POLL_IN_SECONDS', 10);
+define('MESSAGE_DEFAULT_MAX_POLL_IN_SECONDS', 2 * MINSECS);
+define('MESSAGE_DEFAULT_TIMEOUT_POLL_IN_SECONDS', 5 * MINSECS);
+
/**
* Retrieve users blocked by $user1
*
diff --git a/message/templates/message_area.mustache b/message/templates/message_area.mustache
index 15af327e0ba..8667f416daa 100644
--- a/message/templates/message_area.mustache
+++ b/message/templates/message_area.mustache
@@ -32,7 +32,7 @@
{{#js}}
require(['core_message/message_area'],
function(Messagearea) {
- new Messagearea('.messaging-area-container');
+ new Messagearea('.messaging-area-container', {{pollmin}}, {{pollmax}}, {{polltimeout}});
}
);
{{/js}}
diff --git a/message/tests/api_test.php b/message/tests/api_test.php
index 15376e04937..9c52f86f990 100644
--- a/message/tests/api_test.php
+++ b/message/tests/api_test.php
@@ -957,7 +957,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
/**
* Test retrieving messages by providing a minimum timecreated value.
*/
- public function test_get_messages_created_from_only() {
+ public function test_get_messages_time_from_only() {
// Create some users.
$user1 = self::getDataGenerator()->create_user();
$user2 = self::getDataGenerator()->create_user();
@@ -972,7 +972,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
$this->send_fake_message($user1, $user2, 'Message 3', 0, $time + 3);
$this->send_fake_message($user2, $user1, 'Message 4', 0, $time + 4);
- // Retrieve the messages.
+ // Retrieve the messages from $time, which should be all of them.
$messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 0, 'timecreated ASC', $time);
// Confirm the message data is correct.
@@ -988,7 +988,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
$this->assertContains('Message 3', $message3->text);
$this->assertContains('Message 4', $message4->text);
- // Retrieve the messages.
+ // Retrieve the messages from $time + 3, which should only be the 2 last messages.
$messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 0, 'timecreated ASC', $time + 3);
// Confirm the message data is correct.
@@ -1004,7 +1004,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
/**
* Test retrieving messages by providing a maximum timecreated value.
*/
- public function test_get_messages_created_to_only() {
+ public function test_get_messages_time_to_only() {
// Create some users.
$user1 = self::getDataGenerator()->create_user();
$user2 = self::getDataGenerator()->create_user();
@@ -1019,7 +1019,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
$this->send_fake_message($user1, $user2, 'Message 3', 0, $time + 3);
$this->send_fake_message($user2, $user1, 'Message 4', 0, $time + 4);
- // Retrieve the messages.
+ // Retrieve the messages up until $time + 4, which should be all of them.
$messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 0, 'timecreated ASC', 0, $time + 4);
// Confirm the message data is correct.
@@ -1035,7 +1035,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
$this->assertContains('Message 3', $message3->text);
$this->assertContains('Message 4', $message4->text);
- // Retrieve the messages.
+ // Retrieve the messages up until $time + 2, which should be the first two.
$messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 0, 'timecreated ASC', 0, $time + 2);
// Confirm the message data is correct.
@@ -1051,7 +1051,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
/**
* Test retrieving messages by providing a minimum and maximum timecreated value.
*/
- public function test_get_messages_created_from_and_to() {
+ public function test_get_messages_time_from_and_to() {
// Create some users.
$user1 = self::getDataGenerator()->create_user();
$user2 = self::getDataGenerator()->create_user();
@@ -1066,7 +1066,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
$this->send_fake_message($user1, $user2, 'Message 3', 0, $time + 3);
$this->send_fake_message($user2, $user1, 'Message 4', 0, $time + 4);
- // Retrieve the messages.
+ // Retrieve the messages from $time + 2 up until $time + 3, which should be 2nd and 3rd message.
$messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 0, 'timecreated ASC', $time + 2, $time + 3);
// Confirm the message data is correct.
diff --git a/message/tests/externallib_test.php b/message/tests/externallib_test.php
index c739b1a4e36..3f1e38e3dd7 100644
--- a/message/tests/externallib_test.php
+++ b/message/tests/externallib_test.php
@@ -1982,7 +1982,7 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
/**
* Tests retrieving messages.
*/
- public function test_messagearea_messages_createfrom() {
+ public function test_messagearea_messages_timefrom() {
$this->resetAfterTest(true);
// Create some users.
@@ -1999,7 +1999,7 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
$this->send_message($user1, $user2, 'Message 3', 0, $time - 2);
$this->send_message($user2, $user1, 'Message 4', 0, $time - 1);
- // Retrieve the messages.
+ // Retrieve the messages from $time - 3, which should be the 3 most recent messages.
$result = core_message_external::data_for_messagearea_messages($user1->id, $user2->id, 0, 0, false, $time - 3);
// We need to execute the return values cleaning process to simulate the web service server.