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

Extending a class from another add-on...

Discussion in 'XenForo Development Discussions' started by farang, Jan 14, 2016.

  1. farang

    farang Well-Known Member

    Hi there! I've got a simple question.

    Would it generally be possible to extend a class from another add-on the same way that I extend core XF classes?

    I've created a code event listener and here is the listener function

    Code:
            public static function extendTheOtherAddOn($class, array &$extend)
            {
                if ($class == 'AnotherAddOn_XenForo_Model_Thread')
                {
                    die("554646"); // well, just to debug ... 
                    //$extend[] = 'fgX_LastPostPreview_WidgetFramework_XenForo_Model_Thread';
                }
            }   
    
    My problem is that my function is never fired. (Just for debugging, I listen to event load_class without "event hint" )
     
  2. Jake B.

    Jake B. Well-Known Member

    What is the class you're trying to extend?

    EDIT: Nevermind, looks like you're trying to extend WidgetFramework_XenForo_Model_Thread which extends XenForo_Model_Thread This isn't possible since that class is l0aded using the XenForo Class Proxy. You'll want to extend XenForo_Model_Thread and adjust the execution order on your listener.
     
    farang likes this.
  3. farang

    farang Well-Known Member

    Thanks @Jake B. for your kind help. That explains it. :)

    I tried to extend that class because I wanted to add to the $threadFetchOptions array before XenForo_Model_Thread::prepareThreadFetchOptions(array $fetchOptions) runs ...

    Code:
    $threadFetchOptions['fgx_join'] = fgX_LastPostPreview_XenForo_Model_Thread::FETCH_FGX_LAST_POST_PREVIEW;
    Currently my add-on extends prepareThreadFetchOptions(array $fetchOptions) and will join a table in case
    Code:
    ($fetchOptions['fgx_join'] & self::FETCH_FGX_LAST_POST_PREVIEW)
    Hmmm.. I don't know how to solve that right now. :confused:
     
  4. Liam W

    Liam W Well-Known Member

    The XenForo_Model_Thread method will always run last, as that's the root class (ignoring the abstract XenForo_Model).

    Just make sure you extend it, and when the other classes call the parent method, yours will also be called.

    P.S You may want to remove the fetch constant, as if it is called from another class before the class proxy is instantiated, you'll get errors. Obviously, if you only ever read it from itself (or an extension of the class you're extending), it'll be fine.

    Liam
     
    farang likes this.
  5. farang

    farang Well-Known Member

    Thanks Liam.

    I think I'm a bit stuck here... I'd like to extend the code in the "best pratice" way and I try to avoid hard coding in the join.

    I paste the code below and maybe someone can come up with an idea how to do this in a reasonable good way.

    Here is how I extended ControllerPublic_Forum _getThreadFetchElements
    As you see I assign the fetch constant to $threadFetchOptions['fgx_join'] to flag that a join is needed.

    Code:
    <?php
    
    /**
    * Extending XenForo_ControllerPublic_Forum
    */
    class fgX_LastPostPreview_XenForo_ControllerPublic_Forum extends XFCP_fgX_LastPostPreview_XenForo_ControllerPublic_Forum
    {
        protected function _getThreadFetchElements(array $forum, array $displayConditions)
        {
            $parentElements = parent::_getThreadFetchElements($forum, $displayConditions);
            $threadFetchConditions = $parentElements['conditions'];
    
            $threadFetchOptions = $parentElements['options'];
    
            $threadFetchOptions['fgx_join'] = fgX_LastPostPreview_XenForo_Model_Thread::FETCH_FGX_LAST_POST_PREVIEW;
    
            return array(
                'conditions' => $threadFetchConditions,
                'options' => $threadFetchOptions
            );
        }
    }
    And here is my extension of XenForo_Model_Thread

    Code:
    <?php
    
    class fgX_LastPostPreview_XenForo_Model_Thread extends XFCP_fgX_LastPostPreview_XenForo_Model_Thread
    {
        /**
         * Extending XenForo_Model_Thread
         */
        const FETCH_FGX_LAST_POST_PREVIEW = 0x01;
    
        public function prepareThreadFetchOptions(array $fetchOptions)
        {
            $parentFetchOptions = parent::prepareThreadFetchOptions($fetchOptions);
    
            if ((!empty($fetchOptions['join']) && ($fetchOptions['join'] & self::FETCH_FIRSTPOST)) ||
            (!empty($fetchOptions['fgx_join']) && ($fetchOptions['fgx_join'] & self::FETCH_FGX_LAST_POST_PREVIEW)))
            {
                $parentFetchOptions['selectFields'] .= ', lastpost.message AS lastpost_message, lastpost.attach_count AS lastpost_attach_count';
                $parentFetchOptions['joinTables'] .=  ' LEFT JOIN xf_post AS lastpost ON
                        (lastpost.post_id = thread.last_post_id)';
            }
    
            return array(
                'selectFields' => $parentFetchOptions['selectFields'],
                'joinTables'   => $parentFetchOptions['joinTables'],
                'orderClause'  => $parentFetchOptions['orderClause']
            );
           
        }
    In the code above, the join will only occur when needed. It works well because XF Core will always run ControllerPublic_Forum _getThreadFetchElements.

    However and here's my problem ... Widget Framework doesn't call the ControllerPublic_Forum _getThreadFetchElements. I'd need to make Widget Framework to do something like:
    Code:
    $threadFetchOptions['fgx_join'] = fgX_LastPostPreview_XenForo_Model_Thread::FETCH_FGX_LAST_POST_PREVIEW;
    before prepareThreadFetchOptions() runs.

    Obviously I can not extend WidgetFramework_XenForo_Model_Thread since that class is loaded by XenForo Class Proxy. How would You guys approach this problem?

    Thank You for your kind help which I appreciate a lot.

    //farang
     

Share This Page