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

XF 1.5 How can I extend actionForum properly?

AndyB

Well-known member
#1
I created an addon called StickyAllPages. This add-on puts sticky threads on all pages, not just page 1 as the default XenForo does.

One way which works is to overwrite the entire function like this:

PHP:
<?php

class Andy_StickyAllPages_ControllerPublic_Forum extends XFCP_Andy_StickyAllPages_ControllerPublic_Forum
{	
	public function actionForum()
	{
		$forumId = $this->_input->filterSingle('node_id', XenForo_Input::UINT);
		$forumName = $this->_input->filterSingle('node_name', XenForo_Input::STRING);

		$ftpHelper = $this->getHelper('ForumThreadPost');
		$forum = $this->getHelper('ForumThreadPost')->assertForumValidAndViewable(
			$forumId ? $forumId : $forumName,
			$this->_getForumFetchOptions()
		);
		$forumId = $forum['node_id'];

		$visitor = XenForo_Visitor::getInstance();
		$threadModel = $this->_getThreadModel();
		$forumModel = $this->_getForumModel();

		$page = max(1, $this->_input->filterSingle('page', XenForo_Input::UINT));
		$threadsPerPage = XenForo_Application::get('options')->discussionsPerPage;

		$this->canonicalizeRequestUrl(
			XenForo_Link::buildPublicLink('forums', $forum, array('page' => $page))
		);

		list($defaultOrder, $defaultOrderDirection) = $this->_getDefaultThreadSort($forum);

		$order = $this->_input->filterSingle('order', XenForo_Input::STRING, array('default' => $defaultOrder));
		$orderDirection = $this->_input->filterSingle('direction', XenForo_Input::STRING, array('default' => $defaultOrderDirection));

		$displayConditions = $this->_getDisplayConditions($forum);

		$noDateLimit = $this->_input->filterSingle('no_date_limit', XenForo_Input::BOOLEAN);
		$isDateLimited = ($forum['list_date_limit_days'] && $order == 'last_post_date' && !$noDateLimit);
		if ($isDateLimited)
		{
			$displayConditions['last_post_date'] = array('>=', XenForo_Application::$time - 86400 * $forum['list_date_limit_days']);
		}

		$fetchElements = $this->_getThreadFetchElements($forum, $displayConditions);
		$threadFetchConditions = $fetchElements['conditions'];
		$threadFetchOptions = $fetchElements['options'] + array(
			'perPage' => $threadsPerPage,
			'page' => $page,
			'order' => $order,
			'orderDirection' => $orderDirection
		);
		unset($fetchElements);

		$totalThreads = $threadModel->countThreadsInForum($forumId, $threadFetchConditions);

		$this->canonicalizePageNumber($page, $threadsPerPage, $totalThreads, 'forums', $forum);

		$threads = $threadModel->getThreadsInForum($forumId, $threadFetchConditions, $threadFetchOptions);

		if ($page >= 1)
		{
			$stickyThreadFetchOptions = $threadFetchOptions;
			unset($stickyThreadFetchOptions['perPage'], $stickyThreadFetchOptions['page']);

			$stickyThreadConditions = $threadFetchConditions;
			unset($stickyThreadConditions['last_post_date']);

			$stickyThreads = $threadModel->getStickyThreadsInForum($forumId, $stickyThreadConditions, $stickyThreadFetchOptions);
		}
		else
		{
			$stickyThreads = array();
		}

		// prepare all threads for the thread list
		$inlineModOptions = array();
		$permissions = $visitor->getNodePermissions($forumId);

		foreach ($threads AS &$thread)
		{
			$threadModOptions = $threadModel->addInlineModOptionToThread($thread, $forum, $permissions);
			$inlineModOptions += $threadModOptions;

			$thread = $threadModel->prepareThread($thread, $forum, $permissions);
		}
		foreach ($stickyThreads AS &$thread)
		{
			$threadModOptions = $threadModel->addInlineModOptionToThread($thread, $forum, $permissions);
			$inlineModOptions += $threadModOptions;

			$thread = $threadModel->prepareThread($thread, $forum, $permissions);
		}
		unset($thread);

		// if we've read everything on the first page of a normal sort order, probably need to mark as read
		if ($visitor['user_id'] && $page == 1 && !$displayConditions
			&& $order == 'last_post_date' && $orderDirection == 'desc'
			&& $forum['forum_read_date'] < $forum['last_post_date']
		)
		{
			$hasNew = false;
			foreach ($threads AS $thread)
			{
				if ($thread['isNew'] && !$thread['isIgnored'])
				{
					$hasNew = true;
					break;
				}
			}

			if (!$hasNew)
			{
				// everything read, but forum not marked as read. Let's check.
				$this->_getForumModel()->markForumReadIfNeeded($forum);
			}
		}

		// get the ordering params set for the header links
		$orderParams = array();
		foreach ($this->_getThreadSortFields($forum) AS $field)
		{
			$orderParams[$field] = $displayConditions;
			$orderParams[$field]['order'] = ($field != $defaultOrder ? $field : false);
			if ($order == $field)
			{
				$orderParams[$field]['direction'] = ($orderDirection == 'desc' ? 'asc' : 'desc');
			}
		}

		$pageNavParams = $displayConditions;
		$pageNavParams['order'] = ($order != $defaultOrder ? $order : false);
		$pageNavParams['direction'] = ($orderDirection != $defaultOrderDirection ? $orderDirection : false);
		if ($noDateLimit)
		{
			$pageNavParams['no_date_limit'] = 1;
		}
		unset($pageNavParams['last_post_date']);

		$threadEndOffset = ($page - 1) * $threadsPerPage + count($threads);
		$showDateLimitDisabler = ($isDateLimited && $threadEndOffset >= $totalThreads);

		$viewParams = array(
			'nodeList' => $this->_getNodeModel()->getNodeDataForListDisplay($forum, 0),
			'forum' => $forum,
			'nodeBreadCrumbs' => $ftpHelper->getNodeBreadCrumbs($forum, false),

			'canPostThread' => $forumModel->canPostThreadInForum($forum),
			'canSearch' => $visitor->canSearch(),
			'canWatchForum' => $forumModel->canWatchForum($forum),

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

			'ignoredNames' => $this->_getIgnoredContentUserNames($threads) + $this->_getIgnoredContentUserNames($stickyThreads),

			'order' => $order,
			'orderDirection' => $orderDirection,
			'orderParams' => $orderParams,
			'displayConditions' => $displayConditions,

			'pageNavParams' => $pageNavParams,
			'page' => $page,
			'threadStartOffset' => ($page - 1) * $threadsPerPage + 1,
			'threadEndOffset' => $threadEndOffset,
			'threadsPerPage' => $threadsPerPage,
			'totalThreads' => $totalThreads,

			'showPostedNotice' => $this->_input->filterSingle('posted', XenForo_Input::UINT),
			'showDateLimitDisabler' => $showDateLimitDisabler
		);

		return $this->responseView('XenForo_ViewPublic_Forum_View', 'forum_view', $viewParams);
	}
}
But I know that is not the proper way to do it, I need to use the following lines of code at the top and bottom of the function.

PHP:
		$parent = parent::actionForum();

		return $parent;
The problem is if I do that the sticky thread only appears on page 1. What am I doing wrong?

Thank you.
 

AndyB

Well-known member
#2
In overwriting the function actionForum(), the only change I made was to change:

PHP:
if ($page == 1)
to this:
PHP:
if ($page >= 1)
 

arms

Active member
#3
PHP:
$parent = parent::actionForum(); // Extend the default function.

// Your code

$parent->params['stickyThreads '] =  $stickyThreads ;
       
     return $parent; //
 

AndyB

Well-known member
#4
Thank you, arms. That worked perfectly. I tried adding the

$parent->params['stickyThreads'] = $stickyThreads;

code before seeking help, but assumed I didn't need to include the entire function and that resulted in errors. Once i included all the code less the responseView it worked great.
 

AndyB

Well-known member
#5
Here's the working code:

PHP:
<?php

class Andy_StickyAllPages_ControllerPublic_Forum extends XFCP_Andy_StickyAllPages_ControllerPublic_Forum
{   
    public function actionForum()
    {
        // get parent
        $parent = parent::actionForum();
       
        $forumId = $this->_input->filterSingle('node_id', XenForo_Input::UINT);
        $forumName = $this->_input->filterSingle('node_name', XenForo_Input::STRING);

        $ftpHelper = $this->getHelper('ForumThreadPost');
        $forum = $this->getHelper('ForumThreadPost')->assertForumValidAndViewable(
            $forumId ? $forumId : $forumName,
            $this->_getForumFetchOptions()
        );
        $forumId = $forum['node_id'];

        $visitor = XenForo_Visitor::getInstance();
        $threadModel = $this->_getThreadModel();
        $forumModel = $this->_getForumModel();

        $page = max(1, $this->_input->filterSingle('page', XenForo_Input::UINT));
        $threadsPerPage = XenForo_Application::get('options')->discussionsPerPage;

        $this->canonicalizeRequestUrl(
            XenForo_Link::buildPublicLink('forums', $forum, array('page' => $page))
        );

        list($defaultOrder, $defaultOrderDirection) = $this->_getDefaultThreadSort($forum);

        $order = $this->_input->filterSingle('order', XenForo_Input::STRING, array('default' => $defaultOrder));
        $orderDirection = $this->_input->filterSingle('direction', XenForo_Input::STRING, array('default' => $defaultOrderDirection));

        $displayConditions = $this->_getDisplayConditions($forum);

        $noDateLimit = $this->_input->filterSingle('no_date_limit', XenForo_Input::BOOLEAN);
        $isDateLimited = ($forum['list_date_limit_days'] && $order == 'last_post_date' && !$noDateLimit);
        if ($isDateLimited)
        {
            $displayConditions['last_post_date'] = array('>=', XenForo_Application::$time - 86400 * $forum['list_date_limit_days']);
        }

        $fetchElements = $this->_getThreadFetchElements($forum, $displayConditions);
        $threadFetchConditions = $fetchElements['conditions'];
        $threadFetchOptions = $fetchElements['options'] + array(
            'perPage' => $threadsPerPage,
            'page' => $page,
            'order' => $order,
            'orderDirection' => $orderDirection
        );
        unset($fetchElements);

        $totalThreads = $threadModel->countThreadsInForum($forumId, $threadFetchConditions);

        $this->canonicalizePageNumber($page, $threadsPerPage, $totalThreads, 'forums', $forum);

        $threads = $threadModel->getThreadsInForum($forumId, $threadFetchConditions, $threadFetchOptions);

        // change this to any number greater than or equal 1
        if ($page >= 1)
        {
            $stickyThreadFetchOptions = $threadFetchOptions;
            unset($stickyThreadFetchOptions['perPage'], $stickyThreadFetchOptions['page']);

            $stickyThreadConditions = $threadFetchConditions;
            unset($stickyThreadConditions['last_post_date']);

            $stickyThreads = $threadModel->getStickyThreadsInForum($forumId, $stickyThreadConditions, $stickyThreadFetchOptions);
        }
        else
        {
            $stickyThreads = array();
        }

        // prepare all threads for the thread list
        $inlineModOptions = array();
        $permissions = $visitor->getNodePermissions($forumId);

        foreach ($threads AS &$thread)
        {
            $threadModOptions = $threadModel->addInlineModOptionToThread($thread, $forum, $permissions);
            $inlineModOptions += $threadModOptions;

            $thread = $threadModel->prepareThread($thread, $forum, $permissions);
        }
        foreach ($stickyThreads AS &$thread)
        {
            $threadModOptions = $threadModel->addInlineModOptionToThread($thread, $forum, $permissions);
            $inlineModOptions += $threadModOptions;

            $thread = $threadModel->prepareThread($thread, $forum, $permissions);
        }
        unset($thread);

        // if we've read everything on the first page of a normal sort order, probably need to mark as read
        if ($visitor['user_id'] && $page == 1 && !$displayConditions
            && $order == 'last_post_date' && $orderDirection == 'desc'
            && $forum['forum_read_date'] < $forum['last_post_date']
        )
        {
            $hasNew = false;
            foreach ($threads AS $thread)
            {
                if ($thread['isNew'] && !$thread['isIgnored'])
                {
                    $hasNew = true;
                    break;
                }
            }

            if (!$hasNew)
            {
                // everything read, but forum not marked as read. Let's check.
                $this->_getForumModel()->markForumReadIfNeeded($forum);
            }
        }

        // get the ordering params set for the header links
        $orderParams = array();
        foreach ($this->_getThreadSortFields($forum) AS $field)
        {
            $orderParams[$field] = $displayConditions;
            $orderParams[$field]['order'] = ($field != $defaultOrder ? $field : false);
            if ($order == $field)
            {
                $orderParams[$field]['direction'] = ($orderDirection == 'desc' ? 'asc' : 'desc');
            }
        }

        $pageNavParams = $displayConditions;
        $pageNavParams['order'] = ($order != $defaultOrder ? $order : false);
        $pageNavParams['direction'] = ($orderDirection != $defaultOrderDirection ? $orderDirection : false);
        if ($noDateLimit)
        {
            $pageNavParams['no_date_limit'] = 1;
        }
        unset($pageNavParams['last_post_date']);

        $threadEndOffset = ($page - 1) * $threadsPerPage + count($threads);
        $showDateLimitDisabler = ($isDateLimited && $threadEndOffset >= $totalThreads);

        $viewParams = array(
            'nodeList' => $this->_getNodeModel()->getNodeDataForListDisplay($forum, 0),
            'forum' => $forum,
            'nodeBreadCrumbs' => $ftpHelper->getNodeBreadCrumbs($forum, false),

            'canPostThread' => $forumModel->canPostThreadInForum($forum),
            'canSearch' => $visitor->canSearch(),
            'canWatchForum' => $forumModel->canWatchForum($forum),

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

            'ignoredNames' => $this->_getIgnoredContentUserNames($threads) + $this->_getIgnoredContentUserNames($stickyThreads),

            'order' => $order,
            'orderDirection' => $orderDirection,
            'orderParams' => $orderParams,
            'displayConditions' => $displayConditions,

            'pageNavParams' => $pageNavParams,
            'page' => $page,
            'threadStartOffset' => ($page - 1) * $threadsPerPage + 1,
            'threadEndOffset' => $threadEndOffset,
            'threadsPerPage' => $threadsPerPage,
            'totalThreads' => $totalThreads,

            'showPostedNotice' => $this->_input->filterSingle('posted', XenForo_Input::UINT),
            'showDateLimitDisabler' => $showDateLimitDisabler
        );
       
        // update parent
        $parent->params['stickyThreads'] = $stickyThreads;
      
        // return parent
         return $parent;
    }
}
 

Jake B.

Well-known member
#6
Definitely don't ever do that. You're causing all of the code for that entire controller action to be run twice. All you need to do is something like this:

PHP:
<?php
class Andy_StickyAllPages_ControllerPublic_Forum extends XFCP_Andy_StickyAllPages_ControllerPublic_Forum
{
    public function actionForum()    {
        $parent = parent::actionForum();

        if ($parent->params['page'] > 1) {
            $fetchElements = $this->_getThreadFetchElements($forum, $displayConditions);
            $threadFetchConditions = $fetchElements['conditions'];
            $threadFetchOptions = $fetchElements['options'] + array(
                'perPage' => $threadsPerPage,
                'page' => $page,
                'order' => $order,
                'orderDirection' => $orderDirection
            );
            $stickyThreadFetchOptions = $threadFetchOptions;
            unset($stickyThreadFetchOptions['perPage'], $stickyThreadFetchOptions['page']);

            $stickyThreadConditions = $threadFetchConditions;
            unset($stickyThreadConditions['last_post_date']);

            $stickyThreads = $threadModel->getStickyThreadsInForum($forumId, $stickyThreadConditions, $stickyThreadFetchOptions);

            $parent->params['stickyThreads'] = $stickyThreads
        }

        return $parent;
    }
}
Will probably need to get a few additional parameters from $parent as well.
 

AndyB

Well-known member
#8
Thank you, Jake. Great suggestion. I have updated the code to this and it works perfect.

PHP:
<?php

class Andy_StickyAllPages_ControllerPublic_Forum extends XFCP_Andy_StickyAllPages_ControllerPublic_Forum
{
    public function actionForum()    
    {
        // get parent
        $parent = parent::actionForum();

        // if page is greater than 1
        if ($parent->params['page'] > 1) 
        {
            $forumId = $this->_input->filterSingle('node_id', XenForo_Input::UINT);
            $forumName = $this->_input->filterSingle('node_name', XenForo_Input::STRING);

            $ftpHelper = $this->getHelper('ForumThreadPost');
            $forum = $this->getHelper('ForumThreadPost')->assertForumValidAndViewable(
                $forumId ? $forumId : $forumName,
                $this->_getForumFetchOptions()
            );
            $forumId = $forum['node_id'];

            $visitor = XenForo_Visitor::getInstance();
            $threadModel = $this->_getThreadModel();
            $forumModel = $this->_getForumModel();

            $page = max(1, $this->_input->filterSingle('page', XenForo_Input::UINT));
            $threadsPerPage = XenForo_Application::get('options')->discussionsPerPage;

            $this->canonicalizeRequestUrl(
                XenForo_Link::buildPublicLink('forums', $forum, array('page' => $page))
            );

            list($defaultOrder, $defaultOrderDirection) = $this->_getDefaultThreadSort($forum);

            $order = $this->_input->filterSingle('order', XenForo_Input::STRING, array('default' => $defaultOrder));
            $orderDirection = $this->_input->filterSingle('direction', XenForo_Input::STRING, array('default' => $defaultOrderDirection));

            $displayConditions = $this->_getDisplayConditions($forum);

            $noDateLimit = $this->_input->filterSingle('no_date_limit', XenForo_Input::BOOLEAN);
            $isDateLimited = ($forum['list_date_limit_days'] && $order == 'last_post_date' && !$noDateLimit);
            if ($isDateLimited)
            {
                $displayConditions['last_post_date'] = array('>=', XenForo_Application::$time - 86400 * $forum['list_date_limit_days']);
            }

            $fetchElements = $this->_getThreadFetchElements($forum, $displayConditions);
            $threadFetchConditions = $fetchElements['conditions'];
            $threadFetchOptions = $fetchElements['options'] + array(
                'perPage' => $threadsPerPage,
                'page' => $page,
                'order' => $order,
                'orderDirection' => $orderDirection
            );
            unset($fetchElements);

            $totalThreads = $threadModel->countThreadsInForum($forumId, $threadFetchConditions);

            $this->canonicalizePageNumber($page, $threadsPerPage, $totalThreads, 'forums', $forum);

            $threads = $threadModel->getThreadsInForum($forumId, $threadFetchConditions, $threadFetchOptions);

            // change this to any number greater than or equal 1
            if ($page >= 1)
            {
                $stickyThreadFetchOptions = $threadFetchOptions;
                unset($stickyThreadFetchOptions['perPage'], $stickyThreadFetchOptions['page']);

                $stickyThreadConditions = $threadFetchConditions;
                unset($stickyThreadConditions['last_post_date']);

                $stickyThreads = $threadModel->getStickyThreadsInForum($forumId, $stickyThreadConditions, $stickyThreadFetchOptions);
            }
            else
            {
                $stickyThreads = array();
            }

            // prepare all threads for the thread list
            $inlineModOptions = array();
            $permissions = $visitor->getNodePermissions($forumId);

            foreach ($threads AS &$thread)
            {
                $threadModOptions = $threadModel->addInlineModOptionToThread($thread, $forum, $permissions);
                $inlineModOptions += $threadModOptions;

                $thread = $threadModel->prepareThread($thread, $forum, $permissions);
            }
            foreach ($stickyThreads AS &$thread)
            {
                $threadModOptions = $threadModel->addInlineModOptionToThread($thread, $forum, $permissions);
                $inlineModOptions += $threadModOptions;

                $thread = $threadModel->prepareThread($thread, $forum, $permissions);
            }
            unset($thread);

            // if we've read everything on the first page of a normal sort order, probably need to mark as read
            if ($visitor['user_id'] && $page == 1 && !$displayConditions
                && $order == 'last_post_date' && $orderDirection == 'desc'
                && $forum['forum_read_date'] < $forum['last_post_date']
            )
            {
                $hasNew = false;
                foreach ($threads AS $thread)
                {
                    if ($thread['isNew'] && !$thread['isIgnored'])
                    {
                        $hasNew = true;
                        break;
                    }
                }

                if (!$hasNew)
                {
                    // everything read, but forum not marked as read. Let's check.
                    $this->_getForumModel()->markForumReadIfNeeded($forum);
                }
            }

            // get the ordering params set for the header links
            $orderParams = array();
            foreach ($this->_getThreadSortFields($forum) AS $field)
            {
                $orderParams[$field] = $displayConditions;
                $orderParams[$field]['order'] = ($field != $defaultOrder ? $field : false);
                if ($order == $field)
                {
                    $orderParams[$field]['direction'] = ($orderDirection == 'desc' ? 'asc' : 'desc');
                }
            }

            $pageNavParams = $displayConditions;
            $pageNavParams['order'] = ($order != $defaultOrder ? $order : false);
            $pageNavParams['direction'] = ($orderDirection != $defaultOrderDirection ? $orderDirection : false);
            if ($noDateLimit)
            {
                $pageNavParams['no_date_limit'] = 1;
            }
            unset($pageNavParams['last_post_date']);

            $threadEndOffset = ($page - 1) * $threadsPerPage + count($threads);
            $showDateLimitDisabler = ($isDateLimited && $threadEndOffset >= $totalThreads);

            $viewParams = array(
                'nodeList' => $this->_getNodeModel()->getNodeDataForListDisplay($forum, 0),
                'forum' => $forum,
                'nodeBreadCrumbs' => $ftpHelper->getNodeBreadCrumbs($forum, false),

                'canPostThread' => $forumModel->canPostThreadInForum($forum),
                'canSearch' => $visitor->canSearch(),
                'canWatchForum' => $forumModel->canWatchForum($forum),

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

                'ignoredNames' => $this->_getIgnoredContentUserNames($threads) + $this->_getIgnoredContentUserNames($stickyThreads),

                'order' => $order,
                'orderDirection' => $orderDirection,
                'orderParams' => $orderParams,
                'displayConditions' => $displayConditions,

                'pageNavParams' => $pageNavParams,
                'page' => $page,
                'threadStartOffset' => ($page - 1) * $threadsPerPage + 1,
                'threadEndOffset' => $threadEndOffset,
                'threadsPerPage' => $threadsPerPage,
                'totalThreads' => $totalThreads,

                'showPostedNotice' => $this->_input->filterSingle('posted', XenForo_Input::UINT),
                'showDateLimitDisabler' => $showDateLimitDisabler
            );

            // update parent
            $parent->params['stickyThreads'] = $stickyThreads;
        }

        // return parent
        return $parent;
    }
}
 

arms

Active member
#10
I recommend you use something which you can use XDebug, at least you can step through and understand whats being passed. Try Visual Studio Code (Its free). It would help greatly.

1508894179437.png

Again, you are repeating everything, it's not needed, you only want to update StickyThreads.

see


Definitely don't ever do that. You're causing all of the code for that entire controller action to be run twice. All you need to do is something like this:

PHP:
<?php
class Andy_StickyAllPages_ControllerPublic_Forum extends XFCP_Andy_StickyAllPages_ControllerPublic_Forum
{
    public function actionForum()    {
        $parent = parent::actionForum();

        if ($parent->params['page'] > 1) {
            $fetchElements = $this->_getThreadFetchElements($forum, $displayConditions);
            $threadFetchConditions = $fetchElements['conditions'];
            $threadFetchOptions = $fetchElements['options'] + array(
                'perPage' => $threadsPerPage,
                'page' => $page,
                'order' => $order,
                'orderDirection' => $orderDirection
            );
            $stickyThreadFetchOptions = $threadFetchOptions;
            unset($stickyThreadFetchOptions['perPage'], $stickyThreadFetchOptions['page']);

            $stickyThreadConditions = $threadFetchConditions;
            unset($stickyThreadConditions['last_post_date']);

            $stickyThreads = $threadModel->getStickyThreadsInForum($forumId, $stickyThreadConditions, $stickyThreadFetchOptions);

            $parent->params['stickyThreads'] = $stickyThreads
        }

        return $parent;
    }
}
Will probably need to get a few additional parameters from $parent as well.
 
Last edited:

Jake B.

Well-known member
#11
Can't do that, seams the entire code needs to be there, otherwise I get errors.
Then you'll need to look into what the errors are. What I gave you will get you 90% of the way there, just need to define a couple of variables (one of which can be pulled from $parent->params. You definitely don't want to load in the entire function again as it'll just kill performance of someone's site and likely break pretty much any add-on that extends that same controller action that happens to load before yours does.
 

AndyB

Well-known member
#12
Again, you are repeating everything, it's not needed, you only want to update StickyThreads.
Thank you, arms and Jake. Indeed I was able to remove some additional unneeded code.

This is what I have now.

PHP:
<?php

class Andy_StickyAllPages_ControllerPublic_Forum extends XFCP_Andy_StickyAllPages_ControllerPublic_Forum
{
    public function actionForum()    
    {
        // get parent
        $parent = parent::actionForum();

        // if page is greater than 1
        if ($parent->params['page'] > 1) 
        {
            $forumId = $this->_input->filterSingle('node_id', XenForo_Input::UINT);
            $forumName = $this->_input->filterSingle('node_name', XenForo_Input::STRING);

            $ftpHelper = $this->getHelper('ForumThreadPost');
            $forum = $this->getHelper('ForumThreadPost')->assertForumValidAndViewable(
                $forumId ? $forumId : $forumName,
                $this->_getForumFetchOptions()
            );
            $forumId = $forum['node_id'];

            $visitor = XenForo_Visitor::getInstance();
            $threadModel = $this->_getThreadModel();
            $forumModel = $this->_getForumModel();

            $page = max(1, $this->_input->filterSingle('page', XenForo_Input::UINT));
            $threadsPerPage = XenForo_Application::get('options')->discussionsPerPage;

            $this->canonicalizeRequestUrl(
                XenForo_Link::buildPublicLink('forums', $forum, array('page' => $page))
            );

            list($defaultOrder, $defaultOrderDirection) = $this->_getDefaultThreadSort($forum);

            $order = $this->_input->filterSingle('order', XenForo_Input::STRING, array('default' => $defaultOrder));
            $orderDirection = $this->_input->filterSingle('direction', XenForo_Input::STRING, array('default' => $defaultOrderDirection));

            $displayConditions = $this->_getDisplayConditions($forum);

            $noDateLimit = $this->_input->filterSingle('no_date_limit', XenForo_Input::BOOLEAN);
            $isDateLimited = ($forum['list_date_limit_days'] && $order == 'last_post_date' && !$noDateLimit);
            if ($isDateLimited)
            {
                $displayConditions['last_post_date'] = array('>=', XenForo_Application::$time - 86400 * $forum['list_date_limit_days']);
            }

            $fetchElements = $this->_getThreadFetchElements($forum, $displayConditions);
            $threadFetchConditions = $fetchElements['conditions'];
            $threadFetchOptions = $fetchElements['options'] + array(
                'perPage' => $threadsPerPage,
                'page' => $page,
                'order' => $order,
                'orderDirection' => $orderDirection
            );
            unset($fetchElements);

            $totalThreads = $threadModel->countThreadsInForum($forumId, $threadFetchConditions);

            $this->canonicalizePageNumber($page, $threadsPerPage, $totalThreads, 'forums', $forum);

            $threads = $threadModel->getThreadsInForum($forumId, $threadFetchConditions, $threadFetchOptions);

            // get stickyThreads
            $stickyThreadFetchOptions = $threadFetchOptions;
            unset($stickyThreadFetchOptions['perPage'], $stickyThreadFetchOptions['page']);

            $stickyThreadConditions = $threadFetchConditions;
            unset($stickyThreadConditions['last_post_date']);

            $stickyThreads = $threadModel->getStickyThreadsInForum($forumId, $stickyThreadConditions, $stickyThreadFetchOptions);

            // prepare all threads for the thread list
            $inlineModOptions = array();
            $permissions = $visitor->getNodePermissions($forumId);

            foreach ($threads AS &$thread)
            {
                $threadModOptions = $threadModel->addInlineModOptionToThread($thread, $forum, $permissions);
                $inlineModOptions += $threadModOptions;

                $thread = $threadModel->prepareThread($thread, $forum, $permissions);
            }
            foreach ($stickyThreads AS &$thread)
            {
                $threadModOptions = $threadModel->addInlineModOptionToThread($thread, $forum, $permissions);
                $inlineModOptions += $threadModOptions;

                $thread = $threadModel->prepareThread($thread, $forum, $permissions);
            }
            unset($thread);

            // update parent
            $parent->params['stickyThreads'] = $stickyThreads;
        }

        // return parent
        return $parent;
    }
}
 
Last edited:

Jake B.

Well-known member
#13
Thank you, arms and Jake. Indeed I was able to remove some additional unneeded code.

This is what I have now.

PHP:
<?php

class Andy_StickyAllPages_ControllerPublic_Forum extends XFCP_Andy_StickyAllPages_ControllerPublic_Forum
{
    public function actionForum()   
    {
        // get parent
        $parent = parent::actionForum();

        // if page is greater than 1
        if ($parent->params['page'] > 1)
        {
            $forumId = $this->_input->filterSingle('node_id', XenForo_Input::UINT);
            $forumName = $this->_input->filterSingle('node_name', XenForo_Input::STRING);

            $ftpHelper = $this->getHelper('ForumThreadPost');
            $forum = $this->getHelper('ForumThreadPost')->assertForumValidAndViewable(
                $forumId ? $forumId : $forumName,
                $this->_getForumFetchOptions()
            );
            $forumId = $forum['node_id'];

            $visitor = XenForo_Visitor::getInstance();
            $threadModel = $this->_getThreadModel();
            $forumModel = $this->_getForumModel();

            $page = max(1, $this->_input->filterSingle('page', XenForo_Input::UINT));
            $threadsPerPage = XenForo_Application::get('options')->discussionsPerPage;

            $this->canonicalizeRequestUrl(
                XenForo_Link::buildPublicLink('forums', $forum, array('page' => $page))
            );

            list($defaultOrder, $defaultOrderDirection) = $this->_getDefaultThreadSort($forum);

            $order = $this->_input->filterSingle('order', XenForo_Input::STRING, array('default' => $defaultOrder));
            $orderDirection = $this->_input->filterSingle('direction', XenForo_Input::STRING, array('default' => $defaultOrderDirection));

            $displayConditions = $this->_getDisplayConditions($forum);

            $noDateLimit = $this->_input->filterSingle('no_date_limit', XenForo_Input::BOOLEAN);
            $isDateLimited = ($forum['list_date_limit_days'] && $order == 'last_post_date' && !$noDateLimit);
            if ($isDateLimited)
            {
                $displayConditions['last_post_date'] = array('>=', XenForo_Application::$time - 86400 * $forum['list_date_limit_days']);
            }

            $fetchElements = $this->_getThreadFetchElements($forum, $displayConditions);
            $threadFetchConditions = $fetchElements['conditions'];
            $threadFetchOptions = $fetchElements['options'] + array(
                'perPage' => $threadsPerPage,
                'page' => $page,
                'order' => $order,
                'orderDirection' => $orderDirection
            );
            unset($fetchElements);

            $totalThreads = $threadModel->countThreadsInForum($forumId, $threadFetchConditions);

            $this->canonicalizePageNumber($page, $threadsPerPage, $totalThreads, 'forums', $forum);

            $threads = $threadModel->getThreadsInForum($forumId, $threadFetchConditions, $threadFetchOptions);

            // get stickyThreads
            $stickyThreadFetchOptions = $threadFetchOptions;
            unset($stickyThreadFetchOptions['perPage'], $stickyThreadFetchOptions['page']);

            $stickyThreadConditions = $threadFetchConditions;
            unset($stickyThreadConditions['last_post_date']);

            $stickyThreads = $threadModel->getStickyThreadsInForum($forumId, $stickyThreadConditions, $stickyThreadFetchOptions);

            // prepare all threads for the thread list
            $inlineModOptions = array();
            $permissions = $visitor->getNodePermissions($forumId);

            foreach ($threads AS &$thread)
            {
                $threadModOptions = $threadModel->addInlineModOptionToThread($thread, $forum, $permissions);
                $inlineModOptions += $threadModOptions;

                $thread = $threadModel->prepareThread($thread, $forum, $permissions);
            }
            foreach ($stickyThreads AS &$thread)
            {
                $threadModOptions = $threadModel->addInlineModOptionToThread($thread, $forum, $permissions);
                $inlineModOptions += $threadModOptions;

                $thread = $threadModel->prepareThread($thread, $forum, $permissions);
            }
            unset($thread);

            // set viewParams
            $viewParams = array();

            // update parent
            $parent->params['stickyThreads'] = $stickyThreads;
        }

        // return parent
        return $parent;
    }
}
90% of that is still unneeded. You literally just need to take the exact code I gave you and define $forum (which can be loaded from $parent and doesn't need to be queried again) and $displayConditions
 

AndyB

Well-known member
#14
90% of that is still unneeded. You literally just need to take the exact code I gave you and define $forum (which can be loaded from $parent and doesn't need to be queried again) and $displayConditions
I tried several things, but not able to figure out how to eliminate any other code.
 

Chris D

XenForo developer
Staff member
#15
The other guys are correct.

You’re just running code that’s already been run.

If what people have asked you to try does not work then let them help you by telling them why/what doesn’t work including error messages etc.
 

arms

Active member
#16
Errors that you get?

90% of that is still unneeded. You literally just need to take the exact code I gave you and define $forum (which can be loaded from $parent and doesn't need to be queried again) and $displayConditions
EG:
Undefined variable: forum $forum= $parent->params['forum'];
 

AndyB

Well-known member
#17
Thanks everyone, I really appreciate this help.

So using the code in post #12 if I remove the following portion of the code:
PHP:
            foreach ($threads AS &$thread)
            {
                $threadModOptions = $threadModel->addInlineModOptionToThread($thread, $forum, $permissions);
                $inlineModOptions += $threadModOptions;

                $thread = $threadModel->prepareThread($thread, $forum, $permissions);
            }
            foreach ($stickyThreads AS &$thread)
            {
                $threadModOptions = $threadModel->addInlineModOptionToThread($thread, $forum, $permissions);
                $inlineModOptions += $threadModOptions;

                $thread = $threadModel->prepareThread($thread, $forum, $permissions);
            }
            unset($thread);
I get the following error message if I try to view any page besides the first page:
Code:
An exception occurred: Argument 1 passed to XenForo_Template_Helper_Core::helperUserNameHtml() must be of the type array, null given, called in /home/southbay/public_html/forums1515a/library/XenForo/Template/Helper/Core.php on line 853 in /home/southbay/public_html/forums1515a/library/XenForo/Template/Helper/Core.php on line 1671

[LIST=1]
[*]XenForo_Template_Helper_Core::helperUserNameHtml() in XenForo/Template/Helper/Core.php at line 853
[*]XenForo_Template_Helper_Core::callHelper() in XenForo/Template/Abstract.php(265) : eval()'d code at line 743
[*]eval() in XenForo/Template/Abstract.php at line 265
[*]XenForo_Template_Abstract->_renderInternal() in XenForo/Template/Abstract.php at line 191
[*]XenForo_Template_Abstract->render() in XenForo/Template/Public.php at line 110
[*]XenForo_Template_Public->render() in XenForo/ViewRenderer/HtmlPublic.php at line 124
[*]XenForo_ViewRenderer_HtmlPublic->renderContainer() in XenForo/FrontController.php at line 639
[*]XenForo_FrontController->renderView() in XenForo/FrontController.php at line 158
[*]XenForo_FrontController->run() in /home/southbay/public_html/forums1515a/index.php at line 13
[/LIST]
The server error log:
Code:
TypeError: Argument 1 passed to XenForo_Template_Helper_Core::helperUserNameHtml() must be of the type array, null given, called in /home/southbay/public_html/forums1515a/library/XenForo/Template/Helper/Core.php on line 853 - library/XenForo/Template/Helper/Core.php:1671
Generated By: Andy, A moment ago
Code:
#0 /home/southbay/public_html/forums1515a/library/XenForo/Template/Helper/Core.php(853): XenForo_Template_Helper_Core::helperUserNameHtml(NULL, '', false, Array)
#1 /home/southbay/public_html/forums1515a/library/XenForo/Template/Abstract.php(266) : eval()'d code(743): XenForo_Template_Helper_Core::callHelper('usernamehtml', Array)
#2 /home/southbay/public_html/forums1515a/library/XenForo/Template/Abstract.php(266): eval()
#3 /home/southbay/public_html/forums1515a/library/XenForo/Template/Abstract.php(192): XenForo_Template_Abstract->_renderInternal('$__output = '';...', Array)
#4 /home/southbay/public_html/forums1515a/library/XenForo/Template/Public.php(110): XenForo_Template_Abstract->render()
#5 /home/southbay/public_html/forums1515a/library/XenForo/ViewRenderer/HtmlPublic.php(124): XenForo_Template_Public->render()
#6 /home/southbay/public_html/forums1515a/library/XenForo/FrontController.php(639): XenForo_ViewRenderer_HtmlPublic->renderContainer(Object(XenForo_Template_Public), Array)
#7 /home/southbay/public_html/forums1515a/library/XenForo/FrontController.php(158): XenForo_FrontController->renderView(Object(XenForo_ControllerResponse_View), Object(XenForo_ViewRenderer_HtmlPublic), Array)
#8 /home/southbay/public_html/forums1515a/index.php(13): XenForo_FrontController->run()
#9 {main}
Here's the XenForo code it errors on line 853:

1508940590392.png
 
Last edited:

Jake B.

Well-known member
#18
Thanks everyone, I really appreciate this help.

So using the code in post #12 if I remove the following portion of the code:

PHP:
            foreach ($threads AS &$thread)
            {
                $threadModOptions = $threadModel->addInlineModOptionToThread($thread, $forum, $permissions);
                $inlineModOptions += $threadModOptions;

                $thread = $threadModel->prepareThread($thread, $forum, $permissions);
            }
            foreach ($stickyThreads AS &$thread)
            {
                $threadModOptions = $threadModel->addInlineModOptionToThread($thread, $forum, $permissions);
                $inlineModOptions += $threadModOptions;

                $thread = $threadModel->prepareThread($thread, $forum, $permissions);
            }
            unset($thread);
I get the following error message if I try to view any page besides the first page:

Code:
An exception occurred: Argument 1 passed to XenForo_Template_Helper_Core::helperUserNameHtml() must be of the type array, null given, called in /home/southbay/public_html/forums1515a/library/XenForo/Template/Helper/Core.php on line 853 in /home/southbay/public_html/forums1515a/library/XenForo/Template/Helper/Core.php on line 1671

[LIST=1]
[*]XenForo_Template_Helper_Core::helperUserNameHtml() in XenForo/Template/Helper/Core.php at line 853
[*]XenForo_Template_Helper_Core::callHelper() in XenForo/Template/Abstract.php(265) : eval()'d code at line 743
[*]eval() in XenForo/Template/Abstract.php at line 265
[*]XenForo_Template_Abstract->_renderInternal() in XenForo/Template/Abstract.php at line 191
[*]XenForo_Template_Abstract->render() in XenForo/Template/Public.php at line 110
[*]XenForo_Template_Public->render() in XenForo/ViewRenderer/HtmlPublic.php at line 124
[*]XenForo_ViewRenderer_HtmlPublic->renderContainer() in XenForo/FrontController.php at line 639
[*]XenForo_FrontController->renderView() in XenForo/FrontController.php at line 158
[*]XenForo_FrontController->run() in /home/southbay/public_html/forums1515a/index.php at line 13
[/LIST]
Well, you don't want to remove the foreach($stickyThreads AS &$thread) portion, but you'll want to remove significantly more than just the threads loop. I'd suggest starting out what I gave you and build on that rather than starting out with the entire action and removing small chunks
 

AndyB

Well-known member
#19
I'm making a little progress. :)

PHP:
<?php

class Andy_StickyAllPages_ControllerPublic_Forum extends XFCP_Andy_StickyAllPages_ControllerPublic_Forum
{
    public function actionForum()    
    {
        // get parent
        $parent = parent::actionForum();

        // if page is greater than 1
        if ($parent->params['page'] > 1) 
        {    
            // get forum
            $forum = $parent->params['forum'];

            // get forumId
            $forumId = $forum['node_id'];

            $visitor = XenForo_Visitor::getInstance();
            $threadModel = $this->_getThreadModel();

            $page = max(1, $this->_input->filterSingle('page', XenForo_Input::UINT));
            $threadsPerPage = XenForo_Application::get('options')->discussionsPerPage;
            
            // get order
            $order = $forum['default_sort_order'];
            
            // get orderDirection
            $orderDirection = $forum['default_sort_direction'];
            
            $displayConditions = $this->_getDisplayConditions($forum);

            $noDateLimit = $this->_input->filterSingle('no_date_limit', XenForo_Input::BOOLEAN);
            $isDateLimited = ($forum['list_date_limit_days'] && $order == 'last_post_date' && !$noDateLimit);
            if ($isDateLimited)
            {
                $displayConditions['last_post_date'] = array('>=', XenForo_Application::$time - 86400 * $forum['list_date_limit_days']);
            }

            $fetchElements = $this->_getThreadFetchElements($forum, $displayConditions);
            $threadFetchConditions = $fetchElements['conditions'];
            $threadFetchOptions = $fetchElements['options'] + array(
                'perPage' => $threadsPerPage,
                'page' => $page,
                'order' => $order,
                'orderDirection' => $orderDirection
            );
            unset($fetchElements);

            $totalThreads = $threadModel->countThreadsInForum($forumId, $threadFetchConditions);

            $this->canonicalizePageNumber($page, $threadsPerPage, $totalThreads, 'forums', $forum);

            // get threads
            $threads = $parent->params['threads'];
            
            // get stickyThreads
            $stickyThreadFetchOptions = $threadFetchOptions;
            unset($stickyThreadFetchOptions['perPage'], $stickyThreadFetchOptions['page']);

            $stickyThreadConditions = $threadFetchConditions;
            unset($stickyThreadConditions['last_post_date']);

            $stickyThreads = $threadModel->getStickyThreadsInForum($forumId, $stickyThreadConditions, $stickyThreadFetchOptions);

            // prepare all threads for the thread list
            $inlineModOptions = array();
            $permissions = $visitor->getNodePermissions($forumId);

            foreach ($threads AS &$thread)
            {
                $threadModOptions = $threadModel->addInlineModOptionToThread($thread, $forum, $permissions);
                $inlineModOptions += $threadModOptions;

                $thread = $threadModel->prepareThread($thread, $forum, $permissions);
            }
            foreach ($stickyThreads AS &$thread)
            {
                $threadModOptions = $threadModel->addInlineModOptionToThread($thread, $forum, $permissions);
                $inlineModOptions += $threadModOptions;

                $thread = $threadModel->prepareThread($thread, $forum, $permissions);
            }
            unset($thread);

            // update parent
            $parent->params['stickyThreads'] = $stickyThreads;
        }

        // return parent
        return $parent;
    }
}
 
Last edited: