944 lines
29 KiB
PHP
944 lines
29 KiB
PHP
<?php
|
|
/**
|
|
* <pre>
|
|
* Invision Power Services
|
|
* IP.Board v3.2.3
|
|
* Basic Forum Search
|
|
* Last Updated: $Date: 2011-10-04 16:35:02 -0400 (Tue, 04 Oct 2011) $
|
|
* </pre>
|
|
*
|
|
* @author $Author: bfarber $
|
|
* @copyright © 2001 - 2009 Invision Power Services, Inc.
|
|
* @license This is NULLED!
|
|
* @package IP.Board
|
|
* @subpackage Forums
|
|
* @link http://hatynka.in
|
|
* @version $Rev: 9580 $
|
|
*/
|
|
|
|
if ( ! defined( 'IN_IPB' ) )
|
|
{
|
|
print "<h1>Incorrect access</h1>You cannot access this file directly. If you have recently upgraded, make sure you upgraded all the relevant files.";
|
|
exit();
|
|
}
|
|
|
|
class search_engine_forums extends search_engine
|
|
{
|
|
/**
|
|
* Forum ids to search - set in secondary methods
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $searchForumIds = array();
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @return @e void
|
|
*/
|
|
public function __construct( ipsRegistry $registry )
|
|
{
|
|
/* Hard limit */
|
|
IPSSearchRegistry::set('set.hardLimit', ( ipsRegistry::$settings['search_hardlimit'] ) ? ipsRegistry::$settings['search_hardlimit'] : 200 );
|
|
|
|
/* Get class forums, used for displaying forum names on results */
|
|
if ( ipsRegistry::isClassLoaded('class_forums') !== TRUE )
|
|
{
|
|
$classToLoad = IPSLib::loadLibrary( IPSLib::getAppDir( 'forums' ) . "/sources/classes/forums/class_forums.php", 'class_forums', 'forums' );
|
|
ipsRegistry::setClass( 'class_forums', new $classToLoad( ipsRegistry::instance() ) );
|
|
ipsRegistry::getClass('class_forums')->strip_invisible = 1;
|
|
ipsRegistry::getClass('class_forums')->forumsInit();
|
|
}
|
|
|
|
parent::__construct( $registry );
|
|
}
|
|
|
|
/**
|
|
* Perform a search.
|
|
* Returns an array of a total count (total number of matches)
|
|
* and an array of IDs ( 0 => 1203, 1 => 928, 2 => 2938 ).. matching the required number based on pagination. The ids returned would be based on the filters and type of search
|
|
*
|
|
* So if we had 1000 replies, and we are on page 2 of 25 per page, we'd return 25 items offset by 25
|
|
*
|
|
* @return array
|
|
*/
|
|
public function search()
|
|
{
|
|
$start = intval( IPSSearchRegistry::get('in.start') );
|
|
$perPage = IPSSearchRegistry::get('opt.search_per_page');
|
|
$sort_by = IPSSearchRegistry::get('in.search_sort_by');
|
|
$sort_order = IPSSearchRegistry::get('in.search_sort_order');
|
|
$search_term = IPSSearchRegistry::get('in.clean_search_term');
|
|
$search_type = IPSSearchRegistry::get('opt.searchType');
|
|
$search_tags = IPSSearchRegistry::get('in.raw_search_tags');
|
|
$search_ids = array();
|
|
$groupby = false;
|
|
$cType = IPSSearchRegistry::get('contextual.type');
|
|
$cId = IPSSearchRegistry::get('contextual.id' );
|
|
|
|
/* Contextual search */
|
|
if ( $cType == 'topic' )
|
|
{
|
|
$search_type = 'content';
|
|
IPSSearchRegistry::set('opt.searchType', 'content');
|
|
IPSSearchRegistry::set('opt.noPostPreview', false);
|
|
}
|
|
|
|
/* If searching tags, we don't show a preview */
|
|
if( $search_tags )
|
|
{
|
|
IPSSearchRegistry::set('opt.noPostPreview', true);
|
|
IPSSearchRegistry::set('opt.searchType', 'titles');
|
|
$search_type = 'titles';
|
|
}
|
|
|
|
/* Permissions */
|
|
$permissions = array();
|
|
$permissions['TopicSoftDeleteSee'] = $this->registry->getClass('class_forums')->canSeeSoftDeletedTopics( 0 );
|
|
$permissions['canQueue'] = $this->registry->getClass('class_forums')->canQueuePosts( 0 );
|
|
$permissions['PostSoftDeleteSee'] = $this->registry->getClass('class_forums')->canSeeSoftDeletedPosts( 0 );
|
|
$permissions['SoftDeleteReason'] = $this->registry->getClass('class_forums')->canSeeSoftDeleteReason( 0 );
|
|
$permissions['SoftDeleteContent'] = $this->registry->getClass('class_forums')->canSeeSoftDeleteContent( 0 );
|
|
|
|
/* Sorting */
|
|
switch( $sort_by )
|
|
{
|
|
default:
|
|
case 'date':
|
|
$sortKey = 'last_post';
|
|
$sortKeyPost = 'post_date';
|
|
break;
|
|
case 'title':
|
|
$sortKeyPost = $sortKey = 'tordinal';
|
|
break;
|
|
case 'posts':
|
|
$sortKeyPost = $sortKey = 'posts';
|
|
break;
|
|
case 'views':
|
|
$sortKeyPost = $sortKey = 'views';
|
|
break;
|
|
}
|
|
|
|
/* Limit Results */
|
|
$this->sphinxClient->SetLimits( intval($start), $perPage );
|
|
|
|
/* Loop through the forums and build a list of forums we're allowed access to */
|
|
if( is_array($this->searchForumIds) AND count($this->searchForumIds) )
|
|
{
|
|
$forumIdsOk = $this->searchForumIds;
|
|
}
|
|
else
|
|
{
|
|
$forumIdsOk = array();
|
|
$forumIdsBad = array();
|
|
|
|
if ( ! empty( ipsRegistry::$request['search_app_filters']['forums']['forums'] ) AND count( ipsRegistry::$request['search_app_filters']['forums']['forums'] ) )
|
|
{
|
|
foreach( ipsRegistry::$request['search_app_filters']['forums']['forums'] as $forum_id )
|
|
{
|
|
if( $forum_id )
|
|
{
|
|
$data = $this->registry->class_forums->forum_by_id[ $forum_id ];
|
|
|
|
/* Check for sub forums */
|
|
$children = ipsRegistry::getClass( 'class_forums' )->forumsGetChildren( $forum_id );
|
|
|
|
foreach( $children as $kid )
|
|
{
|
|
if( ! in_array( $kid, ipsRegistry::$request['search_app_filters']['forums']['forums'] ) )
|
|
{
|
|
if( ! $this->registry->permissions->check( 'read', $this->registry->class_forums->forum_by_id[ $kid ] ) )
|
|
{
|
|
$forumIdsBad[] = $kid;
|
|
continue;
|
|
}
|
|
|
|
/* Can read, but is it password protected, etc? */
|
|
if ( ! $this->registry->class_forums->forumsCheckAccess( $kid, 0, 'forum', array(), true ) )
|
|
{
|
|
$forumIdsBad[] = $kid;
|
|
continue;
|
|
}
|
|
|
|
if ( ! $this->registry->class_forums->forum_by_id[ $kid ]['sub_can_post'] OR ! $this->registry->class_forums->forum_by_id[ $kid ]['can_view_others'] )
|
|
{
|
|
$forumIdsBad[] = $kid;
|
|
continue;
|
|
}
|
|
|
|
$forumIdsOk[] = $kid;
|
|
}
|
|
}
|
|
|
|
/* Can we read? */
|
|
if ( ! $this->registry->permissions->check( 'view', $data ) )
|
|
{
|
|
$forumIdsBad[] = $forum_id;
|
|
continue;
|
|
}
|
|
|
|
/* Can read, but is it password protected, etc? */
|
|
if ( ! $this->registry->class_forums->forumsCheckAccess( $forum_id, 0, 'forum', array(), true ) )
|
|
{
|
|
$forumIdsBad[] = $forum_id;
|
|
continue;
|
|
}
|
|
|
|
if ( ! $data['sub_can_post'] OR ! $data['can_view_others'] AND !$this->memberData['g_access_cp'] )
|
|
{
|
|
$forumIdsBad[] = $forum_id;
|
|
continue;
|
|
}
|
|
|
|
$forumIdsOk[] = $forum_id;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( ! count($forumIdsOk) )
|
|
{
|
|
/* Get list of good forum IDs */
|
|
$forumIdsOk = $this->registry->class_forums->fetchSearchableForumIds();
|
|
}
|
|
|
|
/* Add allowed forums */
|
|
$forumIdsOk = ( count( $forumIdsOk ) ) ? $forumIdsOk : array( 0 => 0 );
|
|
|
|
/* Contextual */
|
|
if ( $cType == 'forum' AND $cId AND in_array( $cId, $forumIdsOk ) )
|
|
{
|
|
$this->sphinxClient->SetFilter( 'forum_id', array( $cId ) );
|
|
}
|
|
else
|
|
{
|
|
$this->sphinxClient->SetFilter( 'forum_id', $forumIdsOk );
|
|
}
|
|
|
|
/* Topic contextual */
|
|
if ( $cType == 'topic' AND $cId )
|
|
{
|
|
$this->sphinxClient->SetFilter( 'tid', array( $cId ) );
|
|
}
|
|
|
|
/* Exclude some items */
|
|
if ( $search_type != 'titles' )
|
|
{
|
|
if ( $permissions['SoftDeleteContent'] AND $permissions['PostSoftDeleteSee'] AND $permissions['canQueue'] )
|
|
{
|
|
$this->sphinxClient->SetFilter( 'queued', array( 0,1,2 ) );
|
|
}
|
|
else if ( $permissions['SoftDeleteContent'] AND $permissions['PostSoftDeleteSee'] )
|
|
{
|
|
$this->sphinxClient->SetFilter( 'queued', array( 0,2 ) );
|
|
}
|
|
else if ( $permissions['canQueue'] )
|
|
{
|
|
$this->sphinxClient->SetFilter( 'queued', array( 0,1 ) );
|
|
}
|
|
else
|
|
{
|
|
$this->sphinxClient->SetFilter( 'queued', array( 0 ) );
|
|
}
|
|
}
|
|
|
|
if ( $permissions['SoftDeleteContent'] AND $permissions['TopicSoftDeleteSee'] AND $permissions['canQueue'] )
|
|
{
|
|
$this->sphinxClient->SetFilter( 'approved' , array( 0,1 ) );
|
|
$this->sphinxClient->SetFilter( 'soft_deleted', array( 0,1 ) );
|
|
}
|
|
else if ( $permissions['SoftDeleteContent'] AND $permissions['TopicSoftDeleteSee'] )
|
|
{
|
|
$this->sphinxClient->SetFilter( 'approved', array( 1 ) );
|
|
$this->sphinxClient->SetFilter( 'soft_deleted', array( 0,1 ) );
|
|
}
|
|
else if ( $permissions['canQueue'] )
|
|
{
|
|
$this->sphinxClient->SetFilter( 'soft_deleted', array( 0 ) );
|
|
$this->sphinxClient->SetFilter( 'approved', array( 0,1 ) );
|
|
}
|
|
else
|
|
{
|
|
$this->sphinxClient->SetFilter( 'soft_deleted', array( 0 ) );
|
|
$this->sphinxClient->SetFilter( 'approved', array( 1 ) );
|
|
}
|
|
|
|
|
|
/* Additional filters */
|
|
if ( IPSSearchRegistry::get('opt.pCount') )
|
|
{
|
|
$this->sphinxClient->SetFilterRange( 'posts', intval( IPSSearchRegistry::get('opt.pCount') ), 1500000000 );
|
|
}
|
|
|
|
if ( IPSSearchRegistry::get('opt.pViews') )
|
|
{
|
|
$this->sphinxClient->SetFilterRange( 'views', intval( IPSSearchRegistry::get('opt.pViews') ), 1500000000 );
|
|
}
|
|
|
|
/* Date limit */
|
|
if ( $this->search_begin_timestamp )
|
|
{
|
|
if ( ! $this->search_end_timestamp )
|
|
{
|
|
$this->search_end_timestamp = time() + 100;
|
|
}
|
|
|
|
if ( $search_type == 'titles' )
|
|
{
|
|
$this->sphinxClient->SetFilterRange( 'start_date', $this->search_begin_timestamp, $this->search_end_timestamp );
|
|
}
|
|
else
|
|
{
|
|
$this->sphinxClient->SetFilterRange( 'post_date', $this->search_begin_timestamp, $this->search_end_timestamp );
|
|
}
|
|
}
|
|
|
|
if ( IPSSearchRegistry::get('opt.noPostPreview') OR $search_type == 'titles' )
|
|
{
|
|
$groupby = true;
|
|
}
|
|
|
|
/* Check tags */
|
|
$_tag = '';
|
|
$tagIds = array();
|
|
|
|
if ( $search_tags && $this->settings['tags_enabled'] )
|
|
{
|
|
$search_tags = explode( ",", $search_tags );
|
|
|
|
$this->DB->build( array( 'select' => 'tag_id',
|
|
'from' => 'core_tags',
|
|
'where' => 'tag_meta_app=\'forums\' AND tag_meta_area=\'topics\' AND (' . $this->DB->buildLikeChain( 'tag_text', $search_tags, false ) . ')',
|
|
'limit' => array( 0, 500 ) ) );
|
|
|
|
$o = $this->DB->execute();
|
|
|
|
while( $row = $this->DB->fetch( $o ) )
|
|
{
|
|
$tagIds[] = $row['tag_id'];
|
|
}
|
|
|
|
if ( count( $tagIds ) )
|
|
{
|
|
$this->sphinxClient->SetFilter( 'tag_id', $tagIds );
|
|
}
|
|
}
|
|
|
|
/* Set sort order */
|
|
if ( $sort_order == 'asc' )
|
|
{
|
|
$this->sphinxClient->SetSortMode( SPH_SORT_ATTR_ASC, $sortKey );
|
|
}
|
|
else
|
|
{
|
|
$this->sphinxClient->SetSortMode( SPH_SORT_ATTR_DESC, $sortKey );
|
|
}
|
|
|
|
/* Generate sphinx search query */
|
|
switch( $search_type )
|
|
{
|
|
case 'titles':
|
|
/* Group by */
|
|
if ( $groupby )
|
|
{
|
|
/* @link http://community.invisionpower.com/topic/335036-sphinx-vncactive-content-sorting/ */
|
|
$this->sphinxClient->SetGroupDistinct ( "tid" );
|
|
$this->sphinxClient->SetGroupBy( 'tid', SPH_GROUPBY_ATTR, '@group ' . $sort_order );
|
|
}
|
|
|
|
$_s = ( $search_term ) ? '@title ' . $search_term : '';
|
|
break;
|
|
|
|
case 'content':
|
|
/* Group by */
|
|
if ( $groupby )
|
|
{
|
|
$this->sphinxClient->SetSortMode( SPH_SORT_EXTENDED, $sortKeyPost . ' DESC' );
|
|
$this->sphinxClient->SetGroupBy( 'tid', SPH_GROUPBY_ATTR, 'last_post ' . $sort_order );
|
|
|
|
IPSSearchRegistry::set('set.searchResultType', 'both' );
|
|
}
|
|
|
|
|
|
$_s = ( $search_term ) ? '@post ' . $search_term : '';
|
|
break;
|
|
|
|
case 'both':
|
|
default:
|
|
/* Group by */
|
|
if ( $groupby )
|
|
{
|
|
$this->sphinxClient->SetSortMode( SPH_SORT_EXTENDED, $sortKeyPost . ' DESC' );
|
|
$this->sphinxClient->SetGroupBy( 'tid', SPH_GROUPBY_ATTR, 'last_post ' . $sort_order );
|
|
}
|
|
|
|
IPSSearchRegistry::set('set.searchResultType', 'both' );
|
|
|
|
$_s = ( $search_term AND strstr( $search_term, '"' ) ) ? '@post ' . $search_term . ' | @title ' . $search_term : ( $search_term ? '@(post,title) ' . $search_term : '' );
|
|
break;
|
|
}
|
|
|
|
/* Perform search */
|
|
$result = $this->sphinxClient->Query( $_s . $_tag, $this->settings['sphinx_prefix'] . 'forums_search_posts_main, ' . $this->settings['sphinx_prefix'] . 'forums_search_posts_delta' );
|
|
|
|
/* Log errors */
|
|
$this->logSphinxWarnings();
|
|
|
|
/* Get result ids */
|
|
if ( is_array( $result['matches'] ) && count( $result['matches'] ) )
|
|
{
|
|
$c = 0;
|
|
|
|
foreach( $result['matches'] as $res )
|
|
{
|
|
$search_ids[] = ( $search_type == 'titles' && IPSSearchRegistry::get('set.searchResultType') != 'both' ) ? $res['attrs']['tid'] : $res['attrs']['search_id'];
|
|
}
|
|
}
|
|
|
|
/* Set return type */
|
|
if ( $search_type == 'titles' )
|
|
{
|
|
IPSSearchRegistry::set('set.returnType', 'tids' );
|
|
}
|
|
else
|
|
{
|
|
IPSSearchRegistry::set('set.returnType', 'pids' );
|
|
}
|
|
|
|
/* Return it */
|
|
return array( 'count' => intval( $result['total_found'] ) > 1000 ? 1000 : $result['total_found'], 'resultSet' => $search_ids );
|
|
}
|
|
|
|
/**
|
|
* Perform the search
|
|
* Populates $this->_count and $this->_results
|
|
*
|
|
* @return array
|
|
*/
|
|
public function viewUserContent( $member )
|
|
{
|
|
/* Bit of init */
|
|
$time = ( $member['last_post'] ? $member['last_post'] : time() ) - ( 86400 * intval( $this->settings['search_ucontent_days'] ) );
|
|
$sort_by = IPSSearchRegistry::get('in.search_sort_by');
|
|
$sort_order = IPSSearchRegistry::get('in.search_sort_order');
|
|
|
|
switch( IPSSearchRegistry::get('in.userMode') )
|
|
{
|
|
default:
|
|
case 'all':
|
|
IPSSearchRegistry::set('opt.searchType', 'both');
|
|
IPSSearchRegistry::set('opt.noPostPreview' , true );
|
|
break;
|
|
case 'title':
|
|
IPSSearchRegistry::set('opt.searchType', 'titles');
|
|
IPSSearchRegistry::set('opt.noPostPreview' , true );
|
|
break;
|
|
case 'content':
|
|
IPSSearchRegistry::set('opt.searchType', 'content');
|
|
IPSSearchRegistry::set('opt.noPostPreview' , false );
|
|
break;
|
|
}
|
|
|
|
/* Sorting */
|
|
switch( $sort_by )
|
|
{
|
|
default:
|
|
case 'date':
|
|
$sortKey = 'last_post';
|
|
$sortKeyPost = 'post_date';
|
|
break;
|
|
case 'title':
|
|
$sortKeyPost = $sortKey = 'tordinal';
|
|
break;
|
|
case 'posts':
|
|
$sortKeyPost = $sortKey = 'posts';
|
|
break;
|
|
case 'views':
|
|
$sortKeyPost = $sortKey = 'views';
|
|
break;
|
|
}
|
|
|
|
/* Init */
|
|
$start = IPSSearchRegistry::get('in.start');
|
|
$perPage = IPSSearchRegistry::get('opt.search_per_page');
|
|
|
|
//IPSSearchRegistry::set('in.search_sort_by' , 'date' );
|
|
//IPSSearchRegistry::set('in.search_sort_order', 'desc' );
|
|
|
|
/* Limit Results */
|
|
$this->sphinxClient->SetLimits( intval($start), intval($perPage) );
|
|
|
|
/* Get list of good forum IDs */
|
|
$forumIdsOk = $this->registry->class_forums->fetchSearchableForumIds( $this->memberData['member_id'] );
|
|
|
|
$this->sphinxClient->SetFilter( 'forum_id', $forumIdsOk );
|
|
|
|
/* what we doing? */
|
|
if ( IPSSearchRegistry::get('in.userMode') != 'title' )
|
|
{
|
|
$this->sphinxClient->SetFilter( 'author_id', array( intval( $member['member_id'] ) ) );
|
|
}
|
|
else
|
|
{
|
|
$this->sphinxClient->SetFilter( 'starter_id', array( intval( $member['member_id'] ) ) );
|
|
}
|
|
|
|
if ( $this->settings['search_ucontent_days'] )
|
|
{
|
|
$this->sphinxClient->SetFilterRange( 'post_date', $time, time() );
|
|
}
|
|
|
|
/* Set up perms */
|
|
$permissions = array();
|
|
$permissions['TopicSoftDeleteSee'] = $this->registry->getClass('class_forums')->canSeeSoftDeletedTopics( 0 );
|
|
$permissions['canQueue'] = $this->registry->getClass('class_forums')->canQueuePosts( 0 );
|
|
$permissions['PostSoftDeleteSee'] = $this->registry->getClass('class_forums')->canSeeSoftDeletedPosts( 0 );
|
|
$permissions['SoftDeleteReason'] = $this->registry->getClass('class_forums')->canSeeSoftDeleteReason( 0 );
|
|
$permissions['SoftDeleteContent'] = $this->registry->getClass('class_forums')->canSeeSoftDeleteContent( 0 );
|
|
|
|
/* Exclude some items */
|
|
if ( IPSSearchRegistry::get('in.userMode') != 'title' )
|
|
{
|
|
if ( $permissions['SoftDeleteContent'] AND $permissions['PostSoftDeleteSee'] AND $permissions['canQueue'] )
|
|
{
|
|
$this->sphinxClient->SetFilter( 'queued', array( 0,1,2 ) );
|
|
}
|
|
else if ( $permissions['SoftDeleteContent'] AND $permissions['PostSoftDeleteSee'] )
|
|
{
|
|
$this->sphinxClient->SetFilter( 'queued', array( 0,2 ) );
|
|
}
|
|
else if ( $permissions['canQueue'] )
|
|
{
|
|
$this->sphinxClient->SetFilter( 'queued', array( 0,1 ) );
|
|
}
|
|
else
|
|
{
|
|
$this->sphinxClient->SetFilter( 'queued', array( 0 ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( $permissions['SoftDeleteContent'] AND $permissions['TopicSoftDeleteSee'] AND $permissions['canQueue'] )
|
|
{
|
|
$this->sphinxClient->SetFilter( 'approved' , array( 0,1 ) );
|
|
$this->sphinxClient->SetFilter( 'soft_deleted', array( 0,1 ) );
|
|
}
|
|
else if ( $permissions['SoftDeleteContent'] AND $permissions['TopicSoftDeleteSee'] )
|
|
{
|
|
$this->sphinxClient->SetFilter( 'approved', array( 0 ) );
|
|
$this->sphinxClient->SetFilter( 'soft_deleted', array( 0,1 ) );
|
|
}
|
|
else if ( $permissions['canQueue'] )
|
|
{
|
|
$this->sphinxClient->SetFilter( 'soft_deleted', array( 0 ) );
|
|
$this->sphinxClient->SetFilter( 'approved', array( 0,1 ) );
|
|
}
|
|
else
|
|
{
|
|
$this->sphinxClient->SetFilter( 'soft_deleted', array( 0 ) );
|
|
$this->sphinxClient->SetFilter( 'approved', array( 1 ) );
|
|
}
|
|
}
|
|
|
|
/* Perform 'search' */
|
|
/* We have to sort by topic last post date for 'both' otherwise the topics will appear in random order. Even though it's correctly ordering by YOUR post
|
|
date, the user just sees the list of topics with random last post date ordering. In a future version it would be nice to change the last post column
|
|
on 'view user content' to show something like "you last posted on x date" instead of showing the topic last poster and last post date.
|
|
@link http://community.invisionpower.com/tracker/issue-33692-my-content-second-page */
|
|
if ( IPSSearchRegistry::get('in.userMode') == 'title' OR IPSSearchRegistry::get('in.userMode') == 'all' )
|
|
{
|
|
/* Set return type */
|
|
IPSSearchRegistry::set('set.returnType', 'tids' );
|
|
|
|
$this->sphinxClient->SetGroupDistinct ( "tid" );
|
|
$this->sphinxClient->SetGroupBy( 'tid', SPH_GROUPBY_ATTR, $sortKey . ' ' . $sort_order );
|
|
|
|
if ( $sort_order == 'asc' )
|
|
{
|
|
$this->sphinxClient->SetSortMode( SPH_SORT_ATTR_ASC, $sortKey );
|
|
}
|
|
else
|
|
{
|
|
$this->sphinxClient->SetSortMode( SPH_SORT_ATTR_DESC, $sortKey );
|
|
}
|
|
|
|
$result = $this->sphinxClient->Query( '', $this->settings['sphinx_prefix'] . 'forums_search_posts_main,' . $this->settings['sphinx_prefix'] . 'forums_search_posts_delta' );
|
|
}
|
|
else
|
|
{
|
|
/* Set return type */
|
|
if( IPSSearchRegistry::get('in.userMode') == 'all' )
|
|
{
|
|
IPSSearchRegistry::set('set.returnType', 'tids' );
|
|
}
|
|
else
|
|
{
|
|
IPSSearchRegistry::set('set.returnType', 'pids' );
|
|
}
|
|
|
|
if ( $sort_order == 'asc' )
|
|
{
|
|
$this->sphinxClient->SetSortMode( SPH_SORT_ATTR_ASC, $sortKeyPost );
|
|
}
|
|
else
|
|
{
|
|
$this->sphinxClient->SetSortMode( SPH_SORT_ATTR_DESC, $sortKeyPost );
|
|
}
|
|
|
|
if ( IPSSearchRegistry::get('in.userMode') != 'content' )
|
|
{
|
|
$this->sphinxClient->SetGroupBy( 'tid', SPH_GROUPBY_ATTR, $sortKeyPost . ' ' . $sort_order );
|
|
}
|
|
|
|
$result = $this->sphinxClient->Query( '', $this->settings['sphinx_prefix'] . 'forums_search_posts_main,' . $this->settings['sphinx_prefix'] . 'forums_search_posts_delta' );
|
|
}
|
|
|
|
/* Log warnings */
|
|
$this->logSphinxWarnings();
|
|
|
|
/* Get result ids */
|
|
if ( is_array( $result['matches'] ) && count( $result['matches'] ) )
|
|
{
|
|
foreach( $result['matches'] as $res )
|
|
{
|
|
$search_ids[] = ( IPSSearchRegistry::get('set.returnType') == 'tids' ) ? $res['attrs']['tid'] : $res['attrs']['search_id'];
|
|
}
|
|
}
|
|
|
|
/* Return results */
|
|
return array( 'count' => intval( $result['total_found'] ) > 1000 ? 1000 : $result['total_found'], 'resultSet' => $search_ids );
|
|
}
|
|
|
|
/**
|
|
* Perform the viewNewContent search
|
|
* Forum Version
|
|
* Populates $this->_count and $this->_results
|
|
*
|
|
* @return array
|
|
*/
|
|
public function viewNewContent()
|
|
{
|
|
$oldStamp = $this->registry->getClass('classItemMarking')->fetchOldestUnreadTimestamp( array(), 'forums' );
|
|
$check = IPS_UNIX_TIME_NOW - ( 86400 * $this->settings['topic_marking_keep_days'] );
|
|
$forumIdsOk = array();
|
|
$start = IPSSearchRegistry::get('in.start');
|
|
$perPage = IPSSearchRegistry::get('opt.search_per_page');
|
|
$seconds = IPSSearchRegistry::get('in.period_in_seconds');
|
|
$followedOnly = $this->memberData['member_id'] ? IPSSearchRegistry::get('in.vncFollowFilterOn' ) : false;
|
|
$permissions = array();
|
|
|
|
/* Loop through the forums and build a list of forums we're allowed access to */
|
|
$bvnp = explode( ',', $this->settings['vnp_block_forums'] );
|
|
|
|
IPSSearchRegistry::set('in.search_sort_by' , 'date' );
|
|
IPSSearchRegistry::set('in.search_sort_order', 'desc' );
|
|
IPSSearchRegistry::set('opt.noPostPreview' , true );
|
|
IPSSearchRegistry::set('opt.searchType' , 'titles' );
|
|
|
|
$followedForums = array();
|
|
$followedTopics = array();
|
|
|
|
//-----------------------------------------
|
|
// Only content we have participated in?
|
|
//-----------------------------------------
|
|
|
|
if( IPSSearchRegistry::get('in.userMode') )
|
|
{
|
|
$_tempResults = $this->viewUserContent( $this->memberData );
|
|
|
|
if( $_tempResults['count'] )
|
|
{
|
|
$this->sphinxClient->SetFilter( 'tid', $_tempResults['resultSet'] );
|
|
}
|
|
else
|
|
{
|
|
return array( 'count' => 0, 'resultSet' => array() );
|
|
}
|
|
|
|
switch( IPSSearchRegistry::get('in.userMode') )
|
|
{
|
|
default:
|
|
case 'all':
|
|
case 'content':
|
|
IPSSearchRegistry::set('opt.searchType', 'both' );
|
|
IPSSearchRegistry::set('opt.noPostPreview' , true );
|
|
break;
|
|
case 'title':
|
|
IPSSearchRegistry::set('opt.searchType', 'titles' );
|
|
IPSSearchRegistry::set('opt.noPostPreview' , false );
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Set return type */
|
|
IPSSearchRegistry::set('set.returnType', 'tids' );
|
|
|
|
/* Get list of good forum IDs */
|
|
$_forumIdsOk = $this->registry->class_forums->fetchSearchableForumIds( $this->memberData['member_id'], ( $followedOnly ) ? array() : $bvnp );
|
|
|
|
/* Fetch forum rel ids */
|
|
if ( $followedOnly )
|
|
{
|
|
require_once( IPS_ROOT_PATH . 'sources/classes/like/composite.php' );/*noLibHook*/
|
|
|
|
/* @link http://community.invisionpower.com/tracker/issue-33284-view-new-content-just-items-i-follow */
|
|
//$like = classes_like::bootstrap( 'forums', 'forums' );
|
|
|
|
//$followedForums = $like->getDataByMemberIdAndArea( $this->memberData['member_id'] );
|
|
$followedForums = array(); //( $followedForums === null ) ? array() : array_keys( $followedForums );
|
|
|
|
$like = classes_like::bootstrap( 'forums', 'topics' );
|
|
|
|
$followedTopics = $like->getDataByMemberIdAndArea( $this->memberData['member_id'] );
|
|
$followedTopics = ( $followedTopics === null ) ? array() : array_keys( $followedTopics );
|
|
}
|
|
|
|
/* What type of date restriction? */
|
|
if ( IPSSearchRegistry::get('in.period_in_seconds') !== false )
|
|
{
|
|
$oldStamp = ( time() - $seconds );
|
|
$forumIdsOk = $_forumIdsOk;
|
|
}
|
|
else
|
|
{
|
|
foreach( $_forumIdsOk as $id )
|
|
{
|
|
if ( $followedOnly && ! in_array( $id, $followedForums ) )
|
|
{
|
|
// We don't want to skip followed topics just because we don't follow the forum
|
|
//continue;
|
|
}
|
|
|
|
$lMarked = $this->registry->getClass('classItemMarking')->fetchTimeLastMarked( array( 'forumID' => $id ), 'forums' );
|
|
$fData = $this->registry->getClass('class_forums')->forumsFetchData( $id );
|
|
|
|
if ( $fData['last_post'] > $lMarked )
|
|
{
|
|
$forumIdsOk[ $id ] = $id;
|
|
}
|
|
}
|
|
|
|
if ( intval( $this->memberData['_cache']['gb_mark__forums'] ) > 0 )
|
|
{
|
|
$oldStamp = $this->memberData['_cache']['gb_mark__forums'];
|
|
}
|
|
|
|
/* Finalize times */
|
|
if ( ! $oldStamp OR $oldStamp == IPS_UNIX_TIME_NOW )
|
|
{
|
|
$oldStamp = intval( $this->memberData['last_visit'] );
|
|
}
|
|
|
|
/* Older than 3 months.. then limit */
|
|
if ( $oldStamp < $check )
|
|
{
|
|
$oldStamp = $check;
|
|
}
|
|
|
|
/* If no forums, we're done */
|
|
if ( ! count( $forumIdsOk ) )
|
|
{
|
|
/* Return it */
|
|
return array( 'count' => 0, 'resultSet' => array() );
|
|
}
|
|
}
|
|
|
|
/* Only show VNC results from specified forums? */
|
|
if ( is_array(IPSSearchRegistry::get('forums.vncForumFilters')) AND count(IPSSearchRegistry::get('forums.vncForumFilters')) )
|
|
{
|
|
$_newIdsOk = array();
|
|
|
|
foreach( IPSSearchRegistry::get('forums.vncForumFilters') as $forumId )
|
|
{
|
|
if( in_array( $forumId, $forumIdsOk ) )
|
|
{
|
|
$_newIdsOk[] = $forumId;
|
|
}
|
|
}
|
|
|
|
$forumIdsOk = $_newIdsOk;
|
|
}
|
|
|
|
/* Set the timestamps */
|
|
$this->sphinxClient->SetFilterRange( 'last_post', $oldStamp, time() );
|
|
$this->setDateRange( 0, 0 );
|
|
|
|
/* Force it into filter so that search can pick it up */
|
|
$this->searchForumIds = $forumIdsOk;
|
|
|
|
/* Set up some vars */
|
|
IPSSearchRegistry::set('set.resultCutToDate', $oldStamp );
|
|
|
|
/* Fetch first 300 results */
|
|
IPSSearchRegistry::set('opt.search_per_page', 300);
|
|
IPSSearchRegistry::set('in.start', 0);
|
|
|
|
/* Run search */
|
|
$data = $this->search();
|
|
|
|
/* Reset for display function */
|
|
IPSSearchRegistry::set('in.start', $start);
|
|
IPSSearchRegistry::set('opt.search_per_page', $perPage);
|
|
|
|
$_ffWhere = '';
|
|
|
|
/* Followed topics only */
|
|
if ( $followedOnly )
|
|
{
|
|
if ( ! count( $followedTopics ) && ! count( $followedForums ) )
|
|
{
|
|
return array( 'count' => 0, 'resultSet' => array() );
|
|
}
|
|
|
|
if ( count( $followedForums ) )
|
|
{
|
|
/* @link http://community.invisionpower.com/tracker/issue-33284-view-new-content-just-items-i-follow */
|
|
//$_ffWhere = ' OR forum_id IN (' . implode( ',', $followedForums ) . ') ';
|
|
}
|
|
}
|
|
|
|
/* This method allows us to have just one "tid IN()" clause, instead of two, depending on scenario */
|
|
if ( count($followedTopics) )
|
|
{
|
|
$where[] = "( tid IN(" . implode( ',', $followedTopics ) . ')' . $_ffWhere . ' )';
|
|
}
|
|
else
|
|
{
|
|
if( !count($data['resultSet']) )
|
|
{
|
|
return array( 'count' => 0, 'resultSet' => array() );
|
|
}
|
|
|
|
$where[] = "( tid IN(" . implode( ',', $data['resultSet'] ) . ')' . $_ffWhere . ' )';
|
|
}
|
|
|
|
$permissions['TopicSoftDeleteSee'] = $this->registry->getClass('class_forums')->canSeeSoftDeletedTopics( 0 );
|
|
$permissions['canQueue'] = $this->registry->getClass('class_forums')->canQueuePosts( 0 );
|
|
|
|
if ( $permissions['TopicSoftDeleteSee'] AND $permissions['canQueue'] )
|
|
{
|
|
$where[] = $this->registry->class_forums->fetchTopicHiddenQuery( array( 'visible', 'hidden', 'sdeleted' ) );
|
|
}
|
|
else if ( $permissions['TopicSoftDeleteSee'] )
|
|
{
|
|
$where[] = $this->registry->class_forums->fetchTopicHiddenQuery( array( 'visible', 'sdeleted' ) );
|
|
}
|
|
else if ( $permissions['canQueue'] )
|
|
{
|
|
$where[] = $this->registry->class_forums->fetchTopicHiddenQuery( array( 'visible', 'hidden' ) );
|
|
}
|
|
else
|
|
{
|
|
$where[] = $this->registry->class_forums->fetchTopicHiddenQuery( array( 'visible' ) );
|
|
}
|
|
|
|
$where = implode( " AND ", $where );
|
|
|
|
/* Fetch the count */
|
|
$count = $this->DB->buildAndFetch( array( 'select' => 'count(*) as count',
|
|
'from' => 'topics',
|
|
'where' => $where ) );
|
|
|
|
/* Fetch the count */
|
|
if ( $count['count'] )
|
|
{
|
|
$limit = ( IPSSearchRegistry::get('in.period') != 'unread' ) ? array( $start, $perPage ) : array( 0, 1200 );
|
|
|
|
$this->DB->build( array( 'select' => 'tid, forum_id, last_post',
|
|
'from' => 'topics',
|
|
'where' => $where,
|
|
'order' => 'last_post DESC',
|
|
'limit' => $limit ) );
|
|
|
|
$inner = $this->DB->execute();
|
|
|
|
while( $row = $this->DB->fetch( $inner ) )
|
|
{
|
|
$rtids[ $row['tid'] ] = $row;
|
|
}
|
|
}
|
|
|
|
/* Set up some vars */
|
|
IPSSearchRegistry::set('set.resultCutToDate', $oldStamp );
|
|
|
|
if ( IPSSearchRegistry::get('in.period') == 'unread' )
|
|
{
|
|
$filter = $this->registry->class_forums->postProcessVncTids( $rtids, array( $start, $perPage ) );
|
|
$data['count'] = $filter['count'];
|
|
$data['resultSet'] = $filter['tids'];
|
|
}
|
|
else
|
|
{
|
|
$data = array( 'count' => $count['count'], 'resultSet' => array_keys( $rtids) );
|
|
}
|
|
|
|
/* Return it */
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Remap standard columns (Apps can override )
|
|
*
|
|
* @param string $column sql table column for this condition
|
|
* @return string column
|
|
* @return @e void
|
|
*/
|
|
public function remapColumn( $column )
|
|
{
|
|
$column = $column == 'member_id' ? ( IPSSearchRegistry::get('opt.searchTitleOnly') ? 'starter_id' : 'author_id' ) : $column;
|
|
$column = $column == 'content_title' ? 'title' : $column;
|
|
$column = $column == 'type_id' ? 'forum_id' : $column;
|
|
|
|
return $column;
|
|
}
|
|
|
|
/**
|
|
* Returns an array used in the searchplugin's setCondition method
|
|
*
|
|
* @param array $data Array of filters to apply
|
|
* @return array Array with column, operator, and value keys, for use in the setCondition call
|
|
*/
|
|
public function buildFilterSQL( $data )
|
|
{
|
|
/* INIT */
|
|
$return = array();
|
|
|
|
/* Set up some defaults */
|
|
IPSSearchRegistry::set( 'opt.noPostPreview' , true );
|
|
|
|
if ( ! IPSSearchRegistry::get('opt.searchType' ) )
|
|
{
|
|
IPSSearchRegistry::set( 'opt.searchType', 'both' );
|
|
}
|
|
|
|
if( isset( $data ) && is_array( $data ) && count( $data ) )
|
|
{
|
|
foreach( $data as $field => $_data )
|
|
{
|
|
/* CONTENT ONLY */
|
|
if ( $field == 'noPreview' AND $_data['noPreview'] == 0 )
|
|
{
|
|
IPSSearchRegistry::set( 'opt.noPostPreview', false );
|
|
}
|
|
|
|
/* POST COUNT */
|
|
if ( $field == 'pCount' AND intval( $_data['pCount'] ) > 0 )
|
|
{
|
|
IPSSearchRegistry::set( 'opt.pCount', intval( $_data['pCount'] ) );
|
|
}
|
|
|
|
/* TOPIC VIEWS */
|
|
if ( $field == 'pViews' AND intval( $_data ) > 0 )
|
|
{
|
|
IPSSearchRegistry::set( 'opt.pViews', intval( $_data['pViews'] ) );
|
|
}
|
|
}
|
|
|
|
return $return;
|
|
}
|
|
else
|
|
{
|
|
return array();
|
|
}
|
|
}
|
|
} |