Replacing Hard Delete / Adding a New Delete Option

Basically in my forum, moderators have the 'View Deleted Posts' permission, which obviously allows them to see soft-deleted messages.

Essentially I want to be able to make a system that either replaces hard-delete or supplements it (since I don't like the idea of not being able to get the data back), adding a new 'Admin-delete' option. This would co-exist alongside the existing soft-delete functionality, and would perform identically, except that it has a separate permission, which means I can exclude moderators from being able to see those set deleted threads.

What is the feasibility of this. I don't mind making an addon as long as someone can point me in a general direction(e.g. specific PHP files) (although I can understand this could be complex).

Thanks,
 
  • Like
Reactions: Mai
As a workaround you could just create a forum they can't see and move threads in there. In the event you want to restore, just undo the delete. You could use multi-moderation or macros add-on to make this one click.
 
As a workaround you could just create a forum they can't see and move threads in there. In the event you want to restore, just undo the delete. You could use multi-moderation or macros add-on to make this one click.
That could work temporarily, but it doesn't seem seamless enough.
 
If I understood correctly, you want to never hard delete posts and have only your admins be able to view posts they have soft deleted?
If so, you could remove the permission to hard delete posts from your administrators and then prior to displaying the thread check to see if a deleted post was actually deleted by an admin.
If deleted by an admin then add a flag to that post which you check for in the template and thus only display the deleted post placeholder to admins and no one else.
The downside of this is that you need to fetch the deleting user for every soft deleted post in order to check whether they are admins.

If you want to hide only some of the posts that are soft deleted by your admins then that would require more work.
 
If I understood correctly, you want to never hard delete posts and have only your admins be able to view posts they have soft deleted?
If so, you could remove the permission to hard delete posts from your administrators and then prior to displaying the thread check to see if a deleted post was actually deleted by an admin.
If deleted by an admin then add a flag to that post which you check for in the template and thus only display the deleted post placeholder to admins and no one else.
The downside of this is that you need to fetch the deleting user for every soft deleted post in order to check whether they are admins.

If you want to hide only some of the posts that are soft deleted by your admins then that would require more work.
Hmm, interesting idea. Since I want to do the second bit I could potentially add a checkbox which then would connect to a database with post ids or something along those lines. If a post matches an id in the db then it won't display for those without the permission.
 
One possibility would be to add a column to the post table to act as a flag.
Extend function actionDelete() to insert the flag whenever your checkbox is ticked and then check for that flag in the thread_view template.
 
One possibility would be to add a column to the post table to act as a flag.
Extend function actionDelete() to insert the flag whenever your checkbox is ticked and then check for that flag in the thread_view template.
Would you be able to clarify where that particular function is located, and how I should start sorting it (sorry about this, I'm relatively new to making xf addons).
 
I'm going to assume that you already know how to do certain things such as creating a small add-on or adding HTML code. If this is not the case just let me know.

You'll need to add a column to the xf_post table called "fake_delete"
Then ensure the datawriter knows about it.

In MySql:
Code:
ALTER TABLE xf_post
ADD fake_delete TINYINT UNSIGNED NOT NULL DEFAULT 0

In PHP extend DataWriter/DiscussionMessage/Post.php:
PHP:
protected function _getFields()
{
   $fields = parent::_getFields();
   $fields['xf_post']['fake_delete'] = array('type' => self::TYPE_BOOLEAN, 'default' => 0);
 
   return $fields;
}

Add your checkbox to template helper_deletion_type_unit or post_delete ensuring only Admins can select it.

Extend function actionDelete() in ControllerPublic/Post.php
PHP:
public function actionDelete()
{
    $response = parent::actionDelete();
   
    if (!empty($response) && $response instanceof XenForo_ControllerResponse_Redirect)
    {
        $hardDelete = $this->_input->filterSingle('hard_delete', XenForo_Input::UINT);
        $deleteType = ($hardDelete ? 'hard' : 'soft');
       
        if ($deleteType == 'soft' && $this->_input->filterSingle('fake_hard_delete', XenForo_Input::UINT)) // you might also want to check that the user is an admin
        {
            $postId = $this->_input->filterSingle('post_id', XenForo_Input::UINT);
           
            $dw = XenForo_DataWriter::create('XenForo_DataWriter_DiscussionMessage_Post');
            $dw->setExistingData($postId);
            $dw->set('fake_delete', 1);
            $dw->save();
        }
    }
   
    return $response;
}

Modify template thread_view:
Replace
HTML:
<xen:foreach loop="$posts" value="$post">
    <xen:if is="{$post.message_state} == 'deleted'">
        <xen:include template="post_deleted_placeholder" />
    <xen:else />
        <xen:include template="post" />
    </xen:if>
</xen:foreach>

With
HTML:
<xen:foreach loop="$posts" value="$post">
    <xen:if is="{$post.message_state} == 'deleted'">
        <xen:if is="!{$post.fake_delete} OR {$visitor.is_admin}">
            <xen:include template="post_deleted_placeholder" />
        </xen:if>
    <xen:else />
        <xen:include template="post" />
    </xen:if>
</xen:foreach>

Now only administrators should be able to view placeholders for soft deleted posts that had the checkbox selected.
 
Probably my non-existant PHP skills but I can't seem to get it working quite right:
Class NextDelete_ControllerPublic_Post:
PHP:
<?php
class NextDelete_ControllerPublic_Post extends XenForo_ControllerPublic_Post {
  public function actionDelete()
{
    $response = parent::actionDelete();

    if (!empty($response) && $response instanceof XenForo_ControllerResponse_Redirect)
    {
        $hardDelete = $this->_input->filterSingle('hard_delete', XenForo_Input::UINT);
        $deleteType = ($hardDelete ? 'hard' : 'soft');

        if ($deleteType == 'soft' && $this->_input->filterSingle('fake_hard_delete', XenForo_Input::UINT)) // you might also want to check that the user is an admin
        {
            $postId = $this->_input->filterSingle('post_id', XenForo_Input::UINT);

            $dw = XenForo_DataWriter::create('XenForo_DataWriter_DiscussionMessage_Post');
            $dw->setExistingData($postId);
            $dw->set('fake_delete', 1);
            $dw->save();
        }
    }

    return $response;
}
}
Class NextDelete_DataWriter_DiscussionMessage_Post
PHP:
<?php

class NextDelete_DataWriter_DiscussionMessage_Post extends XenForo_DataWriter_DiscussionMessage_Post
{
    
    protected function _getFields()
{
   $fields = parent::_getFields();
   $fields['xf_post']['fake_delete'] = array('type' => self::TYPE_BOOLEAN, 'default' => 0);
 
   return $fields;
}
}
Class NextDelete_Listener_LoadClassController
PHP:
<?php

class NextDelete_Listener_LoadClassController
{
        public static function loadClassListener($class, &$extend)
        {

                if ($class == 'XenForo_ControllerPublic_Post')
                {
                        $extend[] = 'NextDelete_ControllerPublic_Post';
                }

        }

}
and finally class NextDelete_Listener_LoadClassDatawriter:
PHP:
<?php

class NextDelete_Listener_LoadClassDatawriter
{
        public static function loadClassListener($class, &$extend)
        {

                if ($class == 'XenForo_DataWriter_DiscussionMessage_Post')
                {
                        $extend[] = 'NextDelete_DataWriter_DiscussionMessage_Post';
                }

        }

}
upload_2017-6-13_16-34-4.webp
(the DataWriter one is the same)

If you need the template I can send them through, but they should be ok.

These questions must be getting annoying :p, but I'll like to thank you again for helping me out.
 
  • Like
Reactions: Mai
I'm working with an older version of XF (waiting for 2.0) so things might have changed but your extended file should have XFCP_ in it:
class NextDelete_DataWriter_DiscussionMessage_Post extends XFCP_NextDelete_DataWriter_DiscussionMessage_Post
class NextDelete_ControllerPublic_Post extends XFCP_NextDelete_ControllerPublic_Post

I assume you created the column on the xf_post table.
I see I've used both 'fake_hard_delete' and 'fake_delete' in my example. Probably best to use just one so as not to get confused when fetching the value.

You could also have the two listener load functions in one file to make for easier reading (all in one place).

Let me know if it still does not work and if so I'll attempt to create the add-on myself to see where I went wrong.
 
Getting a strange error:
Code:
An exception occurred: Cannot load class using XFCP. Load the class using the correct loader first. in /var/www/html/library/XenForo/Autoloader.php on line 108

XenForo_Autoloader->autoload()
spl_autoload_call() in NextDelete/ControllerPublic/NextDelete.php at line 2
include() in XenForo/Autoloader.php at line 119
XenForo_Autoloader->autoload() in XenForo/Application.php at line 1052
XenForo_Application::autoload() in XenForo/Application.php at line 529
XenForo_Application::resolveDynamicClass() in XenForo/FrontController.php at line 460
XenForo_FrontController->_getValidatedController() in XenForo/FrontController.php at line 343
XenForo_FrontController->dispatch() in XenForo/FrontController.php at line 134
XenForo_FrontController->run() in /var/www/html/index.php at line 13

I've tried Googling and troubleshooting myself, but nothing seems to quite fit what the error seems to be.
 
I'll create the add-on and see what is going on. Perhaps extending classes has changed since my version of the software.
Besides you will also need to remove the flag in the xf_table whenever a post is un-deleted.
 
I've created this add-on and it seems to work for me on XF 1.4.7
It works when you delete a single post but not inline as passing on the checkbox value there is a little more complicated.
Un-deleting in inline mode will revert the post table flag.

I've attached the add-on here so you may take a look and adjust it if needed for the latest version of XF.
I hope this helps.
 

Attachments

  • Like
Reactions: HWS
Top Bottom