Problem/Motivation
When deleting a thread, I would expect all relevant messages to be removed as well.
Currently, the \Drupal\private_message\Entity\PrivateMessageThread::delete is supposed to be loading all messages and delete them, but the underlying \Drupal\private_message\Entity\PrivateMessageThread::getMessages method, is having an edge case where it might skip a few messages.
Steps to reproduce
I will provide a test and a solution, but the main idea is:
* Create 2 users, user A, and user B.
* Create a ban from user A to user B.
* Login as user A.
* Delete the thread.
Because the user A has banned user B, they are not able to view the messages from user B because \Drupal\private_message\Entity\PrivateMessageThread::getMessages is filtering them out using the current user as a fixed source of identification.
However, the delete method also calls for this method and if there is an active session of user A, the messages found to be deleted are filtering out the banned messages.
Proposed resolution
Add an optional parameter to the ::getMessages() method to allow the delete method to call it and include banned messages.
This will retain the BC as well.
Update - 2nd issue: I have found a second issue: The \Drupal\private_message\Entity\PrivateMessageThread::delete method is responsible for deleting the relevant entities of the thread before deleting it as well as clearing the cache after that.
However, the ::delete method of the entity is not reliable for this functionality as it is mainly a wrapper around the storage ::delete method. It is not invoked by core API.
* Create a thread with some messages.
* Call $thread->delete()
* Assert that the messages are deleted. (works fine)
* Create a thread with some messages.
* Call \Drupal::entityTypeManager()->getStorage('private_message_thread')->delete([$thread]);
* Messages are not cleaned up.
Split the functionality to the designated pre/post delete static methods of the entity so that they are invoked when the entity is deleted directly from its storage class.
Issue fork private_message-3488508
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
dimilias commentedComment #4
dimilias commentedComment #5
dimilias commentedComment #6
herved commentedI tested the above scenarios, works correctly. Just a minor nit.
+1, looks like a good fix and maintains BC.
Comment #7
claudiu.cristeaNeeds an upgrade path to ensure we're also cleaning potential orphan private messages and orphan entries in pm_thread_history table
orphan == where the thread doesn't exist anymore
Comment #8
claudiu.cristeaComment #9
dimilias commentedI have added a post update hook to clean the orphaned messages.
2 notes:
1) I used the Drupal API because the private message entity is fieldable. We cannot simply remove the lines from the main table.
2) I haven't provided a test for this. I used the ddev method to setup the project, installed it, used the following script to just create messages
and just ran the deploy hook to ensure everything is removed. Cheers
Comment #10
claudiu.cristeaUpgrade path added. This looks good. It has testing coverage and I've tested manually the update path. Approved!
Comment #13
claudiu.cristeaMerged into 4.x & 3.0.x. Thank you all
Comment #14
socialnicheguru commentedMoved to it's own issue since this issue is closed: #3490816: Divison by Zero
if you have no messages this breaks your site:
$sandbox['#finished'] = $sandbox['current_id'] / $sandbox['total'];Comment #16
claudiu.cristea