1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Writing to secondary table when thread is created...

Discussion in 'XenForo Development Discussions' started by digitalpoint, Nov 21, 2011.

  1. digitalpoint

    digitalpoint Well-Known Member

    So I have a table that I need to write stuff to when a new thread is created (very similar to how polls are created in a different table when needed)...

    I extended the XenForo_DataWriter_Discussion_Thread class, and added my table/fields to the _getFields() method... more or less works well... it creates a record in my custom table with the new thread_id (exactly what I want to do), but all the other fields are just set as default (blank or 0).

    The problem is I can't find a good place within the XenForo_ControllerPublic_Forum::actionAddThread() method to set my fields for my secondary table... it would need to be somewhere between the $writer object being created and the $writer->save(); method being called.

    Maybe extend the $writer->preSave() method and do it all in there?
     
  2. Fuhrmann

    Fuhrmann Well-Known Member

    I think this is the best option.
     
  3. digitalpoint

    digitalpoint Well-Known Member

    Yeah, was mucking around with it a bit... ended up throwing an error about not being able to set something after preSave() was called... apparently preSave is getting called twice for some reason (didn't trace around why that would be). But running my stuff on preSave() only if it hasn't already run (and then setting a flag that it's run afterwards) seems to do the trick.

    Still seems odd that XF is running preSave() twice, but w/e...
     
  4. ragtek

    ragtek Guest

    preSave is called twice, because save() calls also preSave...

    BUT the second time it shouldn't run, because the first run sets $dw->__preSaveCalled to true, which is checked inside of presave

    PHP:
        /**
        * Public facing handler for final verification before a save. Any verification
        * or complex defaults may be set by this.
        *
        * It is generally not advisable to override this function. If you just want to
        * add pre-save behaviors, override {@link _preSave()}.
        */
        
    public function preSave()
        {
            if (
    $this->_preSaveCalled)
            {
                return;
            }

            
    $this->_preSaveDefaults();
            if (!
    $this->_importMode)
            {
                
    $this->_preSave();

                if (!
    $this->_existingData)
                {
                    
    $this->_resolveDefaultsAndRequiredFieldsForInsert();
                }
                else
                {
                    
    $this->_checkRequiredFieldsForUpdate();
                }
            }
            else if (!
    $this->_existingData)
            {
                
    $this->_resolveDefaultsAndRequiredFieldsForInsert(false);
            }

            
    $this->_preSaveCalled true;
        }
    so if you overwrite/extend preSave, you could also check if _preSaveCalled is set and if yes, do nothing..;)
     
  5. digitalpoint

    digitalpoint Well-Known Member

    Yep... That's what I'm doing. Kind of hackish to put code that should be in a controller inside the DataWriter, but at least it gets the job done I suppose...
     
  6. digitalpoint

    digitalpoint Well-Known Member

    Now if only XenForo_DataWriter_Discussion::_preSave() wasn't a "final" method...

    Sometimes I really hate the final keyword on methods.
     
  7. Mike

    Mike XenForo Developer Staff Member

    That's what _discussionPreSave is for in this instance. :)
     
    digitalpoint likes this.
  8. digitalpoint

    digitalpoint Well-Known Member

    Oh, I guess I should have looked around a bit more. lol

    I love the XenForo code, but when I'm done with all this rewriting stuff I'm taking a vacation (been spending about 60 hours/week on XenForo stuff the last month). :)
     
    yavuz likes this.
  9. digitalpoint

    digitalpoint Well-Known Member

    It would be nice to have a better way to do this. Throwing all the stuff that should be in the controller into the datawriter is silly and really ugly. As it is, we need to check the controller and action and only extend the datawriter if we are within the correct action...

    PHP:
    if (isset($GLOBALS['fc']))
    {
        
    // Only want to do this when creating a new thread - blah
        
    if ($GLOBALS['fc']->route()->getControllerName() === 'XenForo_ControllerPublic_Forum' && $GLOBALS['fc']->route()->getAction() === 'add-thread')
        {
            if (
    $class === 'XenForo_DataWriter_Discussion_Thread')
            {
                
    $extend[] = 'DigitalPointMarketplace_DataWriter_Discussion_Thread';
            }
        }
    }
    We have to do that because what we are doing involved input from the thread creation form, which simply won't be there when the datawriter is possibly initiated for other things.

    Then within the datawriter we are needing to initiate the XenForo_Input class and do all the stuff we are actually trying to do...

    PHP:
    class DigitalPointMarketplace_DataWriter_Discussion_Thread extends XFCP_DigitalPointMarketplace_DataWriter_Discussion_Thread
    {
        public function 
    _discussionPreSave()
        {
            
    parent::_discussionPreSave();
                    
            
    $input = new XenForo_Input($GLOBALS['fc']->getRequest());
            
    $this->set('something'$input->filterSingle('input_field'XenForo_Input::UINT));
        }
    }
    It works... but omg it's quite ugly and hackish... lol
     
  10. ragtek

    ragtek Guest

  11. digitalpoint

    digitalpoint Well-Known Member

    You're crazy... creating a input class within the datawriter... using $GLOBALS, etc... makes me want to cry. :)
     
    Jeremy likes this.
  12. ragtek

    ragtek Guest

    me too, but it's nicer as my primitive solutions (because i'm overwriting the complete methods for my boards => and that's only available for 1 add-on so i had to mix several add-on codes...
    it's working and doesn't have too much overhead, but with this way it's impossible to release the add-ons:D

    my last plan was to overwrite the method and create 1 event sending the controller (to have access to input + controller helpers) + dw object as params.
    So i wouldn't need to worry about the xf upgrades.. only 1 diff change per controller necessary
     

Share This Page