XF 2.0 How do I update the $parent when extending a function?

AndyB

Well-known member
Hello,

I'm creating a new XF2 add-on called Remove moderated notices. It allows registered members to see their moderated threads in the forum view.

I have extended the function actionForum like this.

PHP:
<?php

namespace Andy\RemoveModeratedNotices\XF\Pub\Controller;

use XF\Mvc\ParameterBag;

class Forum extends XFCP_Forum
{
    public function actionForum(ParameterBag $params)
    {
        // get parent
        $parent = parent::actionForum($params);
        
        $visitor = \XF::visitor();
        $userId = $visitor['user_id'];
        
        $forum = $this->assertViewableForum($params->node_id ?: $params->node_name, $this->getForumViewExtraWith());

        if ($this->responseType == 'rss')
        {
            return $this->getForumRss($forum);
        }

        $page = $this->filterPage($params->page);
        $perPage = $this->options()->discussionsPerPage;

        $this->assertCanonicalUrl($this->buildLink('forums', $forum, ['page' => $page]));

        $threadRepo = $this->getThreadRepo();

        $threadList = $threadRepo->findThreadsForForumView($forum, [
            'allowOwnPending' => $this->hasContentPendingApproval()
        ]);

        $filters = $this->getForumFilterInput($forum);
        $this->applyForumFilters($forum, $threadList, $filters);

        if ($page == 1)
        {
            $stickyThreadList = clone $threadList;

            /** @var \XF\Entity\Thread[] $stickyThreads */
            $stickyThreads = $stickyThreadList->where('sticky', 1)->fetch();
        }
        else
        {
            $stickyThreads = null;
        }

        $threadList->where('sticky', 0)
            ->limitByPage($page, $perPage);
        
        $threads = $threadList->fetch();

        foreach ($threads AS $thread)
        {
            if ($thread['discussion_state'] == 'moderated')
            {
                // only show thread to thread author
                if ($thread['user_id'] != $userId)
                {
                    $threads->offsetUnset($thread['thread_id']);
                }
            }
        }

        // return parent
        return $parent;
    }
}

Inside the foreach I offsetUnset the thread I don't want to show, but I'm not understanding how I can update the $parent before I return it.

Thank you.
 
What I need to happen is the $thread object gets passed back so the viewParams is updated with the new $threads object, that way when the foum_view template is displayed it will not show moderated threads to anyone besides the author.
 
If I hack the original function the code I add works perfect.

src/XF/Pub/Controller/Fourm.php

PHP:
    public function actionForum(ParameterBag $params)
    {
        $forum = $this->assertViewableForum($params->node_id ?: $params->node_name, $this->getForumViewExtraWith());

        if ($this->responseType == 'rss')
        {
            return $this->getForumRss($forum);
        }

        $page = $this->filterPage($params->page);
        $perPage = $this->options()->discussionsPerPage;

        $this->assertCanonicalUrl($this->buildLink('forums', $forum, ['page' => $page]));

        $threadRepo = $this->getThreadRepo();

        $threadList = $threadRepo->findThreadsForForumView($forum, [
            'allowOwnPending' => $this->hasContentPendingApproval()
        ]);

        $filters = $this->getForumFilterInput($forum);
        $this->applyForumFilters($forum, $threadList, $filters);

        if ($page == 1)
        {
            $stickyThreadList = clone $threadList;

            /** @var \XF\Entity\Thread[] $stickyThreads */
            $stickyThreads = $stickyThreadList->where('sticky', 1)->fetch();
        }
        else
        {
            $stickyThreads = null;
        }

        $threadList->where('sticky', 0)
            ->limitByPage($page, $perPage);

        /** @var \XF\Entity\Thread[] $threads */
        $threads = $threadList->fetch();
        $totalThreads = $threadList->total();

        $this->assertValidPage($page, $perPage, $totalThreads, 'forums', $forum->Node);

        $nodeRepo = $this->getNodeRepo();
        $nodes = $nodeRepo->getNodeList($forum->Node);
        $nodeTree = count($nodes) ? $nodeRepo->createNodeTree($nodes, $forum->node_id) : null;
        $nodeExtras = $nodeTree ? $nodeRepo->getNodeListExtras($nodeTree) : null;

        $canInlineMod = false;
        if ($stickyThreads)
        {
            foreach ($stickyThreads AS $thread)
            {
                if ($thread->canUseInlineModeration())
                {
                    $canInlineMod = true;
                    break;
                }
            }
        }
        foreach ($threads AS $thread)
        {
            if ($thread->canUseInlineModeration())
            {
                $canInlineMod = true;
                break;
            }
        }
        
        // start hack
        $visitor = \XF::visitor();
        $userId = $visitor['user_id'];
        
        foreach ($threads AS $thread)
        {
            if ($thread['discussion_state'] == 'moderated')
            {
                // only show thread to thread author
                if ($thread['user_id'] != $userId)
                {
                    $threads->offsetUnset($thread['thread_id']);
                }
            }
        }
        // end hack

        // if the forum is unread and perhaps it shouldn't be, see if we can mark it as read
        if (\XF::visitor()->user_id
            && $page == 1
            && !$filters
            && $forum->isUnread()
        )
        {
            $hasNew = false;
            foreach ($threads AS $thread)
            {
                if ($thread->isUnread() && !$thread->isIgnored())
                {
                    $hasNew = true;
                    break;
                }
            }

            if (!$hasNew)
            {
                $this->getForumRepo()->markForumReadIfPossible($forum);
            }
        }

        if (!empty($filters['starter_id']))
        {
            $starterFilter = $this->em()->find('XF:User', $filters['starter_id']);
        }
        else
        {
            $starterFilter = null;
        }

        $viewParams = [
            'forum' => $forum,

            'canInlineMod' => $canInlineMod,

            'nodeTree' => $nodeTree,
            'nodeExtras' => $nodeExtras,

            'stickyThreads' => $stickyThreads,
            'threads' => $threads,

            'page' => $page,
            'perPage' => $perPage,
            'total' => $totalThreads,

            'filters' => $filters,
            'starterFilter' => $starterFilter,

            'sortInfo' => $this->getEffectiveSortInfo($forum, $filters),

            'pendingApproval' => $this->filter('pending_approval', 'bool')
        ];
        return $this->view('XF:Forum\View', 'forum_view', $viewParams);
    }
 
That doesn't work perfect, it's going to break any add-on that runs before yours. This change is nearly identical to what you did here: https://xenforo.com/community/threads/how-can-i-extend-actionforum-properly.136172/

The only difference is that since this is xf2 passing the parameter back into the parent is slightly different (if you type $parent->param in any halfway decent IDE it'll give you several options and should be pretty obvious which you'll use)
 
  • Like
Reactions: Bob
That doesn't work perfect, it's going to break any add-on that runs before yours.

Sorry I meant the code works perfect, I wasn't advocating to hack code for live sites, it was just a test.

The only difference is that since this is xf2 passing the parameter back into the parent is slightly different (if you type $parent->param in any halfway decent IDE it'll give you several options and should be pretty obvious which you'll use)

Dreamweaver at this time is not providing me with that sort of information, but I've been using it for 15 years and at this time I don't want to use another IDE due to the learning curve. I'm hoping Dreamweaver will add the functionality soon so I don't have to learn another IDE.

So what is the code I need to use in order pass the parameter back to $parent.

Thank you.
 
When I add the following to my PHP code:

PHP:
\XF::dump($parent);

The first part I see this:

1509041782597.webp

At the bottom I see this:

1509041945629.webp
 
\XF::dump won't show you available methods, but a good IDE will ;)

Don't remember the exact name of the function, but if your IDE doesn't tell you and you don't want to use one that does you'll have to look at the class directly
 
Take a look at viewClass on the dump you made, and drill down from there to the class it extends, and so on
 
Thank you, snog. That tip worked perfect.

PHP:
$parent->setParam('threads', $threads);


Looks like I need to get PHP Storm. :)
 
Top Bottom