Private Message Advanced
Private Message Advanced adds group conversation features to Private Message: leave a thread, remove a member, add people, and name a conversation. It works on the released 4.x module with no patch.
Why this exists
Private Message identifies a thread by its exact set of members. That is how it finds "the conversation between these people", and it is why nobody has been able to add leaving, removing or adding members: once C leaves the A, B, C thread, it has the same members as the real A, B conversation, and the lookup can return either one. Adding a member has the mirror problem.
The request has been open for years across several issues, and nothing was ever decided:
- #2960360: Add a method to remove a user from a thread (2018, RTBC since 2020, never committed)
- #2942602: Allow separate threads with same members (2018, postponed)
- #3158310: Unique threads per user grouping (2020)
- #3283616: Remove restriction for one thread per user/group of users (2022, closed as duplicate)
- #3343833: Is there any way to implement a "Leave chat" feature? (2023, postponed)
- #3355273: Create "group" private message thread type (2023, not merged)
- #3484243: User ban in a 2+ message thread (2024)
So I built it as a separate module. I think this is the way forward. If the Private Message maintainers agree, I am all for merging it into their module.
The approach
The members field stays the live roster. Leaving and removing take the person out of it, adding puts them in. Every inbox query, unread count, access check and notification in Private Message already reads that field, so the person's inbox and thread page follow with no further code.
One small table records every change: thread, person, who did it, joined or left or removed, when. It carries the rule that dissolves the collision: a thread with any row in that table is reachable by its id only and is never again the answer to a member-set lookup. The shrunken A, B group lives on as its own conversation, and a new message from A to B lands in the untouched one-on-one. Threads that were never edited keep their uniqueness exactly as before. The rule is applied by swapping the module's thread service for a subclass that overrides the one lookup method.
Two details make it hold. Private Message writes a person's per-thread history row only when a thread is created, and every inbox query joins on it, so a member added later would never see the thread. This module writes that row at join time with its cutoff set to now, which also means a newcomer sees only what was said after they joined. And every change posts a system line in the thread from the person who made it, "Alex added Sam", "Sam left", which is what makes the thread appear for a newcomer and what the others see.
What it changes in the database
- One new table of its own,
private_message_advanced_log, the membership change log described above. - One new column on the existing private message table:
membership_event, a base field on the private_message entity holding joined, left, removed or renamed for a system line, and empty for a normal message.
No existing thread, message or member data is modified.
Features
- Leave a group. Remove a member. Add people; adding to a one-to-one starts a new group so the one-to-one keeps its history.
- Name a conversation/thread.
- A Details page per thread: the name, the member list as a View you control, an Add members field, and Leave or Remove on each row.
- Permissions for leave, add, remove and rename. A setting caps conversation size.
- An event after every change, for other modules.
Requirements
- Private Message 4.0.0-alpha4 or later
- Views
Depends on
Dependencies of the latest stable release
No dependencies recorded for this project.
Required by
Tracked projects that depend on this one
No tracked projects depend on this one yet.
Activity
Releases
| Version | Type | Core | Notes | Release date | |
|---|---|---|---|---|---|
| 1.0.x-dev | Dev | 10–11 | Sep 20, 2026 |