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.

Command icon 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

idimopoulos created an issue. See original summary.

dimilias’s picture

Assigned: dimilias » Unassigned
Status: Active » Needs review
dimilias’s picture

Issue summary: View changes
dimilias’s picture

Issue summary: View changes
herved’s picture

I tested the above scenarios, works correctly. Just a minor nit.
+1, looks like a good fix and maintains BC.

claudiu.cristea’s picture

Status: Needs review » Needs work
Issue tags: +Needs upgrade path

Needs 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

claudiu.cristea’s picture

Version: 3.0.x-dev » 4.x-dev
Issue tags: +Needs backport to 3.0.x
dimilias’s picture

Status: Needs work » Needs review

I 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

<?php

use Drupal\Component\Utility\Random;

$random = new Random();

for ($i = 0; $i < 1000; $i++) {
    $message = \Drupal::entityTypeManager()
        ->getStorage('private_message')
        ->create([
            'owner' => 0,
            'message' => $random->name(),
        ]);
    $message->save();
}

and just ran the deploy hook to ensure everything is removed. Cheers

claudiu.cristea’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs upgrade path

Upgrade path added. This looks good. It has testing coverage and I've tested manually the update path. Approved!

claudiu.cristea’s picture

Status: Reviewed & tested by the community » Fixed
Issue tags: -Needs backport to 3.0.x

Merged into 4.x & 3.0.x. Thank you all

socialnicheguru’s picture

Moved 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'];

DivisionByZeroError: Division by zero in /drupal-10.3.x/html/modules/contrib/private_message/private_message.post_update.php on line 43

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

claudiu.cristea’s picture

Version: 4.x-dev » 3.0.x-dev