Fire Event on Thread Creation?

Jaxel

Well-known member
#1
So I was looking into firing off an event every time a new thread is created; only public threads that are viewable by unregistered users.

At first I thought about firing it off at the end of ControllerPublic/Forum->actionAddThread, but then I realized that an extended listener on this action would not have access to the thread information. Without that thread information, I wouldn't be able to check if the thread was public to unregistered users or not. Then I thought about extending the PostSave of the DataWriter; and that just brought up a whole bunch of new messes.

Has anyone done anything like this? What approaches did you come up with?
 

Mike

XenForo developer
Staff member
#3
Agreed with Chris: triggering whatever action post-insert in the thread DW seems like the way to go from my perspective. What issues did you have?
 

Jaxel

Well-known member
#4
Agreed with Chris: triggering whatever action post-insert in the thread DW seems like the way to go from my perspective. What issues did you have?
Which function in the DW would you extend? _discussionPostSave?

How would I fire the event only on thread creation (not on thread update), and only if the thread is visible to unregistered? And possibly fire it after a moderated thread becomes approved?
 
Last edited:

Chris D

XenForo developer
Staff member
#5
Which function in the DW would you extend? _discussionPostSave?
Yes.

How would I fire the event only on thread creation (not on thread update), and only if the thread is visible to unregistered? And possibly fire it after a moderated thread becomes approved?
Extend the method and call its parent. You can detect these scenarios using the following methods. Mostly just an example, but some considerations there in terms of only working with a thread that is inserted as visible; you might need a different combination of stuff here:
PHP:
protected function _discussionPostSave()
{
    parent::_discussionPostSave();

    if ($this->isInsert() && $this->get('discussion_state') == 'visible')
    {
        // Do stuff when the thread is inserted as visible
    }

    if ($this->isUpdate() && $this->getExisting('discussion_state') == 'moderated' && $this->get('discussion_state') == 'visible')
    {
        // Do stuff when thread moves from 'moderated' state to 'visible'
    }
}
 

Jaxel

Well-known member
#7
Would this work?

Code:
    protected function _discussionPostSave()
    {
        $response = parent::_discussionPostSave();
        $options = XenForo_Application::get('options');

        if (!empty($options->EWRdiscord_webhook_discussion))
        {
            if ((!$this->_existingData && $this->get('discussion_state') == 'visible') ||
                ($this->isChanged('discussion_state') && $this->get('discussion_state') == 'visible'))
            {
                $this->getModelFromCache('EWRdiscord_Model_Discord')->postToWebhook(
                    $options->EWRdiscord_webhook_discussion,
                    new XenForo_Phrase('discord_x_posted_new_thread_y_z', array(
                        'user' => $this->get('username'),
                        'title' => $this->get('title'),
                        'url' => XenForo_Link::buildPublicLink('full:thread', $this->getMergedData())
                    ))
                );
            }
        }

        return $response;
    }
 

Chris D

XenForo developer
Staff member
#8
Just a few points:
  1. Use $this->isInsert() instead of trying to read _existingData directly (amounts to the same thing, but more consistent and semantically clearer).
  2. The second condition would also apply to threads which are being undeleted, which may or may not be ideal.
  3. It isn't expected that _discussionPostSave() will return anything, so there's no need to return a value (no need to assign the parent call to the $response variable and return it).
To be honest, the example I gave is probably the closest to how the condition should work, though with the two joined together:

PHP:
protected function _discussionPostSave()
{
    parent::_discussionPostSave();

    if (($this->isInsert() && $this->get('discussion_state') == 'visible'))
        || ($this->isUpdate() && $this->getExisting('discussion_state') == 'moderated' && $this->get('discussion_state') == 'visible')
    )
    {
        // Do the stuff
    }
}
 

Jaxel

Well-known member
#9
Hmm... curious... Does "PostSave" actually mean AFTER submission to the database?

For testing reasons, I put "exit;" into my extension. When doing so, even though its after "parent:", the thread wasn't created.

Code:
<?php

class EWRdiscord_DataWriter_Discussion_Thread extends XFCP_EWRdiscord_DataWriter_Discussion_Thread
{
    protected function _discussionPostSave()
    {
        parent::_discussionPostSave();
        
        if (XenForo_Visitor::getUserId() == 1)
        {
            echo "exit";
            exit;
        }
    }
}
 
Top