Step 1 - Create a flag
There is nothing in the Message module equivalent to the "new content" indicator for nodes. However, messages created by the Message module are entities, so messages can be flagged (using the Flag module), which is what can be used to implement the equivalent of such new content indicator.
So to indicate if a message is read or unread, introduce a (non global) flag:
- with machine name (say)
message_viewed
.
- labeled (say)
Message viewed
.
- only role
authenticated user
may use this flag.
The usage of this flag will be like so:
- flagged messages are consider as read.
- all other messages are considered as unread.
Here is an export of the Message viewed
flag:
$flags = array();
// Exported flag: "Message viewed".
$flags['message_viewed'] = array (
'entity_type' => 'message',
'title' => 'Message viewed',
'global' => '0',
'types' =>
array (
),
'flag_short' => 'Mark message as viewed',
'flag_long' => 'Use this link to mark a message as viewed',
'flag_message' => 'Message marked as viewed',
'unflag_short' => 'Mark message as not yet viewed',
'unflag_long' => 'Use this link to mark a message as not yet viewed',
'unflag_message' => 'Message marked as not yet viewed',
'unflag_denied_text' => '',
'link_type' => 'toggle',
'weight' => 0,
'show_in_links' =>
array (
'full' => 'full',
'message_notify_email_subject' => 0,
'message_notify_email_body' => 0,
),
'show_as_field' => 0,
'show_on_form' => 0,
'access_author' => '',
'show_contextual_link' => 0,
'api_version' => 3,
);
return $flags;
Step 2 - Create a view Messages by user (Message)
Add a new view
- View name "Messages by user".
- Show Message.
- Type All.
- Create a page (not a block)
Create 3 table displays of this view
- All messages
- Read messages
- Unread messages
Add Contextual Filters for all 3 displays
- Message: User uid, and for "When the filter value is NOT in the URL" use "Provide default value" with Type "User ID from logged in user".
Add Relationships for all 3 displays
- Message: User uid
- Flags: message_viewed (by current user)
Add Fields for all 3 displays
- Message: Message ID (Msg ID)
- Message: Timestamp (Created on)
- Message: Render message (Get text) (Text)
(User) User: Name (User) ( 1 )
( 1 ) : Use "Exclude from display" for this field, which is only needed to add a "Global: Text area" to the views headers which contains something like Messages for user [name]
.
Add Sort criteria for all 3 displays
- Message: Timestamp (desc)
Refine display All messages
Extra fields:
- (flag) Flags: Flagged (Read Y/N)
- (flag) Flags: Flagged time (Read on)
Filter criteria: none
Page settings:
- Path:
/user/%/messages
- Menu tab: Messages
Refine display Read messages
Extra fields:
- (flag) Flags: Flagged time (Read on)
Filter criteria:
- (flag) Flags: Flagged (True)
Page settings:
- Path:
/user/%/messages/read
- Menu tab: Read Messages
Refine display Unread messages
Extra fields: none
Filter criteria:
- (flag) Flags: Flagged (False)
Page settings:
- Path:
/user/%/messages/unread
- Menu tab: Unread Messages
Step 3 - Use Rules to flag/unflag messages
To actually mark a message as read (or unread), use the Rules module to flag (or unflag) a message with the Message viewed
flag (from step 1). For this, create 2 (extremely basic) Rules Components as further detailed below (both of them use a "Message" as a variable).
To mark Unread msgs as Read
Here is the Rules Component (in Rules export format) to let the currently logged in user flag a message (using the Message viewed
flag):
{ "rules_flag_a_message" : {
"LABEL" : "Flag a message",
"PLUGIN" : "rule",
"OWNER" : "rules",
"REQUIRES" : [ "flag" ],
"USES VARIABLES" : { "message_to_flag" : { "label" : "Message to be flagged", "type" : "message" } },
"DO" : [
{ "flag_flagmessage" : {
"flag" : "message_viewed",
"message" : [ "message-to-flag" ],
"flagging_user" : [ "site:current-user" ],
"permission_check" : "1"
}
}
]
}
}
If you have the Rules UI submodule enabled, you should be able to import the above rule in your own site, provided you first defined the flag as in step 1 (with same machine name, or after you adapted that name in the exported rule above).
To mark Read msgs as Unread
Here is the (similar) Rules Component (in Rules export format) to let the currently logged in user unflag a message (using the Message viewed
flag):
{ "rules_unflag_a_message" : {
"LABEL" : "Unflag a message",
"PLUGIN" : "rule",
"OWNER" : "rules",
"REQUIRES" : [ "flag" ],
"USES VARIABLES" : { "message_to_unflag" : { "label" : "Message to be unflagged", "type" : "message" } },
"DO" : [
{ "flag_unflagmessage" : {
"flag" : "message_viewed",
"message" : [ "message-to-unflag" ],
"flagging_user" : [ "site:current-user" ],
"permission_check" : "1"
}
}
]
}
}
If you have the Rules UI submodule enabled, you should be able to import the above rule in your own site, provided you first defined the flag as in step 1 (with same machine name, or after you adapted that name in the exported rule above).
Step 4 - Trigger the Rules Component to mark messages
About the only thing left to start marking messages as read (or unread), is to have some mechanism to trigger the appropriate Rules Component from step 3, and this from within the views display Unread messages (or Read messages) created in step 2.
Using the Views Bulk Operations (VBO) module is a possible approach for triggering Rules Components. It facilitates processing messages one by one, or a list of selected messages, or even all messages in a single operation. Read on for further details about this approach.
Add VBO processing to mark Unread messages as Read
Enhance the views display Unread messages (from step 2), by adding a VBO field like so:
Add VBO processing to eventually mark Read messages as Unread
Enhance the views display Read messages (from step 2), by adding a VBO field like so:
( 2 ): this is actually a reference to one of the 2 Rules Components from step 3, and which is what in the end will make it all work automagically!
Step 5 - Create notifications about Unread Messages
Enable the Menu Badges module
Enable the Menu Badges module to show the number of Unread Messages via a (red) counter related to the Unread messages view (from step 2), which will look similar to this screenprint:

Refer to "How to create a basic message - notifications system displaying a real time message counter badge?" for more details about this (great) module.
Create Messages counter Views display
Improve the view created in step 2 before, by adding an extra views display which, at any time, will contain (only!) a counter of the number of messages contained in the Unread messages views display.
Here is how to do so:
- Add a new views display, named (say) "Unread msgs badge".
- Make sure to select "Menu Badge" for its display (that's part of the magic ...).
- Add field "Message: Message ID (Msg ID)"
- As Contextual filters add "Message: User uid", and for "When the filter value is NOT in the URL" use "Provide default value" with Type "User ID from logged in user".
- As Relationships add "Flags: message_viewed (by current user)".
- Filter criteria: "(flag) Flags: Flagged (False)".
- Enable aggregation (Use aggregation: Yes) and change the aggregation type for field "Message: Message ID (Msg ID)" to COUNT.
- Attention: with the above setup, when there are 0 unread messages, the notification badge will be shown with a
0
in it. If in this case you don't want any badge at all, then check the option "Hide if empty" when configuring this "Message: Message ID (Msg ID)" field.
Configure menu tab "Unread messages" for the Menu Badges
If the views configuration of the "Unread msgs badge" display (as described above) is done correct, then the Views preview result should (only) show a number that matches the amount of messages that are unflagged (= number of Unread messages).
All that's left is this:
- navigate to relative path
admin/structure/menu/menu-badges-tabs
.
- within the search box (at the top), in the "Menu path" field, enter part of the path used for the views display Unread messages, eg something like "unread", to find the entry with path
user/%/messages/unread
.
- for this entry, select "Messages by user: Unread msgs badge" (that is then name of our view, followed by the name of the views display) from the selection list related to "Menu Badge".
After you hit the Save button, the (red) notification button should start showing up (if you do have at least 1 unflagged message ...).
Step 6 - Possible variations
The approach described above can be used for any entity for which you want to create a similar Views based solution to allow each user to manage their own entity based data. Just change any occurence of "Message" to "YourEntityOfChoice" in the solution described above.
Yet another variation is to use similar/additional flags: in this case the flag was just to indicate read versus unread. But as per the spirit of the Flag module, you could use it for things such as:
- entities a user likes or doesn't like.
- users that a user wants to follow or mute.
- ...
Voilà ...
No custom coding required, only using the joint power of a few popular contributed modules such as Views, Flag, Rules, Message (=VFRM) and VBO, with Menu Badges as a hidden gem added to it.