• This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.
  • This forum has been archived. New threads and replies may not be made. All add-ons/resources that are active should be migrated to the Resource Manager. See this thread for more information.

Backward Compatability Breaks!

Jaxel

Well-known member
#2
I dont quite understand what has changed... or how to fix the new bugs...

It looks the same to me, just without any array keys.
 

Jaxel

Well-known member
#4
Well it seems to be giving me errors...
PHP:
$visitorID = XenForo_Visitor::getUserId();

$conditions = array(
	'deleted' => false,
	'moderated' => false,
);

$fetchOptions = array(
	'join' => XenForo_Model_Thread::FETCH_FORUM | XenForo_Model_Thread::FETCH_USER,
	'readUserId' => $visitorID,
	'watchUserId' => $visitorID,
	'postCountUserId' => $visitorID,
	'order' => 'last_post_date',
	'orderDirection' => 'desc',
	'limit' => $params['option']['recentthreads_limit'],
);

$threads = $this->getModelFromCache('XenForo_Model_Thread')->getThreads($conditions, $fetchOptions);

foreach ($threads AS &$thread)
{
	$thread['content_type'] = 'thread';
	$thread['content_id'] = $thread['thread_id'];
}
$threads = $this->getModelFromCache('XenForo_Model_Search')->getViewableSearchResults($threads);
On the last line, I get the following error:
An exception occurred: Undefined offset: 0 in /library/XenForo/Model/Search.php on line 235
  1. XenForo_Application::handlePhpError() in XenForo/Model/Search.php at line 235
  2. XenForo_Model_Search->groupSearchResultsByType() in XenForo/Model/Search.php at line 295
  3. XenForo_Model_Search->getViewableSearchResults() in EWRporta/Block/RecentThreads.php at line 31
  4. EWRporta_Block_RecentThreads->getBypass() in EWRporta/ViewPublic/Portal.php at line 87
  5. EWRporta_ViewPublic_Portal->getModuleParams() in EWRporta/ViewPublic/Portal.php at line 23
  6. EWRporta_ViewPublic_Portal->renderHtml() in XenForo/ViewRenderer/Abstract.php at line 222
  7. XenForo_ViewRenderer_Abstract->renderViewObject() in XenForo/ViewRenderer/HtmlPublic.php at line 67
  8. XenForo_ViewRenderer_HtmlPublic->renderView() in XenForo/FrontController.php at line 533
  9. XenForo_FrontController->renderView() in XenForo/FrontController.php at line 156
  10. XenForo_FrontController->run() in /index.php at line 17
 

Mike

XenForo developer
Staff member
#5
Some of the PHPDocs are out of date, oops.

But write into the array via:

$thread[XenForo_Model_Search::CONTENT_TYPE]
$thread[XenForo_Model_Search::CONTENT_ID]

That said, using the search stuff for this really isn't necessary - you can get the permissions with the threads and filter out the results without doing all the search lookups.
 

Mike

XenForo developer
Staff member
#7
Have a look at XenForo_Search_DataHandler_Thread, particularly getDataForResults and canViewResult.

Really the general concept is get all the thread (make sure you include permissionCombinationId), unserialize the permissions in the list, then loop through the list and unset any records that can't be viewed.

The code in that function is general purpose, so $viewingUser is roughly the visitor. You'll need to explicitly pass in a permissionCombinationId, but you don't need to pass $viewingUser to the permission check if you're checking against a visitor (you do need to pass their permissions though).
 

Jaxel

Well-known member
#8
I still cant get this to work... I tried this:
PHP:
$conditions = array(
	'deleted' => false,
	'moderated' => false,
);

$fetchOptions = array(
	'order' => 'last_post_date',
	'orderDirection' => 'desc',
	'limit' => $options['recentthreads_limit'],
);

$threads = $this->getModelFromCache('XenForo_Model_Thread')->getThreads($conditions, $fetchOptions);
$threadIDs = array_keys($threads);

$visitor = XenForo_Visitor::getInstance();
$handler = XenForo_Search_DataHandler_Abstract::create('thread');

$threads = $handler->getDataForResults($threadIDs, $visitor, $threadIDs);
 
R

ragtek

Guest
#9
PHP:
/**
     * get the newest threads
     */
    protected function getThreads(){
        $nodeModel = $this->getModelFromCache('XenForo_Model_Node');
        $threadModel = $this->getModelFromCache('XenForo_Model_Thread');

        $viewableNodeList = $nodeModel->getViewableNodeList();      // check if this returns pages too, if yes, we need an other way

        $condition = array(
            'forum_ids' => array_keys($viewableNodeList), // had to overwrite the model to provide this feature
            'moderated' => false,
            'deleted' => false
        );

        $fetchOptions = array(
            'order' => 'last_post_date',
            'orderDirection' => 'desc',
            'join' => XenForo_Model_Thread::FETCH_FIRSTPOST,
            'limit' => XenForo_Application::get('options')->ragtek_feed_maxThreads
        );

        return $threadModel->getThreads($condition,$fetchOptions);
    }
that's what i'm using in http://xenforo.com/community/threads/global-rss-xml-feed.7856/
 

Jaxel

Well-known member
#10
Okay... I got it using this:
PHP:
$conditions = array(
	'deleted' => false,
	'moderated' => false,
);

$fetchOptions = array(
	'order' => 'last_post_date',
	'orderDirection' => 'desc',
	'limit' => $options['recentthreads_limit'],
);

$threads = $this->getModelFromCache('XenForo_Model_Thread')->getThreads($conditions, $fetchOptions);

$threadIDs = array_keys($threads);
$visitor = XenForo_Visitor::getInstance()->toArray();
$handler = XenForo_Search_DataHandler_Abstract::create('XenForo_Search_DataHandler_Thread');

$threads = $handler->getDataForResults($threadIDs, $visitor, $threadIDs);

foreach ($threads AS &$thread)
{
	$thread = $this->getModelFromCache('XenForo_Model_Thread')->prepareThread($thread, $thread);
	$thread['canInlineMod'] = false;
	$thread['showForumLink'] = true;
}

return $threads;
 

Mike

XenForo developer
Staff member
#14
Jaxel, this is derived from the first set of code you provided. Your latest code does some different stuff (in terms of what it fetches and preparation), and I'm not sure if it's intentional.

I also haven't tested it at all - just typed it up in a text editor, so there might be parse errors. :)

PHP:
$visitor = XenForo_Visitor::getInstance();
$visitorID = $visitor['user_id'];

$conditions = array(
    'deleted' => false,
    'moderated' => false,
);

$fetchOptions = array(
    'join' => XenForo_Model_Thread::FETCH_FORUM | XenForo_Model_Thread::FETCH_USER,
    'permissionCombinationId' => $visitor['permission_combination_id'],
    'readUserId' => $visitorID,
    'watchUserId' => $visitorID,
    'postCountUserId' => $visitorID,
    'order' => 'last_post_date',
    'orderDirection' => 'desc',
    'limit' => $params['option']['recentthreads_limit'],
);

$threadModel = $this->getModelFromCache('XenForo_Model_Thread');

$threads = $threadModel->getThreads($conditions, $fetchOptions);
$threads = $threadModel->unserializePermissionsInList($threads, 'node_permission_cache');

foreach ($threads AS $threadId => $thread)
{
    if (!$threadModel->canViewThreadAndContainer($thread, $thread, $null, $thread['permissions']))
    {
        unset($threads[$threadId]);
    }
}
 
R

ragtek

Guest
#15
Jaxel, this is derived from the first set of code you provided. Your latest code does some different stuff (in terms of what it fetches and preparation), and I'm not sure if it's intentional.

I also haven't tested it at all - just typed it up in a text editor, so there might be parse errors. :)

PHP:
$visitor = XenForo_Visitor::getInstance();
$visitorID = $visitor['user_id'];

$conditions = array(
    'deleted' => false,
    'moderated' => false,
);

$fetchOptions = array(
    'join' => XenForo_Model_Thread::FETCH_FORUM | XenForo_Model_Thread::FETCH_USER,
    'permissionCombinationId' => $visitor['permission_combination_id'],
    'readUserId' => $visitorID,
    'watchUserId' => $visitorID,
    'postCountUserId' => $visitorID,
    'order' => 'last_post_date',
    'orderDirection' => 'desc',
    'limit' => $params['option']['recentthreads_limit'],
);

$threadModel = $this->getModelFromCache('XenForo_Model_Thread');

$threads = $threadModel->getThreads($conditions, $fetchOptions);
$threads = $threadModel->unserializePermissionsInList($threads, 'node_permission_cache');

foreach ($threads AS $threadId => $thread)
{
    if (!$threadModel->canViewThreadAndContainer($thread, $thread, $null, $thread['permissions']))
    {
        unset($threads[$threadId]);
    }
}
With this way it's not possible to get n Elements back.
If you limit 20 and 5 from them are not viable, the user will get only 15 back!
That's why we need an official way in the thread model, to use a list of forumids . (just like in http://xenforo.com/community/threads/backward-compatability-breaks.13290/#post-174050 )
 

Kier

XenForo Developer
Staff member
#16
With this way it's not possible to get n Elements back.
If you limit 20 and 5 from them are not viable, the user will get only 15 back!
That's why we need an official way in the thread model, to use a list of forumids . (just like in http://xenforo.com/community/threads/backward-compatability-breaks.13290/#post-174050 )
All you can do is select more than you need and hope that when you filter them, you have n remaining. Any more than that, you can chop off.

(This is the principle behind pretty much every search engine that has to manage diverse data)
 
R

ragtek

Guest
#17
All you can do is select more than you need and hope that when you filter them, you have n remaining. Any more than that, you can chop off.

(This is the principle behind pretty much every search engine that has to manage diverse data)
I have sleepless nights because of this because i don't understand it:D

Is there really no other way?
Isn't this extrem overhead?

Is there no easier way to get the last 50 new threads?
The readable forums are known because of $nodemodell->getViewableNodeList.

if i select ALL threads which are not moderated and not deleted and thread.node_id is in ( 1,2,4,6) shouldn't all results be viewable?
Why should i check them once again with the canViewThreadAndContainer method
 

Kier

XenForo Developer
Staff member
#18
The readable forums are known because of $nodemodell->getViewableNodeList.
There are far more variables involved than just that. What about soft-deleted threads, or threads in the moderation queue, or threads subject to other viewing restrictions?
 
R

ragtek

Guest
#19
There are far more variables involved than just that. What about soft-deleted threads, or threads in the moderation queue,
I thought the condition part is handling this?

$condition = array(
'moderated' => false,
'deleted' => false
);

Hm, i'll check this tommorow, before i go on your nerves^^
 
#20
There are far more variables involved than just that. What about soft-deleted threads, or threads in the moderation queue, or threads subject to other viewing restrictions?
Is this a better way, as the code ragtek posted?

PHP:
 protected function _getThreads()
    {
        $visitor = XenForo_Visitor::getInstance();
        $visitorID = $visitor['user_id'];

        $conditions = array(
            'deleted' => false,
            'moderated' => false,
        );

        $fetchOptions = array(
            'join' => XenForo_Model_Thread::FETCH_FORUM |
                      XenForo_Model_Thread::FETCH_USER |
                      XenForo_Model_Thread::FETCH_FIRSTPOST,
            'permissionCombinationId' => $visitor['permission_combination_id'],
            'readUserId' => $visitorID,
            'watchUserId' => $visitorID,
            'postCountUserId' => $visitorID,
            'order' => 'last_post_date',
            'orderDirection' => 'desc',
            'limit' => XenForo_Application::get('options')->ragtek_feed_maxThreads * 2, // get more as we need because of the cut off, we'll remove them later
        );

        /** @var $threadModel XenForo_Model_Thread */
        $threadModel = $this->getModelFromCache('XenForo_Model_Thread');

        $threads = $threadModel->getThreads($conditions, $fetchOptions);
        $threads = $threadModel->unserializePermissionsInList($threads, 'node_permission_cache');

        foreach ($threads AS $threadId => $thread)
        {
            if (!$threadModel->canViewThreadAndContainer($thread, $thread, $null, $thread['permissions'])) {
                unset($threads[$threadId]);
            }
        }
        // make sure that we only return max. threads
        $threads = array_slice($threads, 0,XenForo_Application::get('options')->ragtek_feed_maxThreads);
        return $threads;
    }