Question about handling URL parameters

corbitWire1

Member
My adventure into the beautiful system of xenForo continues:

I've overriden XenForo_Route_Prefix_Threads and XenForo_ControllerPublic_Thread. Actually I am trying to modify the behavior of XenForo_ControllerPublic_Thread and I need to support one additional URL parameter named 'apage'. That's why I've overriden XenForo_Route_Prefix_Threads.

My class (which overrides XenForo_Route_Prefix_Threads) contains the following code:

PHP:
public function match($routePath, Zend_Controller_Request_Http $request, XenForo_Router $router)
{
$action = $router->resolveActionWithIntegerParam($routePath, $request, 'thread_id');
$action = $router->resolveActionAsPageNumber($action, $request);

// Handle article pages
if (preg_match('#^apage-(\d+)$#i', $action, $match))
{
$action = '';
$request->setParam('apage', $match[1]);
//die ($request->getParam('apage'));
}

//$request->setParam('apage', 1);
return $router->getRouteMatch('XenForo_ControllerPublic_Thread', $action, 'forums');
}

It should work on a URL like index.php?threads/this-is-a-test.5/apage-2. The regex code works correctly as it is almost the same code xenForo uses to handle /page-id URL patterns. If I uncomment the 'die' line, the requested apage value get's displayed. That means that the regex works and the apage param get's set correctly. The problem is that the value of apage isn't available to my controller (my controller reports a value of 0 all the time). If I set the apage parameter to a hardcoded value as I've done in the commented line, everything works like a charm. My controller fetches the apage value by using

PHP:
$apage = max(0, $this->_input->filterSingle('apage', XenForo_Input::UINT));

Why my hardcoded apage value works while the URL's one doesn't?
 
I have tested in here and dont know why too.

This is strange, because after using the method setParam with the value of $match[1], then calling getParams method return me this:

array(3) { ["_origRoutePath"]=> string(29) "threads/sdfsdfdsfs.77/apage-2" ["thread_id"]=> int(77) ["apage"]=> string(1) "2" }

But then in the Controller, i receive this 0 value too.
 
Maybe you have to use in your extended controller
Code:
 canonicalizePageNumber($page, $postsPerPage, $thread['reply_count'] + 1, 'threads', $thread)

AND

Code:
canonicalizeRequestUrl(XenForo_Link::buildPublicLink('threads', $thread, array('page' => $page)))

both functions are used by the actionIndex in the ControllerPublicThread.

I have commented this lines, and now i get the value from "apage".
 
Thanks for your help :) I noticed these functions but I didn't touched them because I can't understand why setting a hardcoded value works, while the value found in the url doesn't work. Both use $request->setParam. I'll do some experiments with these functions and reply with the results.
 
No luck so far...

I'am digging in canonicalizeRequestUrl and XenForo_Link::buildPublicLink in order to understand the way they work. If you have any suggestion please let me know!
 
To Kier/Mike (or any other developer who knows the answer :p)

I haven't solved the problem yet. I noticed that buildLink method XenForo_Route_Prefix_Threads get's called in the process of handing the url and it's parameters. I've kept match function as shown above and I've overriden buildLink as follows:

PHP:
public function buildLink($originalPrefix, $outputPrefix, $action, $extension, $data, array &$extraParams)
    {
        if ($action == 'article-page' && !empty($extraParams['articlePage']))
        {
            $articlePage = $extraParams['articlePage'];
            unset($extraParams['articlePage']);
            $extraParams['apage'] = $articlePage['pageId'];
            $action = '';
            $action = $this->getAPageNumberAsAction($action, $extraParams);
 
            return XenForo_Link::buildBasicLinkWithIntegerParam($outputPrefix, $action, $extension, $data, 'thread_id', 'title');
        }
        else
        {
            return parent::buildLink($originalPrefix, $outputPrefix, $action, $extension, $data, $extraParams);
        }
    }

Also I tried the following...

PHP:
public function buildLink($originalPrefix, $outputPrefix, $action, $extension, $data, array &$extraParams)
    {
        if ($action == 'article-page' && !empty($extraParams['articlePage']))
        {
            $articlePage = $extraParams['articlePage'];
            unset($extraParams['articlePage']);
            $extraParams['apage'] = $articlePage['pageId'];
            $action = '';
            $action = $this->getAPageNumberAsAction($action, $extraParams);
 
            return XenForo_Link::buildBasicLinkWithIntegerParam($outputPrefix, $action, $extension, $data, 'thread_id', 'title');
        }
        else if (isset($extraParams['apage']))
        {
 
            $action = '';
            $action = $this->getAPageNumberAsAction($action, $extraParams);
         
            return XenForo_Link::buildBasicLinkWithIntegerParam($outputPrefix, $action, $extension, $data, 'thread_id', 'title');
        }
        else
        {
            return parent::buildLink($originalPrefix, $outputPrefix, $action, $extension, $data, $extraParams);
        }
    }
 
    private function getAPageNumberAsAction($action, array &$params)
    {
        if (isset($params['apage']))
        {
            if (strval($params['apage']) !== XenForo_Application::$integerSentinel && $params['apage'] < 0)
            {
                unset($params['apage']);
            }
            else if (!$action)
            {
                if ($params['apage'] != XenForo_Application::$integerSentinel)
                {
                    $params['apage'] = intval($params['apage']);
                }
 
                $action = "apage-$params[apage]";
 
                unset($params['apage']);
            }
        }
 
        return $action;
    }

with no luck as you already know! apage is always 0. But if I set apage to a hardcoded value as I've shown above, everything works normally without adding this extra code in buildLink. The only way for my controller to read a non-zero value is to set it hardcoded in match function. Why is this happening? What is the proper way to handle the apage parameter?
 
Top Bottom