* Invision Power Services * IP.Board v3.1.4 * Basic Forum Search * Last Updated: $Date: 2010-02-23 12:38:11 +0000 (Tue, 23 Feb 2010) $ * * * @author $Author: matt $ * @copyright (c) 2001 - 2009 Invision Power Services, Inc. * @license http://www.invisionpower.com/community/board/license.html * @package IP.Board * @subpackage Forums * @link http://www.invisionpower.com * @version $Rev: 5861 $ */ if ( ! defined( 'IN_IPB' ) ) { print "

Incorrect access

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 { /** * Constructor */ 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')->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() { /* INIT */ $count = 0; $results = array(); $sort_by = IPSSearchRegistry::get('in.search_sort_by'); $sort_order = IPSSearchRegistry::get('in.search_sort_order'); $search_term = IPSSearchRegistry::get('in.clean_search_term'); $content_title_only = IPSSearchRegistry::get('opt.searchTitleOnly'); $post_search_only = IPSSearchRegistry::get('opt.onlySearchPosts'); $order_dir = ( $sort_order == 'asc' ) ? 'asc' : 'desc'; $rows = array(); $count = 0; $c = 0; $got = 0; $sortKey = ''; $sortType = ''; $cType = IPSSearchRegistry::get('contextual.type'); $cId = IPSSearchRegistry::get('contextual.id' ); /* Contextual search */ if ( $cType == 'topic' ) { $content_title_only = false; $post_search_only = true; IPSSearchRegistry::set('opt.searchTitleOnly', false); IPSSearchRegistry::set('opt.onlySearchPosts', true); IPSSearchRegistry::set('display.onlyTitles', false); IPSSearchRegistry::set('opt.noPostPreview', false); } /* Sorting */ switch( $sort_by ) { default: case 'date': $sortKey = ( $content_title_only ) ? 'last_post' : 'post_date'; $sortType = 'numerical'; break; case 'title': $sortKey = 'title'; $sortType = 'string'; break; case 'posts': $sortKey = 'posts'; $sortType = 'numerical'; break; case 'views': $sortKey = 'views'; $sortType = 'numerical'; break; } /* Search in titles */ if ( $content_title_only ) { /* Do the search */ $this->DB->build( array( 'select' => "t.tid as id, t.tid as topic_id, t.title, t.posts, t.views, t.last_post", 'from' => 'topics t', 'where' => $this->_buildWhereStatement( $search_term, $content_title_only ), 'limit' => array(0, IPSSearchRegistry::get('set.hardLimit') + 1), 'order' => 't.'.$sortKey . ' ' . $order_dir ) ); } else { /* Do the search */ $this->DB->build( array( 'select' => "p.pid as id, post_date, p.topic_id", 'from' => array( 'posts' => 'p' ), 'where' => $this->_buildWhereStatement( $search_term, $content_title_only, '', null, ( IPSSearchRegistry::get('opt.onlySearchPosts') || IPSSearchRegistry::get('in.search_author') ) ? false : true ), 'limit' => array(0, IPSSearchRegistry::get('set.hardLimit') + 1), 'order' => $sortKey . ' ' . $sort_order, 'add_join' => array( array( 'select' => 't.title, t.posts, t.views', 'from' => array( 'topics' => 't' ), 'where' => 't.tid=p.topic_id', 'type' => 'left' ) ) ) ); } $DB = $this->DB->execute(); /* Fetch all to sort */ while( $r = $this->DB->fetch( $DB ) ) { if ( IPSSearchRegistry::get('opt.noPostPreview') ) { $_rows[ $r['topic_id'] ] = $r; } else { $_rows[ $r['id'] ] = $r; } } /* Fetch count */ $count = count( $_rows ); if ( $count > IPSSearchRegistry::get('set.hardLimit') ) { $count = IPSSearchRegistry::get('set.hardLimit'); IPSSearchRegistry::set('set.resultsCutToLimit', true ); } /* Set vars */ IPSSearch::$ask = $sortKey; IPSSearch::$aso = strtolower( $order_dir ); IPSSearch::$ast = $sortType; /* Sort */ if ( count( $_rows ) ) { usort( $_rows, array("IPSSearch", "usort") ); /* Build result array */ foreach( $_rows as $r ) { $c++; if ( IPSSearchRegistry::get('in.start') AND IPSSearchRegistry::get('in.start') >= $c ) { continue; } $rows[ $got ] = $r['id']; $got++; /* Done? */ if ( IPSSearchRegistry::get('opt.search_per_page') AND $got >= IPSSearchRegistry::get('opt.search_per_page') ) { break; } } } /* Return it */ return array( 'count' => $count, 'resultSet' => $rows ); } /** * Perform the search * Populates $this->_count and $this->_results * * @return nothin' */ public function viewUserContent( $member ) { $app = IPSSearchRegistry::get('in.search_app'); IPSSearchRegistry::set('in.search_sort_by' , 'date' ); IPSSearchRegistry::set('in.search_sort_order', 'desc' ); switch( IPSSearchRegistry::get('in.userMode') ) { default: case 'all': IPSSearchRegistry::set('opt.searchTitleOnly', true ); IPSSearchRegistry::set('display.onlyTitles' , true ); IPSSearchRegistry::set('opt.noPostPreview' , false ); break; case 'title': IPSSearchRegistry::set('opt.searchTitleOnly', true ); IPSSearchRegistry::set('display.onlyTitles' , true ); IPSSearchRegistry::set('opt.noPostPreview' , false ); break; case 'content': IPSSearchRegistry::set('opt.searchTitleOnly', false ); IPSSearchRegistry::set('display.onlyTitles' , false ); IPSSearchRegistry::set('opt.noPostPreview' , false ); 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' ); /* Ensure we limit by date */ $this->settings['search_ucontent_days'] = ( $this->settings['search_ucontent_days'] ) ? $this->settings['search_ucontent_days'] : 365; /* Get list of good forum IDs */ $forumIdsOk = $this->registry->class_forums->fetchSearchableForumIds( $this->memberData['member_id'] ); $forumIdsOk = ( count( $forumIdsOk ) ) ? $forumIdsOk : array( 0 => 0 ); $topic_where[] = "t.forum_id IN (" . implode( ",", $forumIdsOk ) . ")"; if ( IPSSearchRegistry::get('in.userMode') != 'title' ) { $where[] = "p.author_id=" . intval( $member['member_id'] ); } if ( $this->settings['search_ucontent_days'] ) { if ( IPSSearchRegistry::get('in.userMode') != 'title' ) { $where[] = "p.post_date > " . ( time() - ( 86400 * intval( $this->settings['search_ucontent_days'] ) ) ); } $topic_where[] = "t.start_date > " . ( time() - ( 86400 * intval( $this->settings['search_ucontent_days'] ) ) ); } /* Set up perms */ $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'] ) { $where[] = $this->registry->class_forums->fetchPostHiddenQuery(array('visible', 'hidden', 'sdeleted'), 'p.'); } else if ( $permissions['SoftDeleteContent'] AND $permissions['PostSoftDeleteSee'] ) { $where[] = $this->registry->class_forums->fetchPostHiddenQuery(array('visible', 'sdeleted'), 'p.'); } else if ( $permissions['canQueue'] ) { $where[] = $this->registry->class_forums->fetchPostHiddenQuery(array('visible', 'hidden'), 'p.'); } else { $where[] = $this->registry->class_forums->fetchPostHiddenQuery(array('visible' ), 'p.' ); } } if ( $permissions['TopicSoftDeleteSee'] AND $permissions['canQueue'] ) { $topic_where[] = $this->registry->class_forums->fetchTopicHiddenQuery(array('visible', 'hidden', 'sdeleted'), 't.' ); } else if ( $permissions['TopicSoftDeleteSee'] ) { $topic_where[] = $this->registry->class_forums->fetchTopicHiddenQuery(array('visible', 'sdeleted'), 't.' ); } else if ( $permissions['canQueue'] ) { $topic_where[] = $this->registry->class_forums->fetchTopicHiddenQuery(array('visible', 'hidden'), 't.' ); } else { $topic_where[] = $this->registry->class_forums->fetchTopicHiddenQuery(array('visible' ), 't.' ); } /* Manual fetch if user content all */ if ( IPSSearchRegistry::get('in.userMode') == 'all' ) { /* init */ $pids = array(); $this->DB->build( array( 'select' => 't.tid, t.last_post, t.topic_firstpost', 'from' => 'topics t', 'where' => implode( ' AND ', $topic_where ) . " AND t.starter_id=" . intval( $member['member_id'] ), 'order' => 't.last_post DESC', 'limit' => array(0, 1000 ) ) ); $this->DB->execute(); while( $t = $this->DB->fetch() ) { $pids[ $t['tid'] ] = $t['last_post']; } $where = ( array_merge( (array) $where, (array) $topic_where ) ); $where = implode( " AND ", $where ); /* Now for posts */ $this->DB->build( array( 'select' => 'p.pid', 'from' => array('posts' => 'p' ), 'where' => $where, 'add_join' => array( array( 'select' => 't.tid, t.last_post, t.topic_firstpost', 'from' => array( 'topics' => 't' ), 'where' => 'p.topic_id=t.tid', 'type' => 'left' ) ), 'order' => 'p.pid DESC', 'limit' => array( 0, 1000 ) ) ); $this->DB->execute(); while( $t = $this->DB->fetch() ) { $pids[ $t['tid'] ] = $t['last_post']; } $count = array( 'count' => count( $pids ) ); if ( $count['count'] ) { arsort( $pids, SORT_NUMERIC ); $tids = array_slice( array_keys( $pids ), $start, $perPage ); } } else if ( IPSSearchRegistry::get('in.userMode') == 'title' ) { $topic_where[] = "t.starter_id=" . intval( $member['member_id'] ); $where = ( array_merge( (array) $where, (array) $topic_where ) ); $where = implode( " AND ", $where ); /* Fetch the count */ $count = $this->DB->buildAndFetch( array( 'select' => 'COUNT(tid) as count', 'from' => 'topics t', 'where' => $where ) ); /* Fetch the count */ if ( $count['count'] ) { $this->DB->build( array( 'select' => 'tid', 'from' => 'topics t', 'where' => $where, 'order' => 't.tid DESC', 'limit' => array( $start, $perPage ) ) ); $inner = $this->DB->execute(); while( $row = $this->DB->fetch( $inner ) ) { $tids[ $row['tid'] ] = $row['tid']; } } } else { $where = ( array_merge( (array) $where, (array) $topic_where ) ); $where = implode( " AND ", $where ); /* Fetch the count */ $count = $this->DB->buildAndFetch( array( 'select' => 'COUNT(tid) as count', 'from' => array('topics' => 't' ), 'where' => $where, 'add_join' => array( array( 'from' => array( 'posts' => 'p' ), 'where' => 'p.topic_id=t.tid', 'type' => 'left' ) ) ) ); /* Fetch the count */ if ( $count['count'] ) { $this->DB->build( array( 'select' => 'tid', 'from' => array('topics' => 't' ), 'where' => $where, 'add_join' => array( array( 'select' => 'p.pid', 'from' => array( 'posts' => 'p' ), 'where' => 'p.topic_id=t.tid', 'type' => 'left' ) ), 'order' => 't.last_post DESC', 'limit' => array( $start, $perPage ) ) ); $inner = $this->DB->execute(); while( $row = $this->DB->fetch( $inner ) ) { $tids[ $row['pid'] ] = $row['pid']; } } } /* Fix to 1000 results max */ $count['count'] = ( $count['count'] > 1000 ) ? 1000 : $count['count']; /* Return it */ return array( 'count' => $count['count'], 'resultSet' => $tids ); } /** * Perform the viewNewContent search * Forum Version * Populates $this->_count and $this->_results * * @return nothin' */ public function viewNewContent() { $rtids = array(); $tids = $this->registry->getClass('classItemMarking')->fetchCookieData( 'forums', 'items' ); $oldStamp = $this->registry->getClass('classItemMarking')->fetchOldestUnreadTimestamp( array(), 'forums' ); $check = IPS_UNIX_TIME_NOW - ( 86400 * 90 ); $forumIdsOk = array(); /* Loop through the forums and build a list of forums we're allowed access to */ $bvnp = explode( ',', $this->settings['vnp_block_forums'] ); $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' ); IPSSearchRegistry::set('opt.searchTitleOnly' , true ); IPSSearchRegistry::set('display.onlyTitles' , true ); IPSSearchRegistry::set('opt.noPostPreview' , true ); 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; } /* Get list of good forum IDs */ $_forumIdsOk = $this->registry->class_forums->fetchSearchableForumIds( $this->memberData['member_id'], $bvnp ); if ( ! $this->memberData['bw_vnc_type'] ) { $oldStamp = IPSLib::fetchHighestNumber( array( intval( $this->memberData['_cache']['gb_mark__forums'] ), intval( $this->memberData['last_visit'] ) ) ); $where[] = "last_post > " . $oldStamp; $forumIdsOk = $_forumIdsOk; } else { foreach( $_forumIdsOk as $id ) { $lMarked = $this->registry->getClass('classItemMarking')->fetchTimeLastMarked( array( 'forumID' => $id ), 'forums' ); $fData = $this->registry->getClass('class_forums')->forumsFetchData( $id ); if ( $fData['last_post'] > $lMarked ) { /* Add to tids */ $_tids = $this->registry->getClass('classItemMarking')->fetchReadIds( array( 'forumID' => $id ), 'forums', false ); if ( is_array( $_tids ) ) { foreach( $_tids as $k => $v ) { $tids[ $k ] = $v; } } $forumIdsOk[ $id ] = $id; } } /* If no forums, we're done */ if ( ! count( $forumIdsOk ) ) { /* Return it */ return array( 'count' => 0, 'resultSet' => array() ); } /* Try and limit the TIDS */ if ( is_array( $tids ) AND count( $tids ) ) { if ( count( $tids ) > 300 ) { /* Sort by last read date */ arsort( $tids, SORT_NUMERIC ); $tids = array_slice( $tids, 0, 300 ); } $this->DB->build( array( 'select' => 'tid, last_post', 'from' => 'topics', 'where' => "tid IN (" . implode( ",", array_keys( $tids ) ) . ')' ) ); $this->DB->execute(); while( $row = $this->DB->fetch() ) { /* Posted in since last read? */ if ( $row['last_post'] > $tids[ $row['tid'] ] ) { unset( $tids[ $row['tid'] ] ); } } if ( count( $tids ) ) { $tids = array_keys( $tids ); } } /* Based on oldest timestamp */ $where[] = "last_post > " . $oldStamp; /* Set read tids */ if ( count( $tids ) ) { $where[] = "tid NOT IN (" . implode( ",", $tids ) . ')'; } } $forumIdsOk = ( count( $forumIdsOk ) ) ? $forumIdsOk : array( 0 => 0 ); $where[] = "forum_id IN (" . implode( ",", $forumIdsOk ) . ")"; /* Add in last bits */ $where[] = "state != 'link'"; /* Set up perms */ $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'] ) { $this->DB->build( array( 'select' => 'tid', 'from' => 'topics', 'where' => $where, 'order' => 'last_post DESC', 'limit' => array( $start, $perPage ) ) ); $inner = $this->DB->execute(); while( $row = $this->DB->fetch( $inner ) ) { $rtids[ $row['tid'] ] = $row['tid']; } } /* Set up some vars */ IPSSearchRegistry::set('set.resultCutToDate', $oldStamp ); /* Return it */ return array( 'count' => $count['count'], 'resultSet' => $rtids ); } /** * Perform the search * Populates $this->_count and $this->_results * * @return nothin' */ public function viewActiveContent() { $seconds = IPSSearchRegistry::get('in.period_in_seconds'); /* Loop through the forums and build a list of forums we're allowed access to */ $where = array(); $forumIdsOk = array(); $bvnp = explode( ',', $this->settings['vnp_block_forums'] ); $start = IPSSearchRegistry::get('in.start'); $perPage = IPSSearchRegistry::get('opt.search_per_page'); $tids = array(); /* Get list of good forum IDs */ $forumIdsOk = $this->registry->class_forums->fetchSearchableForumIds( $this->memberData['member_id'], $bvnp ); $forumIdsOk = ( count( $forumIdsOk ) ) ? $forumIdsOk : array( 0 => 0 ); $where[] = "t.forum_id IN (" . implode( ",", $forumIdsOk ) . ")"; /* Generate last post times */ $where[] = "t.last_post > " . intval( time() - $seconds ); /* Set up perms */ $permissions['TopicSoftDeleteSee'] = $this->registry->getClass('class_forums')->canSeeSoftDeletedTopics( 0 ); $permissions['canQueue'] = $this->registry->getClass('class_forums')->canQueuePosts( 0 ); /* Add in last bits */ $where[] = "t.state != 'link'"; if ( $permissions['TopicSoftDeleteSee'] AND $permissions['canQueue'] ) { $where[] = $this->registry->class_forums->fetchTopicHiddenQuery(array('visible', 'hidden', 'sdeleted'), 't.'); } else if ( $permissions['TopicSoftDeleteSee'] ) { $where[] = $this->registry->class_forums->fetchTopicHiddenQuery(array('visible', 'sdeleted'), 't.'); } else if ( $permissions['canQueue'] ) { $where[] = $this->registry->class_forums->fetchTopicHiddenQuery(array('visible', 'hidden'), 't.'); } else { $where[] = $this->registry->class_forums->fetchTopicHiddenQuery(array('visible' ), 't.' ); } $where = implode( " AND ", $where ); /* Fetch the count */ $count = $this->DB->buildAndFetch( array( 'select' => 'COUNT(tid) as count', 'from' => array( 'topics' => 't' ), 'where' => $where ) ); /* Grab */ $this->DB->build( array( 'select' => 'tid', 'from' => array( 'topics' => 't' ), 'where' => $where, 'order' => 'last_post DESC', 'limit' => array( $start, $perPage ) ) ); $this->DB->execute(); while( $row = $this->DB->fetch() ) { $tids[ $row['tid'] ] = $row['tid']; } /* Return it */ return array( 'count' => $count['count'], 'resultSet' => $tids ); } /** * Builds the where portion of a search string * * @param string $search_term The string to use in the search * @param bool $content_title_only Search only title records * @param string $order Order by data * @param bool $onlyPosts Enforce posts only * @param bool $noForums Don't check forums that posts are in * @return string */ private function _buildWhereStatement( $search_term, $content_title_only=false, $order='', $onlyPosts=null, $noForums=false ) { /* INI */ $where_clause = array(); $onlyPosts = ( $onlyPosts !== null ) ? $onlyPosts : IPSSearchRegistry::get('opt.onlySearchPosts'); $sort_by = IPSSearchRegistry::get('in.search_sort_by'); $sort_order = IPSSearchRegistry::get('in.search_sort_order'); $sortKey = ''; $sortType = ''; $cType = IPSSearchRegistry::get('contextual.type'); $cId = IPSSearchRegistry::get('contextual.id' ); /* Loop through the forums and build a list of forums we're allowed access to */ $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) ) { $allowTrashCan = ( $cType == 'forum' ) ? true : false; /* Get list of good forum IDs */ $forumIdsOk = $this->registry->class_forums->fetchSearchableForumIds( null, array(), $allowTrashCan ); } /* Add allowed forums */ if ( $noForums !== true ) { $forumIdsOk = ( count( $forumIdsOk ) ) ? $forumIdsOk : array( 0 => 0 ); /* Contextual */ if ( $cType == 'forum' AND $cId AND in_array( $cId, $forumIdsOk ) ) { $where_clause[] = "t.forum_id=" . $cId; } else { $where_clause[] = "t.forum_id IN (" . implode( ",", $forumIdsOk ) . ")"; } } /* Topic contextual */ if ( $cType == 'topic' AND $cId ) { $where_clause[] = "t.tid=" . $cId; } /* Exclude some items */ $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 ); if ( ! $content_title_only ) { if ( $permissions['SoftDeleteContent'] AND $permissions['PostSoftDeleteSee'] AND $permissions['canQueue'] ) { $where_clause[] = $this->registry->class_forums->fetchPostHiddenQuery(array('visible', 'hidden', 'sdeleted'), 'p.'); } else if ( $permissions['SoftDeleteContent'] AND $permissions['PostSoftDeleteSee'] ) { $where_clause[] = $this->registry->class_forums->fetchPostHiddenQuery(array('visible', 'sdeleted'), 'p.'); } else if ( $permissions['canQueue'] ) { $where_clause[] = $this->registry->class_forums->fetchPostHiddenQuery(array('visible', 'hidden'), 'p.'); } else { $where_clause[] = $this->registry->class_forums->fetchPostHiddenQuery(array('visible' ), 'p.' ); } } if ( $permissions['SoftDeleteContent'] AND $permissions['TopicSoftDeleteSee'] AND $permissions['canQueue'] ) { $where_clause[] = $this->registry->class_forums->fetchTopicHiddenQuery(array('visible', 'hidden', 'sdeleted'), 't.'); } else if ( $permissions['SoftDeleteContent'] AND $permissions['TopicSoftDeleteSee'] ) { $where_clause[] = $this->registry->class_forums->fetchTopicHiddenQuery(array('visible', 'sdeleted'), 't.'); } else if ( $permissions['canQueue'] ) { $where_clause[] = $this->registry->class_forums->fetchTopicHiddenQuery(array('visible', 'hidden'), 't.'); } else { $where_clause[] = $this->registry->class_forums->fetchTopicHiddenQuery(array('visible' ), 't.' ); } if( $search_term ) { $search_term = str_replace( '"', '"', $search_term ); if( $content_title_only ) { $where_clause[] = $this->DB->buildSearchStatement( 't.title', $search_term, true, false, ipsRegistry::$settings['use_fulltext'] ); } else { if ( $onlyPosts ) { $where_clause[] = $this->DB->buildSearchStatement( 'p.post', $search_term, true, false, ipsRegistry::$settings['use_fulltext'] ); } else { /* Sorting */ switch( $sort_by ) { default: case 'date': $sortKey = 'last_post'; $sortType = 'numerical'; break; case 'title': $sortKey = 'title'; $sortType = 'string'; break; case 'posts': $sortKey = 'posts'; $sortType = 'numerical'; break; case 'views': $sortKey = 'views'; $sortType = 'numerical'; break; } /* Set vars */ IPSSearch::$ask = $sortKey; IPSSearch::$aso = strtolower( $sort_order ); IPSSearch::$ast = $sortType; /* Find topic ids that match */ $tids = array( 0 => 0 ); $pids = array( 0 => 0 ); $this->DB->build( array( 'select' => "t.tid, t.last_post, t.forum_id", 'from' => 'topics t', 'where' => str_replace( 'p.author_id', 't.starter_id', $this->_buildWhereStatement( $search_term, true, $order, null ) ), 'order' => 't.' . $sortKey . ' ' . $sort_order, 'limit' => array(0, IPSSearchRegistry::get('set.hardLimit')) ) ); $i = $this->DB->execute(); /* Grab the results */ while( $row = $this->DB->fetch( $i ) ) { $_rows[ $row['tid'] ] = $row; } /* Sort */ if ( count( $_rows ) ) { usort( $_rows, array("IPSSearch", "usort") ); foreach( $_rows as $id => $row ) { $tids[] = $row['tid']; } } /* Now get the Pids */ if ( count( $tids ) > 1 ) { $this->DB->build( array('select' => 'pid', 'from' => 'posts', 'where' => 'topic_id IN ('. implode( ',', $tids ) . ') AND new_topic=1' ) ); $i = $this->DB->execute(); while( $row = $this->DB->fetch() ) { $pids[ $row['pid'] ] = $row['pid']; } } /* Set vars */ IPSSearch::$ask = ( $sortKey == 'last_post' ) ? 'post_date' : $sortKey; IPSSearch::$aso = strtolower( $sort_order ); IPSSearch::$ast = $sortType; $this->DB->build( array( 'select' => "p.pid, p.queued", 'from' => array( 'posts' => 'p' ), 'where' => $this->_buildWhereStatement( $search_term, false, $order, true ), 'order' => IPSSearch::$ask . ' ' . IPSSearch::$aso, 'group' => 'p.topic_id', 'limit' => array(0, IPSSearchRegistry::get('set.hardLimit')), 'add_join' => array( array( 'select' => 't.approved, t.forum_id', 'from' => array( 'topics' => 't' ), 'where' => 'p.topic_id=t.tid', 'type' => 'left' ) ) ) ); $i = $this->DB->execute(); /* Grab the results */ while( $row = $this->DB->fetch( $i ) ) { $_prows[ $row['pid'] ] = $row; } /* Sort */ if ( count( $_prows ) ) { usort( $_prows, array("IPSSearch", "usort") ); foreach( $_prows as $id => $row ) { $pids[ $row['pid'] ] = $row['pid']; } } $where_clause[] = '( p.pid IN (' . implode( ',', $pids ) .') )'; } } } /* No moved topic links */ $where_clause[] = "t.state != 'link'"; /* Date Restrict */ if( $this->search_begin_timestamp && $this->search_end_timestamp ) { $where_clause[] = $this->DB->buildBetween( $content_title_only ? "t.last_post" : "p.post_date", $this->search_begin_timestamp, $this->search_end_timestamp ); } else { if( $this->search_begin_timestamp ) { $where_clause[] = $content_title_only ? "t.last_post > {$this->search_begin_timestamp}" : "p.post_date > {$this->search_begin_timestamp}"; } if( $this->search_end_timestamp ) { $where_clause[] = $content_title_only ? "t.last_post < {$this->search_end_timestamp}" : "p.post_date < {$this->search_end_timestamp}"; } } /* Add in AND where conditions */ if( isset( $this->whereConditions['AND'] ) && count( $this->whereConditions['AND'] ) ) { $where_clause = array_merge( $where_clause, $this->whereConditions['AND'] ); } /* ADD in OR where conditions */ if( isset( $this->whereConditions['OR'] ) && count( $this->whereConditions['OR'] ) ) { $where_clause[] = '( ' . implode( ' OR ', $this->whereConditions['OR'] ) . ' )'; } /* Build and return the string */ return implode( " AND ", $where_clause ); } /** * Remap standard columns (Apps can override ) * * @param string $column sql table column for this condition * @return string column * @return void */ public function remapColumn( $column ) { $column = $column == 'member_id' ? ( IPSSearchRegistry::get('opt.searchTitleOnly') ? 't.starter_id' : 'p.author_id' ) : $column; $column = $column == 'content_title' ? 't.title' : $column; $column = $column == 'type_id' ? 't.forum_id' : $column; return $column; } /** * Returns an array used in the searchplugin's setCondition method * * @param array $data Array of forums to view * @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 ); IPSSearchRegistry::set( 'opt.onlySearchPosts', false ); /* Make default search type topics */ 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 ); } /* CONTENT ONLY */ if ( $field == 'contentOnly' AND $_data['contentOnly'] == 1 ) { IPSSearchRegistry::set( 'opt.onlySearchPosts', true ); } /* POST COUNT */ if ( $field == 'pCount' AND intval( $_data['pCount'] ) > 0 ) { $return[] = array( 'column' => 't.posts', 'operator' => '>=', 'value' => intval( $_data['pCount'] ) ); } /* TOPIC VIEWS */ if ( $field == 'pViews' AND intval( $_data['pViews'] ) > 0 ) { $return[] = array( 'column' => 't.views', 'operator' => '>=', 'value' => intval( $_data['pViews'] ) ); } } return $return; } else { return ''; } } }