Version 3.1.4

This commit is contained in:
Neo committed 2025-12-19 00:32:22 -08:00
1 parent 1d4720f3e2
commit ae5c01cc78
2563 files changed
+283048 -240689

No files matched your search

@@ -0,0 +1,700 @@
<?php
/**
* <pre>
* Invision Power Services
* IP.Board v3.1.4
* Global Search
* Last Updated: $Date: 2010-02-22 17:06:11 +0000 (Mon, 22 Feb 2010) $
* </pre>
*
* @author $Author: matt $
* @copyright (c) 2001 - 2009 Invision Power Services, Inc.
* @license http://www.invisionpower.com/community/board/license.html
* @package IP.Board
* @subpackage Core
* @link http://www.invisionpower.com
* @version $Rev: 5859 $
*/
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();
}
/**
* Slightly nice way of dumping vars and stuff globally
* Yeah, it's an evil global variable, but it's FANCY
*/
class IPSSearchRegistry {
/**
* Registry vars
* @var array
*/
static private $_vars = array();
/**
* Set var
* @param mixed Key
* @param mixed value
*/
static public function set( $k, $v )
{
if ( $k and isset( $v ) )
{
self::$_vars[ $k ] = $v;
}
}
/**
* Get var
* @param mixed
*/
static public function get( $k )
{
if ( isset( self::$_vars[ $k ] ) )
{
return self::$_vars[ $k ];
}
return null;
}
}
/**
* Ties in:
* extensions/search/form.php
* extensions/search/{engine}.php
* extensions/search/format.php
*/
class IPSSearch
{
/**#@+
* Registry Object Shortcuts
*
* @var object
*/
protected $registry;
protected $DB;
protected $settings;
protected $request;
protected $lang;
protected $member;
protected $cache;
/**#@-*/
/**
* Plug in for search
*
* @var object
*/
private $SEARCH;
/**
* Plug in for formatting results
*
* @var object
*/
private $FORMAT;
/**
* App
*
* @var string
*/
private $_app;
/**
* Engine
*
* @var string
*/
private $_engine;
/**
* Result count
*
* @param int
*/
private $_count;
/**
* Result array
*
* @param array
*/
private $_results;
static public $aso;
static public $ask;
static public $ast;
/**
* Setup registry objects
*
* @param object ipsRegistry $registry
* @return void
*/
public function __construct( ipsRegistry $registry, $engine, $app )
{
/* Make object */
$this->registry = $registry;
$this->DB = $this->registry->DB();
$this->settings =& $this->registry->fetchSettings();
$this->request =& $this->registry->fetchRequest();
$this->lang = $this->registry->getClass('class_localization');
$this->member = $this->registry->member();
$this->memberData =& $this->registry->member()->fetchMemberData();
$this->cache = $this->registry->cache();
$this->caches =& $this->registry->cache()->fetchCaches();
/* Set engine */
$this->_engine = strtolower( IPSText::alphanumericalClean( $engine ) );
/* Set app */
$this->_app = IPSText::alphanumericalClean( $app );
/* Quick check */
if ( ! file_exists( IPS_ROOT_PATH . 'sources/classes/search/engines/' . $this->_engine . '.php' ) )
{
/* Try SQL */
if ( ! $this->_engine != 'sql' )
{
$this->_engine = 'sql';
if ( ! file_exists( IPS_ROOT_PATH . 'sources/classes/search/engines/' . $this->_engine . '.php' ) )
{
throw new Exception( "NO_SUCH_ENGINE" );
}
}
else
{
throw new Exception( "NO_SUCH_ENGINE" );
}
}
if ( ! isset( ipsRegistry::$applications[ $this->_app ] ) )
{
throw new Exception( "NO_SUCH_APP" );
}
/* Set in registry */
IPSSearchRegistry::set( 'global.engine', $this->_engine );
IPSSearchRegistry::set( 'global.app' , $this->_app );
/* Load up the relevant engines */
$_className = 'search_' . $this->_engine;
require_once( IPS_ROOT_PATH . 'sources/classes/search/format.php' );
/* Got an app specific file? Lets hope so */
if ( file_exists( IPSLib::getAppDir( $this->_app ) . '/extensions/search/format.php' ) )
{
/* We may not have sphinx specific stuff, so... */
if ( ! file_exists( IPSLib::getAppDir( $this->_app ) . '/extensions/search/engines/' . $this->_engine . '.php' ) )
{
$this->_engine = 'sql';
if ( ! file_exists( IPSLib::getAppDir( $this->_app ) . '/extensions/search/engines/' . $this->_engine . '.php' ) )
{
throw new Exception( "NO_SUCH_APP_ENGINE" );
}
}
require_once( IPS_ROOT_PATH . 'sources/classes/search/engines/' . $this->_engine . '.php' );
require_once( IPSLib::getAppDir( $this->_app ) . '/extensions/search/engines/' . $this->_engine . '.php' );
/* SEARCH classname */
$_className = 'search_engine_' . $this->_app;
$this->SEARCH = new $_className( $registry );
/* FORMAT file */
require_once( IPSLib::getAppDir( $this->_app ) . '/extensions/search/format.php' );
/* FORMAT classname */
$_className = 'search_format_' . $this->_app;
$this->FORMAT = new $_className( $registry );
/* Grab config */
$CONFIG = array();
require( IPSLib::getAppDir( $this->_app ) . '/extensions/search/config.php' );
if ( is_array( $CONFIG ) && count( $CONFIG ) )
{
foreach( $CONFIG as $k => $v )
{
IPSSearchRegistry::set( 'config.' . $k, $v );
}
}
}
else
{
throw new Exception( "NO_SUCH_APP_ENGINE" );
}
/* Multi content types */
if ( IPSSearchRegistry::get( 'config.contentTypes' ) )
{
$c = IPSSearchRegistry::get( 'config.contentTypes' );
if ( is_array( $c ) AND count( $c ) )
{
/* Set up default content type if supported */
IPSSearchRegistry::set( $this->_app . '.searchInKey' , $c[0] );
/* Filter specific search */
if ( isset( $this->request['search_app_filters'][ $this->_app ]['searchInKey'] ) )
{
IPSSearchRegistry::set( $this->_app . '.searchInKey', $this->request['search_app_filters'][ $this->_app ]['searchInKey'] );
}
}
}
}
/**
* Magic __call methods
* Aka too lazy to create a proper function
*/
public function __call( $funcName, $args )
{
/* Output format stuff.. */
switch ( $funcName )
{
case 'isBoolean':
return $this->SEARCH->isBoolean();
break;
case 'formatSearchTerm':
return $this->SEARCH->formatSearchTerm( $args[0] );
break;
case 'getResultCount':
return $this->_count;
break;
case 'getResultSet':
return $this->_results;
break;
case 'fetchTemplates':
return $this->FORMAT->fetchTemplates();
break;
case 'fetchSortDropDown':
return $this->SEARCH->fetchSortDropDown();
break;
}
}
/**
* Generic: Return sort drop down
*
* @param string App
* @return array
*/
public function fetchSortDropDown( $app='' )
{
$app = ( $app ) ? $app : $this->_app;
/* results page? */
$filter = ( ! IPSSearchRegistry::get('view.search_form') AND IPSSearchRegistry::get( $app . '.searchInKey' ) ) ? IPSSearchRegistry::get( $app . '.searchInKey' ) : '';
if ( file_exists( IPSLib::getAppDir( $app ) . '/extensions/search/form.php' ) )
{
require_once( IPSLib::getAppDir( $app ) . '/extensions/search/form.php' );
$_class = 'search_form_' . $app;
if ( class_exists( $_class ) )
{
$_obj = new $_class();
$_dd = $_obj->fetchSortDropDown();
if ( $filter )
{
return $_dd[ $filter ];
}
else
{
return $_dd;
}
}
}
return array( 'date' => $this->lang->words['s_search_type_0'] );
}
/**
* Generic: Return sort in
*
* @param string [App]
* @return array
*/
public function fetchSortIn( $app='' )
{
$app = ( $app ) ? $app : $this->_app;
if ( file_exists( IPSLib::getAppDir( $app ) . '/extensions/search/form.php' ) )
{
require_once( IPSLib::getAppDir( $app ) . '/extensions/search/form.php' );
$_class = 'search_form_' . $app;
if ( class_exists( $_class ) )
{
$_obj = new $_class();
if ( method_exists( $_obj, 'fetchSortIn' ) )
{
return $_obj->fetchSortIn();
}
}
}
return FALSE;
}
/**
* Returns boxes for the search form
*
* @param boolean Grab all apps or just the current one
* @return array
*/
public function getHtml( $allApps = TRUE )
{
/* INIT */
$filtersHtml = '';
/* Loop through apps */
foreach( ipsRegistry::$applications as $app )
{
/* Not all? */
if ( ! $allApps and $app['app_directory'] != $this->_app )
{
continue;
}
if( IPSLib::appisSearchable( $app['app_directory'] ) )
{
/* got custom filter? */
if ( file_exists( IPSLib::getAppDir( $app['app_directory'] ) . '/extensions/search/form.php' ) )
{
require_once( IPSLib::getAppDir( $app['app_directory'] ) . '/extensions/search/form.php' );
$_class = 'search_form_' . $app['app_directory'];
if ( class_exists( $_class ) and method_exists( $_class, 'getHtml' ) )
{
$_obj = new $_class();
$filtersHtml[ $app['app_directory'] ] = $_obj->getHtml();
}
else
{
$filtersHtml[ $app['app_directory'] ] = array( 'title' => IPSLib::getAppTitle( $app['app_directory'] ), 'html' => '' );
}
}
else
{
$filtersHtml[ $app['app_directory'] ] = array( 'title' => IPSLib::getAppTitle( $app['app_directory'] ), 'html' => '' );
}
$filtersHtml[ $app['app_directory'] ]['sortDropIn'] = $this->fetchSortIn( $app['app_directory'] );
$filtersHtml[ $app['app_directory'] ]['sortDropDown'] = $this->fetchSortDropDown( $app['app_directory'] );
}
}
return $filtersHtml;
}
/**
* Perform the search
* Populates $this->_count and $this->_results
*
* @return nothin'
*/
public function search()
{
$APP = IPSSearchRegistry::get('in.search_app');
$filterData = $this->request['search_app_filters'][ $APP ];
/* Check for an author filter */
if ( IPSSearchRegistry::get('in.search_author') )
{
/* Query the member id */
$mem = $this->DB->buildAndFetch( array( 'select' => 'member_id',
'from' => 'members',
'where' => "members_display_name='" . $this->DB->addSlashes( IPSSearchRegistry::get('in.search_author') ) . "'" ) );
IPSSearchRegistry::set('opt.searchAuthor', true );
/* Add the condition to our search */
$this->SEARCH->setCondition( 'member_id', '=', $mem['member_id'] ? $mem['member_id'] : -1 );
}
/* Check for application specific filters - just need to do active app here */
$filterData = $this->SEARCH->buildFilterSQL( $filterData );
if( $filterData )
{
if ( isset( $filterData[0] ) )
{
foreach( $filterData as $_data )
{
$this->SEARCH->setCondition( $_data['column'], $_data['operator'], $_data['value'], 'AND' );
}
}
else
{
$this->SEARCH->setCondition( $filterData['column'], $filterData['operator'], $filterData['value'], 'OR' );
}
}
/* Check Date Range */
if( IPSSearchRegistry::get('in.search_date_start') || IPSSearchRegistry::get('in.search_date_end') )
{
/* Start Range Date */
$search_date_start = 0;
if( IPSSearchRegistry::get('in.search_date_start') )
{
$search_date_start = strtotime( IPSSearchRegistry::get('in.search_date_start') );
/* Correct for timezone...hopefully */
$search_date_start += abs( $this->registry->class_localization->getTimeOffset() );
}
/* End Range Date */
$search_date_end = 0;
if( IPSSearchRegistry::get('in.search_date_end') AND IPSSearchRegistry::get('in.search_date_end') != 'now' )
{
$search_date_end = strtotime( IPSSearchRegistry::get('in.search_date_end') );
/* Correct for timezone...hopefully */
$search_date_end += abs( $this->registry->class_localization->getTimeOffset() );
}
/* If the times are exactly equaly, we're going to assume they are trying to search all posts from one day */
if( ( $search_date_start && $search_date_end ) && $search_date_start == $search_date_end )
{
$search_date_end += 86400;
}
$this->SEARCH->setDateRange( $search_date_start, $search_date_end );
}
/* Init session */
$processId = $this->_startSession();
/* Run the search */
$results = $this->SEARCH->search();
/* Set data */
$this->_count = intval( $results['count'] );
$this->_results = $results['resultSet'];
/* Now format results */
if ( count( $this->_results ) )
{
$this->_results = $this->FORMAT->processResults( $this->_results );
/* Now generate HTML */
$this->_results = $this->FORMAT->parseAndFetchHtmlBlocks( $this->_results );
}
/* Kill session */
$this->_endSession( $processId );
}
/**
* Perform the search
* Populates $this->_count and $this->_results
*
* @return nothin'
*/
public function viewNewContent()
{
IPSSearchRegistry::set('display.onlyTitles', true);
/* Hard fix mobile app users to VNC based on unread content */
if ( $this->member->isMobileApp )
{
$this->memberData['bw_vnc_type'] = 1;
}
/* Run the search */
$results = $this->SEARCH->viewNewContent();
/* Set data */
$this->_count = intval( $results['count'] );
$this->_results = $results['resultSet'];
/* Now format results */
if ( count( $this->_results ) )
{
$this->_results = $this->FORMAT->processResults( $this->_results );
/* Now generate HTML */
$this->_results = $this->FORMAT->parseAndFetchHtmlBlocks( $this->_results );
}
}
/**
* Perform the search
* Populates $this->_count and $this->_results
*
* @return nothin'
*/
public function viewUserContent( $member )
{
/* Run the search */
$results = $this->SEARCH->viewUserContent( $member );
/* Set data */
$this->_count = intval( $results['count'] );
$this->_results = $results['resultSet'];
/* Now format results */
if ( count( $this->_results ) )
{
$this->_results = $this->FORMAT->processResults( $this->_results );
/* Now generate HTML */
$this->_results = $this->FORMAT->parseAndFetchHtmlBlocks( $this->_results );
}
}
/**
* Perform the search
*
* @return nothin'
*/
public function viewActiveContent()
{
/* Bit 'o set up */
IPSSearchRegistry::set('opt.searchTitleOnly', IPSSearchRegistry::get('in.view_by_title') );
IPSSearchRegistry::set('display.onlyTitles', true);
IPSSearchRegistry::set('opt.searchTitleOnly', true);
/* Do we have a period? */
switch( IPSSearchRegistry::get('in.period') )
{
case 'today':
default:
$date = 86400; // 24 hours
break;
case 'week':
$date = 604800; // 1 week
break;
case 'weeks':
$date = 1209600; // 2 weeks
break;
case 'month':
$date = 2592000; // 30 days
break;
case 'months':
$date = 15552000; // 6 months
break;
case 'year':
$date = 31536000; // 365 days
break;
}
/* Set date up */
IPSSearchRegistry::set('in.period_in_seconds', $date );
/* Run the search */
$results = $this->SEARCH->viewActiveContent();
/* Set data */
$this->_count = intval( $results['count'] );
$this->_results = $results['resultSet'];
/* Now format results */
if ( count( $this->_results ) )
{
$this->_results = $this->FORMAT->processResults( $this->_results );
/* Now generate HTML */
$this->_results = $this->FORMAT->parseAndFetchHtmlBlocks( $this->_results );
}
}
/**
* Flag a search session
*
* @return int Process ID
*/
private function _startSession()
{
/**
* If we've already run a search and it's not clear, kill it now
*/
if( $this->member->sessionClass()->session_data['search_thread_id'] )
{
$this->DB->return_die = true;
$this->DB->kill( $this->member->sessionClass()->session_data['search_thread_id'] );
$this->DB->return_die = false;
}
/**
* Store the process id
*/
$processId = $this->DB->getThreadId();
if ( $processId )
{
$this->DB->update( 'sessions', array( 'search_thread_id' => $processId, 'search_thread_time' => time() ), "id='" . $this->member->session_id . "'" );
}
return $processId;
}
/**
* End a search session
*
* @return void
*/
private function _endSession( $processId )
{
if ( $processId )
{
$this->DB->update( 'sessions', array( 'search_thread_id' => 0, 'search_thread_time' => 0 ), "id='" . $this->member->session_id . "'" );
}
}
/**
* Custom sort function to avoid filesorts in the system
*
* @param array A
* @param array B
* @return boolean
*/
static function usort( $a, $b )
{
switch ( self::$ast )
{
case 'numeric':
case 'numerical':
if ( self::$aso == 'asc' )
{
return ($a[ self::$ask ] > $b[ self::$ask ]) ? +1 : -1;
}
else
{
return ($a[ self::$ask ] < $b[ self::$ask ]) ? +1 : -1;
}
break;
case 'string':
if ( self::$aso == 'asc' )
{
return strcasecmp($a[ self::$ask ], $b[ self::$ask ]) <= 0 ? -1 : +1;
}
else
{
return strcasecmp($a[ self::$ask ], $b[ self::$ask ]) <= 0 ? +1 : -1;
}
break;
}
}
}
@@ -0,0 +1,10 @@
<html>
<head><title>IP.Board - Bulletin Board System</title></head>
<body>
<h1>403: IP.Board -&gt; Forbidden</h1>
<hr>
You have reached this page in error, please use your back button to return to the forum.
<hr>
<a href="http://www.invisionboard.com/">IP.Board</a>
</body>
</html>
@@ -0,0 +1,348 @@
<?php
/**
* <pre>
* Invision Power Services
* IP.Board v3.1.4
* Global Search
* Last Updated: $Date: 2010-02-19 01:29:54 +0000 (Fri, 19 Feb 2010) $
* </pre>
*
* @author $Author: josh $
* @copyright (c) 2001 - 2009 Invision Power Services, Inc.
* @license http://www.invisionpower.com/community/board/license.html
* @package IP.Board
* @subpackage Core
* @link http://www.invisionpower.com
* @version $Rev: 5855 $
*/
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
{
/**
* Date range restriction start
*
* @access protected
* @var integer
*/
protected $search_begin_timestamp = 0;
/**
* Date range restriction end
*
* @access protected
* @var integer
*/
protected $search_end_timestamp = 0;
/**
* Array of conditions for this search
*
* @access protected
* @var array
*/
protected $whereConditions = array();
/**
* Sphinx client object
*
* @access public
* @var object
*/
public $sphinxClient;
/**
* Setup registry objects
*
* @access public
* @param object ipsRegistry $registry
* @return void
*/
public function __construct( ipsRegistry $registry )
{
/* Make object */
$this->registry = $registry;
$this->DB = $this->registry->DB();
$this->settings =& $this->registry->fetchSettings();
$this->request =& $this->registry->fetchRequest();
$this->lang = $this->registry->getClass('class_localization');
$this->member = $this->registry->member();
$this->memberData =& $this->registry->member()->fetchMemberData();
$this->cache = $this->registry->cache();
$this->caches =& $this->registry->cache()->fetchCaches();
/* Do we have the sphinxes? */
if( ! file_exists( 'sphinxapi.php' ) )
{
$registry->output->showError( 'sphinx_api_missing', 10182 );
}
/* Load Sphinx */
require( 'sphinxapi.php' );
$this->sphinxClient = new SphinxClient();
$this->sphinxClient->SetServer( $this->settings['search_sphinx_server'], intval( $this->settings['search_sphinx_port'] ) );
$this->sphinxClient->SetMatchMode( SPH_MATCH_EXTENDED );
$this->sphinxClient->SetLimits( 0, 1000 );
}
/**
* Perform a search.
* Returns an array of a total count (total number of matches)
* and an array of IDs 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
*
* @access public
* @return array
*/
public function search()
{
/* Per app class handles this */
throw new Exception("NO_SEARCH_AVAILABLE");
}
/**
* Perform the viewNewContent search
* Generic version
* Populates $this->_count and $this->_results
*
* @access public
* @return nothin'
*/
public function viewNewContent()
{
$app = IPSSearchRegistry::get('in.search_app');
$lastActive = IPSLib::fetchHighestNumber( array( intval( $this->memberData['_cache']['gb_mark__' . $app] ), intval( $this->memberData['last_visit'] ) ) );
IPSSearchRegistry::set('in.search_sort_by' , 'date' );
IPSSearchRegistry::set('in.search_sort_order', 'desc' );
$this->setDateRange( $lastActive, time() );
/* Force title search only */
IPSSearchRegistry::set('opt.searchTitleOnly', true);
return $this->search();
}
/**
* Perform the search
* Populates $this->_count and $this->_results
*
* @access public
* @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' );
IPSSearchRegistry::set('opt.searchTitleOnly', IPSSearchRegistry::get('in.view_by_title') );
IPSSearchRegistry::set('display.onlyTitles' , IPSSearchRegistry::get('in.view_by_title') );
IPSSearchRegistry::set('opt.noPostPreview' , IPSSearchRegistry::get('in.view_by_title') );
/* Set the member_id */
$this->setCondition( 'member_id', '=', $member['member_id'] );
/* Cut by date for efficiency? */
if ( $this->settings['search_ucontent_days'] )
{
$begin = ( $member['last_post'] ? $member['last_post'] : time() ) - 86400 * intval( $this->settings['search_ucontent_days'] );
$this->setDateRange( $begin, time() );
}
return $this->search();
}
/**
* Perform the search
* Populates $this->_count and $this->_results
*
* @access public
* @return nothin'
*/
public function viewActiveContent()
{
$seconds = IPSSearchRegistry::get('in.period_in_seconds');
/* Set time stamp */
$this->setDateRange( time() - $seconds, time() );
return $this->search();
}
/**
* Can handle boolean searching
*
* @access public
* @return boolean
*/
public function isBoolean()
{
return TRUE;
}
/**
* Formats search term for SQL
*
* @access private
* @param string Raw IPB santized form input
* @return array array( 'search_term' => Safe string to use in SQL, 'removed' => array of removed search terms )
*/
public function formatSearchTerm( $search_term )
{
$isBoolean = $this->isBoolean();
$andor = isset( $this->request['andor_type'] ) ? $this->request['andor_type'] : $this->settings['s_andor_type'];
$removedTerms = array();
/* Fix up some sanitized HTML */
$search_term = str_replace( "&amp;" , '&' , IPSText::parseCleanValue( rawurldecode( $search_term ) ) );
$search_term = str_replace( "&quot;" , '"' , $search_term );
$search_term = IPSText::mbstrtolower( $search_term );
/* Check for disallowed search terms */
while( preg_match_all( "/(?:^|\s+)(img|quote|code|html|javascript|a href|color|span|div|border|style)(?:\s+|$)/", $search_term, $removed_search_terms ) )
{
$removedTerms[] = $removed_search_terms[0][0];
$search_term = preg_replace( "/(^|\s+)(?:img|quote|code|html|javascript|a href|color|span|div|border|style)(\s+|$)/", str_replace( " ", " ", "$1$2" ), $search_term );
}
/* Remove some formatting */
//$search_term = str_replace( array( '|', '\\', '/' ), '', $search_term );
// | is an OR operator for sphinx - don't want to block globally
$search_term = str_replace( array( '\\', '/' ), '', $search_term );
/* Sphinx chars are not allowed */
$search_term = str_replace( array( '.', ')', '(', '!', '@', '[', ']' ), '', $search_term );
if ( $andor == 'or' )
{
$search_term = preg_replace( "/\s+(?!-|~)/", " | ", $search_term );
}
return array( 'search_term' => $search_term, 'removed' => $removedTerms );
}
/**
* Restrict the date range that the search is performed on
*
* @access public
* @param int $begin Start timestamp
* @param int [$end] End timestamp
* @return void
*/
public function setDateRange( $begin, $end=0 )
{
$this->search_begin_timestamp = $begin;
$this->search_end_timestamp = $end;
}
/**
* Remap standard columns (Apps can override )
*
* @access public
* @param string $column sql table column for this condition
* @return string column
* @return void
*/
public function remapColumn( $column )
{
return $column;
}
/**
* mySQL function for adding special search conditions
*
* @access public
* @param string $column sql table column for this condition
* @param string $operator Operation to perform for this condition, ex: =, <>, IN, NOT IN
* @param mixed $value Value to check with
* @param string $comp Comparison type
* @return void
*/
public function setCondition( $column, $operator, $value, $comp='AND' )
{
/* This is restricted by the indexes searched */
if( $column == 'app' )
{
return;
}
$column = $this->remapColumn( $column );
if( !$column )
{
return;
}
/* Build the condition based on operator */
switch( strtoupper( $operator ) )
{
case 'IN':
$this->sphinxClient->setFilter( $column, explode( ',', $value ) );
break;
case 'NOT IN':
$this->sphinxClient->setFilter( $column, explode( ',', $value ), TRUE );
break;
case '=':
$this->sphinxClient->setFilter( $column, array( $value ) );
break;
case '!=':
case '<>':
$this->sphinxClient->setFilter( $column, array( $value ), TRUE );
break;
default:
echo "<b>Unhandled sphinx search operator: {$operator}</b><br />";
break;
}
}
/**
* Allows you to specify multiple conditions that are chained together
*
* @access public
* @param array $conditions Array of conditions, each element has 3 keys: column, operator, value, see the setCondition function for information on each
* @param string $inner_comp Comparison operator to use inside the chain
* @param string $outer_comp Comparison operator to use outside the chain
* @return void
*/
public function setMultiConditions( $conditions, $inner_comp='OR', $outer_comp='AND' )
{
/* Loop through the conditions to build the statement */
return;
}
/**
* Checks and logs any errors
*
* @access public
* @return void
*/
public function logSphinxWarnings()
{
$error = $this->sphinxClient->GetLastError();
$warning = $this->sphinxClient->GetLastWarning();
if ( $error )
{
IPSDebug::addLogMessage( "Sphinx Error: $error", 'sphinx_error_' . date('m_d_y'), $error, TRUE );
}
if ( $warning )
{
IPSDebug::addLogMessage( "Sphinx Warning: $warning", 'sphinx_warning_' . date('m_d_y'), $warning, TRUE );
}
}
}
@@ -0,0 +1,322 @@
<?php
/**
* <pre>
* Invision Power Services
* IP.Board v3.1.4
* Global Search
* Last Updated: $Date: 2010-02-22 17:06:11 +0000 (Mon, 22 Feb 2010) $
* </pre>
*
* @author $Author: matt $
* @copyright (c) 2001 - 2009 Invision Power Services, Inc.
* @license http://www.invisionpower.com/community/board/license.html
* @package IP.Board
* @subpackage Core
* @link http://www.invisionpower.com
* @version $Rev: 5859 $
*/
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
{
/**
* Date range restriction start
*
* @access protected
* @var integer
*/
protected $search_begin_timestamp = 0;
/**
* Date range restriction end
*
* @access protected
* @var integer
*/
protected $search_end_timestamp = 0;
/**
* Array of conditions for this search
*
* @access protected
* @var array
*/
protected $whereConditions = array();
/**
* Setup registry objects
*
* @access public
* @param object ipsRegistry $registry
* @return void
*/
public function __construct( ipsRegistry $registry )
{
/* Make object */
$this->registry = $registry;
$this->DB = $this->registry->DB();
$this->settings =& $this->registry->fetchSettings();
$this->request =& $this->registry->fetchRequest();
$this->lang = $this->registry->getClass('class_localization');
$this->member = $this->registry->member();
$this->memberData =& $this->registry->member()->fetchMemberData();
$this->cache = $this->registry->cache();
$this->caches =& $this->registry->cache()->fetchCaches();
}
/**
* Perform a search.
* Returns an array of a total count (total number of matches)
* and an array of IDs 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
*
* @access public
* @return array
*/
public function search()
{
/* Per app class handles this */
throw new Exception("NO_SEARCH_AVAILABLE");
}
/**
* Perform the viewNewContent search
* Generic version
* Populates $this->_count and $this->_results
*
* @access public
* @return nothin'
*/
public function viewNewContent()
{
$app = IPSSearchRegistry::get('in.search_app');
$lastActive = IPSLib::fetchHighestNumber( array( intval( $this->memberData['_cache']['gb_mark__' . $app] ), intval( $this->memberData['last_visit'] ) ) );
IPSSearchRegistry::set('in.search_sort_by' , 'date' );
IPSSearchRegistry::set('in.search_sort_order', 'desc' );
$this->setDateRange( $lastActive, time() );
/* Force title search only */
IPSSearchRegistry::set('opt.searchTitleOnly', true);
return $this->search();
}
/**
* Perform the search
* Populates $this->_count and $this->_results
*
* @access public
* @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' );
IPSSearchRegistry::set('opt.searchTitleOnly', IPSSearchRegistry::get('in.view_by_title') );
IPSSearchRegistry::set('display.onlyTitles' , IPSSearchRegistry::get('in.view_by_title') );
IPSSearchRegistry::set('opt.noPostPreview' , IPSSearchRegistry::get('in.view_by_title') );
/* Set the member_id */
$this->setCondition( 'member_id', '=', $member['member_id'] );
/* Cut by date for efficiency? */
if ( $this->settings['search_ucontent_days'] )
{
$begin = time() - ( 86400 * intval( $this->settings['search_ucontent_days'] ) );
$this->setDateRange( $begin, time() );
}
return $this->search();
}
/**
* Perform the search
* Populates $this->_count and $this->_results
*
* @access public
* @return nothin'
*/
public function viewActiveContent()
{
$seconds = IPSSearchRegistry::get('in.period_in_seconds');
/* Set time stamp */
$this->setDateRange( time() - $seconds, time() );
return $this->search();
}
/**
* Can handle boolean searching
*
* @access public
* @return boolean
*/
public function isBoolean()
{
return ( $this->settings['use_fulltext'] AND $this->DB->checkBooleanFulltextSupport() ) ? TRUE : FALSE;
}
/**
* Formats search term for SQL
*
* @access private
* @param string Raw IPB santized form input
* @return array array( 'search_term' => Safe string to use in SQL, 'removed' => array of removed search terms )
*/
public function formatSearchTerm( $search_term )
{
$isBoolean = $this->isBoolean();
$andor = isset( $this->request['andor_type'] ) ? $this->request['andor_type'] : $this->settings['s_andor_type'];
$removedTerms = array();
/* Fix up some sanitized HTML */
$search_term = str_replace( "&amp;" , '&' , IPSText::parseCleanValue( rawurldecode( $search_term ) ) );
if( $isBoolean )
{
$search_term = str_replace( "&quot;" , '"' , $search_term );
}
else
{
$search_term = str_replace( "&quot;" , '' , $search_term );
}
$search_term = IPSText::mbstrtolower( $search_term );
/* Check for disallowed search terms */
while( preg_match_all( "/(?:^|\s+)(img|quote|code|html|javascript|a href|color|span|div|border|style)(?:\s+|$)/", $search_term, $removed_search_terms ) )
{
$removedTerms[] = $removed_search_terms[0][0];
$search_term = preg_replace( "/(^|\s+)(?:img|quote|code|html|javascript|a href|color|span|div|border|style)(\s+|$)/", str_replace( " ", " ", "$1$2" ), $search_term );
}
/* Remove some formatting */
//$search_term = str_replace( array( '|', '\\', '/' ), '', $search_term );
// | is an OR operator for sphinx - don't want to block globally
$search_term = str_replace( array( '\\', '/' ), '', $search_term );
/* got some bullean to do? */
if ( $isBoolean AND strstr( $search_term, ' ' ) AND ! strstr( $search_term, '"' ) )
{
if ( $andor == 'and' )
{
$search_term = '+' . preg_replace( "/\s+(?!-|~)/", " +", $search_term );
}
}
return array( 'search_term' => $search_term, 'removed' => $removedTerms );
}
/**
* Restrict the date range that the search is performed on
*
* @access public
* @param int $begin Start timestamp
* @param int [$end] End timestamp
* @return void
*/
public function setDateRange( $begin, $end=0 )
{
$this->search_begin_timestamp = $begin;
$this->search_end_timestamp = $end;
}
/**
* mySQL function for adding special search conditions
*
* @access public
* @param string $column sql table column for this condition
* @param string $operator Operation to perform for this condition, ex: =, <>, IN, NOT IN
* @param mixed $value Value to check with
* @param string $comp Comparison type
* @return void
*/
public function setCondition( $column, $operator, $value, $comp='AND' )
{
$column = $this->remapColumn( $column );
if ( $column == 'app' OR ! $column )
{
return;
}
/* Build the condition based on operator */
switch( strtoupper( $operator ) )
{
case 'IN':
case 'NOT IN':
$this->whereConditions[$comp][] = "{$column} {$operator} ( {$value} )";
break;
default:
$this->whereConditions[$comp][] = "{$column} {$operator} {$value}";
break;
}
}
/**
* Remap standard columns (Apps can override )
*
* @access public
* @param string $column sql table column for this condition
* @return string column
* @return void
*/
public function remapColumn( $column )
{
return $column;
}
/**
* Allows you to specify multiple conditions that are chained together
*
* @access public
* @param array $conditions Array of conditions, each element has 3 keys: column, operator, value, see the setCondition function for information on each
* @param string $inner_comp Comparison operator to use inside the chain
* @param string $outer_comp Comparison operator to use outside the chain
* @return void
*/
public function setMultiConditions( $conditions, $inner_comp='OR', $outer_comp='AND' )
{
/* Loop through the conditions to build the statement */
$_temp = array();
foreach( $conditions as $r )
{
/* REMAP */
$r['column'] = $r['column'] == 'type_id' ? 't.forum_id' : $r['column'];
if( $r['column'] == 'app' )
{
continue;
}
switch( strtoupper( $r['operator'] ) )
{
case 'IN':
case 'NOT IN':
$_temp[] = "{$r['column']} {$r['operator']} ( {$r['value']} )";
break;
default:
$_temp[] = "{$r['column']} {$r['operator']} {$r['value']}";
break;
}
}
$this->whereConditions[$outer_comp][] = '( ' . implode( $_temp, ' ' . $inner_comp . ' ' ) . ' ) ';
}
}
@@ -0,0 +1,229 @@
<?php
/**
* <pre>
* Invision Power Services
* IP.Board v3.1.4
* Global Search
* Last Updated: $Date: 2010-02-22 17:06:11 +0000 (Mon, 22 Feb 2010) $
* </pre>
*
* @author $Author: matt $
* @copyright (c) 2001 - 2009 Invision Power Services, Inc.
* @license http://www.invisionpower.com/community/board/license.html
* @package IP.Board
* @subpackage Core
* @link http://www.invisionpower.com
* @version $Rev: 5859 $
*/
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_format
{
/**
* Search templates to use
*
* @access protected
* @var array
*/
protected $templates = array();
/**
* Setup registry objects
*
* @access public
* @param object ipsRegistry $registry
* @return void
*/
public function __construct( ipsRegistry $registry )
{
/* Make object */
$this->registry = $registry;
$this->DB = $this->registry->DB();
$this->settings =& $this->registry->fetchSettings();
$this->request =& $this->registry->fetchRequest();
$this->lang = $this->registry->getClass('class_localization');
$this->member = $this->registry->member();
$this->memberData =& $this->registry->member()->fetchMemberData();
$this->cache = $this->registry->cache();
$this->caches =& $this->registry->cache()->fetchCaches();
/* Set up default wrapper */
$this->templates = array( 'group' => 'search', 'template' => 'searchResults' );
}
/**
* Fetch templates to use
*
* @access public
* @return array
*/
public function fetchTemplates()
{
return $this->templates;
}
/**
* Formats / grabs extra data for results
* Takes an array of IDS (can be IDs from anything) and returns an array of expanded data.
*
* @access public
* @return array
*/
public function processResults( $ids )
{
/* Per app class handles this */
throw new Exception("NO_FORMAT_AVAILABLE");
}
/**
* Reassigns fields in a generic way for results output
* DEFAULT METHOD: Just return data. This should be overriden in the apps
*
* @param array $r
* @return array
**/
public function genericizeResults( $r )
{
return $r;
}
/**
* Parse common search results
*
* @access private
* @param array $r Search result
* @return array $html Blocks of HTML
*/
public function parseAndFetchHtmlBlocks( $rows )
{
/* Forum stuff */
$sub = false;
$isVnc = false;
$search_term = IPSSearchRegistry::get('in.clean_search_term');
$results = array();
/* loop and process */
foreach( $rows as $id => $r )
{
/* If basic search, strip the content */
IPSText::getTextClass( 'bbcode' )->parse_wordwrap = 0;
IPSText::getTextClass( 'bbcode' )->parse_bbcode = 0;
IPSText::getTextClass( 'bbcode' )->strip_quotes = 1;
IPSText::getTextClass( 'bbcode' )->parsing_section = 'topics';
IPSText::getTextClass( 'bbcode' )->parsing_mgroup = $r['member_group_id'];
IPSText::getTextClass( 'bbcode' )->parsing_mgroup_others = $r['mgroup_others'];
$r['content'] = strip_tags( IPSText::getTextClass( 'bbcode' )->stripAllTags( $r['content'] ) );
$r['content'] = str_replace( array( '&lt;br&gt;', '&lt;br /&gt;' ), '', $r['content'] );
$r['content'] = trim( str_replace( array( "\n\n\n", "\n\n" ), "\n", str_replace( "\r", '', $r['content'] ) ) );
/* Highlight */
$r['content'] = IPSText::searchHighlight( $this->searchTruncate( $r['content'], $search_term ), $search_term );
/* Format title */
$r['content_title'] = IPSText::searchHighlight( $r['content_title'], $search_term );
/* Format content */
list( $html, $sub ) = $this->formatContent( $r );
$results[ $id ] = array( 'html' => $html, 'app' => $r['app'], 'type' => $r['type'], 'sub' => $sub );
}
return $results;
}
/**
* Formats the forum search result for display
*
* @access public
* @param array $search_row Array of data
* @return mixed Formatted content, ready for display, or array containing a $sub section flag, and content
**/
public function formatContent( $data )
{
return array( $this->registry->output->getTemplate( 'search' )->searchRowGenericFormat( $data ), 0 );
}
/**
* Function to trim the search result display around the the hit
*
* @access private
* @param string $haystack Full search result
* @param string $needle The search term
* @return string
**/
public function searchTruncate( $haystack, $needle )
{
/* Base on words */
$haystack = explode( " ", $haystack );
if( count( $haystack ) > 21 )
{
$_term_at = $this->searchInArray( $needle, $haystack );
if( $_term_at - 11 > 0 )
{
$begin = array_splice( $haystack, 0, $_term_at - 11 );
/* The term position will have changed now */
$_term_at = $this->searchInArray( $needle, $haystack );
}
if( $_term_at + 11 < count( $haystack ) )
{
$end = array_splice( $haystack, $_term_at + 11, count( $haystack ) );
}
}
else
{
$begin = array();
$end = array();
}
$haystack = implode( " ", $haystack );
if( is_array( $begin ) && count( $begin ) )
{
$haystack = '...' . $haystack;
}
if( is_array( $end ) && count( $end ) )
{
$haystack = $haystack . '...';
}
return $haystack;
}
/**
* Search array (array_search only finds exact instances)
*
* @access protected
* @param string "Needle"
* @param array Array of entries to search
* @return mixed Key of array, or false on failure
*/
public function searchInArray( $needle, $haystack )
{
if( !is_array( $haystack ) OR !count($haystack) OR ! $needle )
{
return false;
}
foreach( $haystack as $k => $v )
{
if( $v AND strpos( $v, $needle ) !== false )
{
return $k;
}
}
return false;
}
}
+10 -1
View File
@@ -1 +1,10 @@
<html>␍<head><title>IP.Board - Bulletin Board System</title></head>␍<body>␍<h1>403: IP.Board -> Forbidden</h1>␍<hr>␍You have reached this page in error, please use your back button to return to the forum.␍<hr>␍<a href="http://www.invisionboard.com/">IP.Board</a>␍</body>␍</html>␍
<html>
<head><title>IP.Board - Bulletin Board System</title></head>
<body>
<h1>403: IP.Board -&gt; Forbidden</h1>
<hr>
You have reached this page in error, please use your back button to return to the forum.
<hr>
<a href="http://www.invisionboard.com/">IP.Board</a>
</body>
</html>
@@ -1,469 +0,0 @@
<?php
/**
* Invision Power Services
* IP.Board v3.0.5
* Global Search
* Last Updated: $Date: 2009-03-04 07:36:56 -0500 (Wed, 04 Mar 2009) $
*
* @author $Author: matt $
* @copyright (c) 2001 - 2009 Invision Power Services, Inc.
* @license http://www.iinvisionpower.com/community/board/license.html
* @package Invision Power Board
* @subpackage Core
* @link http://www.iinvisionpower.com
* @version $Rev: 4135 $
*/
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 searchPluginIndexIndex implements iSearchIndexPlugin
{
/**
* Database object
*
* @access private
* @var object
*/
private $DB;
/**
* Date range restriction start
*
* @access private
* @var integer
*/
private $search_begin_timestamp = 0;
/**
* Date range restriction end
*
* @access private
* @var integer
*/
private $search_end_timestamp = 0;
/**
* Array of conditions for this search
*
* @access private
* @var array
*/
private $whereConditions = array();
/**
* Apps to exclude
*
* @access public
* @var array
*/
public $exclude_apps = array();
/**
* Setup registry objects
*
* @access public
* @param object ipsRegistry $registry
* @return void
*/
public function __construct( ipsRegistry $registry )
{
$this->DB = $registry->DB();
$this->member = $registry->member();
$this->memberData =& $registry->member()->fetchMemberData();
}
/**
* Performs search and returns an array of results
*
* @access public
* @param string $search_term
* @param array $limit_clause The erray should be array( begin, end )
* @param string $sort_by Column to sort by
* @param string $group_by Column to group by
* @param bool $content_title_only Only search title records
* @return array
*/
public function getSearchResults( $search_term, $limit_clause, $sort_by, $group_by='', $content_title_only=false )
{
/* Do the search */
$this->DB->build( $this->_buildSearchQueryArray( $search_term, $limit_clause, $sort_by, $group_by, false, $content_title_only ) );
$this->DB->execute();
/* Build result array */
$rows = array();
while( $r = $this->DB->fetch() )
{
$rows[] = $r;
}
return $rows;
}
/**
* Performs live search and returns an array of results
* NOT AVAILABLE IN BASIC SEARCH
*
* @access public
* @param string $search_term
* @return array
*/
public function getLiveSearchResults( $search_term )
{
if( ipsRegistry::$settings['live_search_disable'] )
{
return array();
}
/* Do the search */
$this->DB->build( $this->_buildSearchQueryArray( $search_term, array( 0, 10 ), 'date' ) );
$this->DB->execute();
/* Build result array */
$rows = array();
while( $r = $this->DB->fetch() )
{
$rows[] = $r;
}
return $rows;
}
/**
* Returns the total number of results the search will return
*
* @access public
* @param string $search_term Search term
* @param string $group_by Column to group by
* @param bool $content_title_only Only search title records
* @return integer
*/
public function getSearchCount( $search_term, $group_by='', $content_title_only=false )
{
/* Query the count */
$this->DB->build( $this->_buildSearchQueryArray( $search_term, array(), '', $group_by, true, $content_title_only ) );
$this->DB->execute();
/* Return the count */
if( $group_by )
{
return $this->DB->getTotalRows();
}
else
{
$r = $this->DB->fetch();
return $r['total_results'];
}
}
/**
* Restrict the date range that the search is performed on
*
* @access public
* @param int $begin Start timestamp
* @param int [$end] End timestamp
* @return void
*/
public function setDateRange( $begin, $end=0 )
{
$this->search_begin_timestamp = $begin;
$this->search_end_timestamp = $end;
}
/**
* mySQL function for adding special search conditions
*
* @access public
* @param string $column sql table column for this condition
* @param string $operator Operation to perform for this condition, ex: =, <>, IN, NOT IN
* @param mixed $value Value to check with
* @param string $comp Comparison type
* @return void
*/
public function setCondition( $column, $operator, $value, $comp='AND' )
{
/* Build the condition based on operator */
switch( strtoupper( $operator ) )
{
case 'IN':
case 'NOT IN':
$this->whereConditions[$comp][] = "i.{$column} {$operator} ( {$value} )";
break;
default:
$this->whereConditions[$comp][] = "i.{$column} {$operator} {$value}";
break;
}
}
/**
* Allows you to specify multiple conditions that are chained together
*
* @access public
* @param array $conditions Array of conditions, each element has 3 keys: column, operator, value, see the setCondition function for information on each
* @param string $inner_comp Comparison operator to use inside the chain
* @param string $outer_comp Comparison operator to use outside the chain
* @return void
*/
public function setMultiConditions( $conditions, $inner_comp='OR', $outer_comp='AND' )
{
/* Loop through the conditions to build the statement */
$_temp = array();
foreach( $conditions as $r )
{
switch( strtoupper( $r['operator'] ) )
{
case 'IN':
case 'NOT IN':
$_temp[] = "i.{$r['column']} {$r['operator']} ( {$r['value']} )";
break;
default:
$_temp[] = "i.{$r['column']} {$r['operator']} {$r['value']}";
break;
}
}
$this->whereConditions[$outer_comp][] = '( ' . implode( $_temp, ' ' . $inner_comp . ' ' ) . ' ) ';
}
/**
* Reassigns fields in a way the index exepcts
*
* @param array $r
* @return array
**/
public function formatFieldsForIndex( $r )
{
}
/**
* This function grabs the actual results for display
*
* @param array $ids
* @return query result
**/
public function getResultsForSphinx( $ids )
{
}
/**
* Builds an array that can be used in build
*
* @access public
* @param string $search_term
* @param array $limit_clause The erray should be array( begin, end )
* @param string $sort_by Either relevance or date
* @param string [$group_by] Field to group on
* @param bool [$count_only] Set to true for a count(*) query
* @param bool [$content_title_only] Set to true to only search titles
* @return array
*/
private function _buildSearchQueryArray( $search_term, $limit_clause, $sort_by, $group_by='', $count_only=false, $content_title_only=false )
{
/* Do we only need to count results? */
if( $count_only )
{
if( $group_by )
{
$group_by = 'i.' . $group_by;
}
$search_query_array = array(
'select' => 'COUNT(*) as total_results',
'from' => array( 'search_index' => 'i' ),
'where' => $this->_buildWhereStatement( $search_term, $content_title_only ),
'group' => $group_by,
'add_join' => array(
array(
'from' => array( 'permission_index' => 'p' ),
'where' => 'p.perm_type_id=i.type_id AND p.perm_type=i.type',
'type' => 'left',
),
array(
'from' => array( 'profile_friends' => 'friend' ),
'where' => 'friend.friends_member_id=i.member_id AND friend.friends_friend_id=' . $this->memberData['member_id'],
'type' => 'left',
),
)
);
}
else
{
/* Sort By */
if( isset( $sort_by ) && in_array( $sort_by, array( 'date', 'relevance', 'ascdate' ) ) )
{
$_ord = strstr( $sort_by, 'asc' ) ? 'ASC' : 'DESC';
$order = $sort_by == 'date' ? 'i.updated ' . $_ord : 'ranking' . $_ord;
}
else
{
$order = 'ranking DESC';
}
/* If there is no search term, we need to force search by updated */
if( ! $search_term )
{
$order = 'i.updated DESC';
}
if( $group_by )
{
$group_by = 'i.' . $group_by;
}
if( $content_title_only )
{
$ranking_select = $search_term ? ", MATCH( i.content_title ) AGAINST( '{$search_term}' IN BOOLEAN MODE ) as ranking" : '';
}
else
{
$ranking_select = $search_term ? ", MATCH( i.content, i.content_title ) AGAINST( '{$search_term}' IN BOOLEAN MODE ) as ranking" : '';
}
/* Build the search query array */
$search_query_array = array(
'select' => "i.*{$ranking_select}",
'from' => array( 'search_index' => 'i' ),
'where' => $this->_buildWhereStatement( $search_term, $content_title_only ),
'limit' => $limit_clause,
'group' => $group_by,
'order' => $order,
'add_join' => array(
array(
'select' => 'p.perm_view',
'from' => array( 'permission_index' => 'p' ),
'where' => 'p.perm_type_id=i.type_id AND p.perm_type=i.type',
'type' => 'left',
),
array(
'select' => 'm.members_display_name, m.member_group_id, m.mgroup_others',
'from' => array( 'members' => 'm' ),
'where' => 'i.member_id=m.member_id',
'type' => 'left',
),
array(
'from' => array( 'profile_friends' => 'friend' ),
'where' => 'friend.friends_member_id=i.member_id AND friend.friends_friend_id=' . $this->memberData['member_id'],
'type' => 'left',
),
)
);
}
/* Loop through all the search plugins and let them modify the search query */
foreach( ipsRegistry::$applications as $app )
{
if( IPSSearchIndex::appisSearchable( $app['app_directory'] ) )
{
if( ! isset( $this->display_plugins[ $app['app_directory'] ] ) || ! $this->display_plugins[ $app['app_directory'] ] )
{
require_once( IPSLib::getAppDir( $app['app_directory'] ) . '/extensions/searchDisplay.php' );
$_class = $app['app_directory'] . 'SearchDisplay';
$this->display_plugins[ $app['app_directory'] ] = new $_class();
}
if( method_exists( $this->display_plugins[ $app['app_directory'] ] , 'modifySearchQuery' ) )
{
/* Get the modified query */
$new_query = $this->display_plugins[ $app['app_directory'] ]->modifySearchQuery( $search_query_array, $count_only );
/* Simple check to prevent accidentaly breaking the query, clearly not fool proof :) */
$search_query_array = is_array( $new_query ) && count( $new_query ) ? $new_query : $search_query_array;
}
}
}
return $search_query_array;
}
/**
* Builds the where portion of a search string
*
* @access private
* @param string $search_term The string to use in the search
* @param bool $content_title_only Search only title records
* @return string
**/
private function _buildWhereStatement( $search_term, $content_title_only=false )
{
/* INI */
$where_clause = array();
if( $search_term )
{
/* Main Search Statement */
if( $content_title_only )
{
$where_clause[] = "MATCH( i.content_title ) AGAINST( '$search_term' IN BOOLEAN MODE )";
}
else
{
$where_clause[] = "MATCH( i.content, i.content_title ) AGAINST( '$search_term' IN BOOLEAN MODE )";
}
}
/* Exclude Apps */
if( count( $this->exclude_apps ) )
{
$where_clause[] = 'i.app NOT IN ( ' . implode( ',', $this->exclude_apps ) . ' )';
}
/* Exclude some items */
if( !$this->memberData['g_is_supmod'] )
{
/* Owner only */
$where_clause[] = '(p.owner_only=0 OR i.member_id=' . $this->memberData['member_id'] . ')';
/* Friend only */
$where_clause[] = '(p.friend_only=0 OR friend.friends_id ' . $this->DB->buildIsNull( false ) . ')';
/* Authorized users only */
$where_clause[] = '(p.authorized_users ' . $this->DB->buildIsNull() . ' OR i.member_id=' . $this->memberData['member_id'] . " OR p.authorized_users LIKE '%," . $this->memberData['member_id'] . ",%')";
}
/* Date Restrict */
if( $this->search_begin_timestamp && $this->search_end_timestamp )
{
$where_clause[] = "i.updated BETWEEN {$this->search_begin_timestamp} AND {$this->search_end_timestamp}";
}
else
{
if( $this->search_begin_timestamp )
{
$where_clause[] = "i.updated > {$this->search_begin_timestamp}";
}
if( $this->search_end_timestamp )
{
$where_clause[] = "i.updated < {$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'] ) . ' )';
}
/* Permissions */
$where_clause[] = $this->DB->buildRegexp( "p.perm_view", $this->member->perm_id_array );
/* Build and return the string */
return implode( " AND ", $where_clause );
}
}
File diff suppressed because it is too large. Load diff