Version 3.0.5
This commit is contained in:
1 parent
19b38c7c74
commit
1d4720f3e2
3755 files changed
+508378
-664541
No files matched your search
@@ -0,0 +1,506 @@
|
||||
<?php
|
||||
/**
|
||||
* Invision Power Services
|
||||
* IP.Board v3.0.5
|
||||
* Global Search
|
||||
* Last Updated: $Date: 2009-11-13 19:55:00 -0500 (Fri, 13 Nov 2009) $
|
||||
*
|
||||
* @author $Author: bfarber $
|
||||
* @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: 5405 $
|
||||
*/
|
||||
|
||||
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 searchPluginSphinxIndex 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();
|
||||
|
||||
/**
|
||||
* Sphinx client object
|
||||
*
|
||||
* @access public
|
||||
* @var object
|
||||
*/
|
||||
public $sphinxClient;
|
||||
|
||||
/**
|
||||
* Don't show post preview
|
||||
*
|
||||
* @access public
|
||||
* @var boolean
|
||||
*/
|
||||
public $noPostPreview = false;
|
||||
|
||||
/**
|
||||
* Do not join posts table on
|
||||
*
|
||||
* @access public
|
||||
* @var boolean
|
||||
*/
|
||||
public $onlyTitles = false;
|
||||
|
||||
/**
|
||||
* Search plugin for the application
|
||||
*
|
||||
* @access public
|
||||
* @var object
|
||||
*/
|
||||
public $appSearchPlugin;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
$this->settings = $registry->settings();
|
||||
$this->request = $registry->request();
|
||||
|
||||
/* 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 );
|
||||
|
||||
/* We're going to need the regular app index plugin also */
|
||||
require_once( IPSLib::getAppDir( ipsRegistry::$request[ 'search_app' ] ) . '/extensions/searchPlugin.php' );
|
||||
$searchApp = 'search' . ucfirst( $this->request['search_app'] ) . 'Plugin';
|
||||
$this->appSearchPlugin = new $searchApp( $registry );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 )
|
||||
{
|
||||
$search_term = str_replace( '"', '"', $search_term );
|
||||
$search_term = str_replace( '&', '&', $search_term );
|
||||
$search_term = str_replace( '!', '!', $search_term );
|
||||
|
||||
/* Do the search */
|
||||
$results = $this->_searchQuery( $search_term, $limit_clause, $sort_by, $group_by, false, $content_title_only );
|
||||
|
||||
/* Build result array */
|
||||
$rows = array();
|
||||
|
||||
if( is_array( $results ) && count( $results ) )
|
||||
{
|
||||
$q = $this->appSearchPlugin->getResultsForSphinx( $results );
|
||||
|
||||
while( $r = $this->DB->fetch( $q ) )
|
||||
{
|
||||
/* Reassign stuff to match the search_index */
|
||||
$rows[] = $this->appSearchPlugin->formatFieldsForIndex( $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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 )
|
||||
{
|
||||
$search_term = str_replace( '"', '"', $search_term );
|
||||
$search_term = str_replace( '&', '&', $search_term );
|
||||
$search_term = str_replace( '!', '!', $search_term );
|
||||
|
||||
/* Return the count */
|
||||
return $this->_searchQuery( $search_term, array(), '', '', true, $content_title_only );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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->sphinxClient->SetFilterRange( $this->appSearchPlugin->getDateField(), $begin, $end );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set search conditions for "View unread content"
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setUnreadConditions()
|
||||
{
|
||||
$this->setDateRange( intval( $this->memberData['last_visit'] ), time() );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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->appSearchPlugin->getConditionField( $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>Не существующий оператор: {$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' )
|
||||
{
|
||||
//echo "<b>setMultiCondidion</b> should not be used in sphinx<br />";
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does search
|
||||
*
|
||||
* @access private
|
||||
* @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] Only search titles
|
||||
* @return array
|
||||
**/
|
||||
private function _searchQuery( $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( $limit_clause[1] )
|
||||
{
|
||||
/* Limit Results */
|
||||
$this->sphinxClient->SetLimits( intval($limit_clause[0]), intval($limit_clause[1]) );
|
||||
}
|
||||
else if( $limit_clause[0] )
|
||||
{
|
||||
$this->sphinxClient->SetLimits( 0, intval($limit_clause[0]) );
|
||||
}
|
||||
|
||||
/* Sort By */
|
||||
if( isset( $sort_by ) && in_array( $sort_by, array( 'date', 'relevance' ) ) )
|
||||
{
|
||||
if( $sort_by == 'date' )
|
||||
{
|
||||
if( $this->request['search_sort_order'] == 0 )
|
||||
{
|
||||
$this->sphinxClient->SetSortMode( SPH_SORT_ATTR_DESC, $this->appSearchPlugin->getDateField() /* Sigh */ );
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->sphinxClient->SetSortMode( SPH_SORT_ATTR_ASC, $this->appSearchPlugin->getDateField() /* Sigh */ );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->sphinxClient->SetSortMode( SPH_SORT_RELEVANCE );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->sphinxClient->SetSortMode( SPH_SORT_RELEVANCE );
|
||||
}
|
||||
}
|
||||
|
||||
/* Exclude Apps */
|
||||
if( count( $this->exclude_apps ) )
|
||||
{
|
||||
$app_id_exclude = array();
|
||||
foreach( $this->exclude_apps as $app_dir )
|
||||
{
|
||||
$app_id_exclude[] = ipsRegistry::$applications[$app_dir]['app_id'];
|
||||
}
|
||||
|
||||
$this->sphinxClient->SetFilter( 'app', $app_id_exclude, TRUE );
|
||||
}
|
||||
|
||||
/* Permissions */
|
||||
$perm_array = $this->member->perm_id_array;
|
||||
$perm_array[] = 0;
|
||||
|
||||
/* Need to remove empty values... */
|
||||
$final_perms = array();
|
||||
|
||||
foreach( $perm_array as $perm_id )
|
||||
{
|
||||
if( is_numeric( $perm_id ) )
|
||||
{
|
||||
$final_perms[] = intval($perm_id);
|
||||
}
|
||||
}
|
||||
|
||||
$this->sphinxClient->SetFilter( 'perm_view', $final_perms );
|
||||
|
||||
/* Exclude some items */
|
||||
if( ! $this->memberData['g_is_supmod'] )
|
||||
{
|
||||
/* Owner only */
|
||||
$this->sphinxClient->SetFilter( 'owner_only', array( 0, intval($this->memberData['member_id']) ) );
|
||||
|
||||
/* Friend only */
|
||||
$this->DB->build( array(
|
||||
'select' => 'friends_member_id',
|
||||
'from' => 'profile_friends',
|
||||
'where' => "friends_friend_id={$this->memberData['member_id']}"
|
||||
) );
|
||||
$this->DB->execute();
|
||||
|
||||
$friends_ids = array( 0 );
|
||||
while( $r = $this->DB->fetch() )
|
||||
{
|
||||
$friends_ids[] = intval($r['friends_member_id']);
|
||||
}
|
||||
|
||||
$this->sphinxClient->SetFilter( 'friend_only', $friends_ids );
|
||||
|
||||
/* Authorized users only */
|
||||
$this->sphinxClient->SetFilter( 'authorized_users', array( 0, intval($this->memberData['member_id']) ) );
|
||||
}
|
||||
|
||||
/* 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();
|
||||
}
|
||||
|
||||
$this->appSearchPlugin->onlyTitles = $this->onlyTitles;
|
||||
$this->appSearchPlugin->noPostPreview = $this->noPostPreview;
|
||||
|
||||
$this->display_plugins[ $app['app_directory'] ]->search_plugin = $this->appSearchPlugin;
|
||||
|
||||
if( method_exists( $this->display_plugins[ $app['app_directory'] ], 'modifySearchQuery' ) )
|
||||
{
|
||||
/* Get the modified query */
|
||||
$this->display_plugins[ $app['app_directory'] ]->modifySearchQuery( $this->sphinxClient, $count_only );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$groupby = $this->onlyTitles ? true : false;
|
||||
|
||||
/* Perform the search */
|
||||
if( method_exists( $this->display_plugins[ $this->request['search_app'] ], 'runSearchQuery' ) )
|
||||
{
|
||||
$result = $this->display_plugins[ $this->request['search_app'] ]->runSearchQuery( $this->sphinxClient, $search_term, $groupby );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( $groupby )
|
||||
{
|
||||
$this->sphinxClient->SetGroupBy( 'search_id', SPH_GROUPBY_ATTR, '@group DESC');
|
||||
}
|
||||
|
||||
$result = $this->sphinxClient->Query( $search_term, $this->request['search_app'] . '_search_main,' . $this->request['search_app'] . '_search_delta' );
|
||||
}
|
||||
|
||||
/* Return the total number of results */
|
||||
if( $count_only )
|
||||
{
|
||||
return $result['total'];
|
||||
}
|
||||
/* Return the results */
|
||||
else
|
||||
{
|
||||
$search_ids = array();
|
||||
|
||||
if( is_array( $result['matches'] ) && count( $result['matches'] ) )
|
||||
{
|
||||
foreach( $result['matches'] as $res )
|
||||
{
|
||||
$search_ids[] = $res['attrs']['search_id'];
|
||||
}
|
||||
}
|
||||
|
||||
return $search_ids;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reassigns fields in a way the index exepcts
|
||||
*
|
||||
* @param array $r
|
||||
* @return array
|
||||
**/
|
||||
public function formatFieldsForIndex( $r )
|
||||
{
|
||||
// Blank
|
||||
}
|
||||
|
||||
/**
|
||||
* This function grabs the actual results for display
|
||||
*
|
||||
* @param array $ids
|
||||
* @return query result
|
||||
**/
|
||||
public function getResultsForSphinx( $ids )
|
||||
{
|
||||
// Blank
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether or not we're showing as forum or not
|
||||
*
|
||||
* @param public
|
||||
* @return bool
|
||||
*/
|
||||
public function getShowAsForum()
|
||||
{
|
||||
if( method_exists( $this->appSearchPlugin, 'getShowAsForum' ) )
|
||||
{
|
||||
return $this->appSearchPlugin->getShowAsForum();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user