2007-07-22 22:23:00 +00:00
< ? php
/**
*
2014-05-27 20:18:06 +02:00
* This file is part of the phpBB Forum Software package .
*
* @ copyright ( c ) phpBB Limited < https :// www . phpbb . com >
* @ license GNU General Public License , version 2 ( GPL - 2.0 )
*
* For full copyright and license information , please see
* the docs / CREDITS . txt file .
2007-07-22 22:23:00 +00:00
*
*/
2013-09-10 14:01:09 +02:00
namespace phpbb\search ;
2007-07-22 22:23:00 +00:00
/**
* Fulltext search for PostgreSQL
*/
2013-09-10 14:01:09 +02:00
class fulltext_postgres extends \phpbb\search\base
2007-07-22 22:23:00 +00:00
{
2012-08-10 16:00:51 +05:30
/**
* Associative array holding index stats
* @ var array
*/
2012-08-14 17:47:01 +05:30
protected $stats = array ();
2012-08-10 16:00:51 +05:30
/**
2012-08-19 13:04:34 +05:30
* Holds the words entered by user , obtained by splitting the entered query on whitespace
2012-08-10 16:00:51 +05:30
* @ var array
*/
2012-08-14 17:47:01 +05:30
protected $split_words = array ();
2012-08-10 16:00:51 +05:30
/**
* Stores the tsearch query
* @ var string
*/
2012-08-14 17:47:01 +05:30
protected $tsearch_query ;
2012-08-10 16:00:51 +05:30
/**
2012-08-19 13:13:03 +05:30
* True if phrase search is supported .
2012-08-15 23:49:51 +05:30
* PostgreSQL fulltext currently doesn ' t support it
2012-08-10 16:00:51 +05:30
* @ var boolean
*/
2012-08-14 17:47:01 +05:30
protected $phrase_search = false ;
2012-08-10 16:00:51 +05:30
/**
2012-08-19 12:07:06 +05:30
* Config object
2013-09-10 14:01:09 +02:00
* @ var \phpbb\config\config
2012-08-10 16:00:51 +05:30
*/
2012-08-14 17:47:01 +05:30
protected $config ;
2012-08-10 16:00:51 +05:30
/**
2012-12-04 04:29:31 -05:00
* Database connection
2014-03-17 13:29:35 +01:00
* @ var \phpbb\db\driver\driver_interface
2012-08-10 16:00:51 +05:30
*/
2012-08-14 17:47:01 +05:30
protected $db ;
2012-08-10 16:00:51 +05:30
2015-03-11 17:46:42 +00:00
/**
2015-06-09 12:55:27 +01:00
* phpBB event dispatcher object
2015-03-11 17:46:42 +00:00
* @ var \phpbb\event\dispatcher_interface
*/
protected $phpbb_dispatcher ;
2012-08-10 16:00:51 +05:30
/**
2012-08-19 12:07:06 +05:30
* User object
2013-09-10 14:01:09 +02:00
* @ var \phpbb\user
2012-08-10 16:00:51 +05:30
*/
2012-08-14 17:47:01 +05:30
protected $user ;
2012-08-10 16:00:51 +05:30
/**
2012-08-20 01:04:43 +05:30
* Contains tidied search query .
* Operators are prefixed in search query and common words excluded
2012-08-10 16:00:51 +05:30
* @ var string
*/
2012-11-09 16:22:32 +05:30
protected $search_query ;
2012-08-10 16:00:51 +05:30
/**
2012-08-19 13:13:03 +05:30
* Contains common words .
* Common words are words with length less / more than min / max length
2012-08-10 16:00:51 +05:30
* @ var array
*/
2012-11-09 16:22:32 +05:30
protected $common_words = array ();
2012-08-10 16:00:51 +05:30
/**
2012-08-20 00:58:41 +05:30
* Associative array stores the min and max word length to be searched
2012-08-10 16:00:51 +05:30
* @ var array
*/
2012-11-09 16:22:32 +05:30
protected $word_length = array ();
2007-07-22 22:23:00 +00:00
2012-06-23 02:14:46 +05:30
/**
* Constructor
2013-09-10 14:01:09 +02:00
* Creates a new \phpbb\search\fulltext_postgres , which is used as a search backend
2012-06-23 02:14:46 +05:30
*
* @ param string | bool $error Any error that occurs is passed on through this reference variable otherwise false
2014-05-19 04:07:08 +03:00
* @ param string $phpbb_root_path Relative path to phpBB root
2014-08-07 13:19:49 +03:00
* @ param string $phpEx PHP file extension
2014-05-19 04:07:08 +03:00
* @ param \phpbb\auth\auth $auth Auth object
* @ param \phpbb\config\config $config Config object
2021-04-10 10:22:54 +02:00
* @ param \phpbb\db\driver\driver_interface $db Database object
2014-05-19 04:07:08 +03:00
* @ param \phpbb\user $user User object
2015-03-11 17:46:42 +00:00
* @ param \phpbb\event\dispatcher_interface $phpbb_dispatcher Event dispatcher object
2012-06-23 02:14:46 +05:30
*/
2015-03-11 17:46:42 +00:00
public function __construct ( & $error , $phpbb_root_path , $phpEx , $auth , $config , $db , $user , $phpbb_dispatcher )
2007-07-22 22:23:00 +00:00
{
2012-07-22 16:50:09 +05:30
$this -> config = $config ;
$this -> db = $db ;
2015-03-11 17:46:42 +00:00
$this -> phpbb_dispatcher = $phpbb_dispatcher ;
2012-07-22 16:50:09 +05:30
$this -> user = $user ;
2007-07-22 22:23:00 +00:00
2012-07-22 16:50:09 +05:30
$this -> word_length = array ( 'min' => $this -> config [ 'fulltext_postgres_min_word_len' ], 'max' => $this -> config [ 'fulltext_postgres_max_word_len' ]);
2007-07-22 22:23:00 +00:00
2012-11-12 17:05:07 +01:00
/**
* Load the UTF tools
*/
if ( ! function_exists ( 'utf8_strlen' ))
{
include ( $phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx );
}
2007-07-22 22:23:00 +00:00
$error = false ;
}
2012-05-01 16:09:08 +05:30
/**
* Returns the name of this search backend to be displayed to administrators
*
* @ return string Name
*/
2012-06-10 16:46:07 +05:30
public function get_name ()
2012-05-01 16:09:08 +05:30
{
return 'PostgreSQL Fulltext' ;
}
2012-07-03 03:54:01 +05:30
2012-08-15 14:13:31 +05:30
/**
* Returns the search_query
*
* @ return string search query
*/
public function get_search_query ()
{
return $this -> search_query ;
}
/**
* Returns the common_words array
*
* @ return array common words that are ignored by search backend
*/
public function get_common_words ()
{
return $this -> common_words ;
}
/**
* Returns the word_length array
*
* @ return array min and max word length for searching
*/
public function get_word_length ()
{
return $this -> word_length ;
}
2012-07-03 03:54:01 +05:30
/**
* Returns if phrase search is supported or not
*
* @ return bool
*/
public function supports_phrase_search ()
{
return $this -> phrase_search ;
}
2012-05-01 16:09:08 +05:30
2007-07-22 22:23:00 +00:00
/**
* Checks for correct PostgreSQL version and stores min / max word length in the config
2012-06-23 02:14:46 +05:30
*
2017-08-15 15:00:12 -04:00
* @ return string | bool Language key of the error / incompatibility occurred
2007-07-22 22:23:00 +00:00
*/
2012-08-10 11:30:02 +05:30
public function init ()
2007-07-22 22:23:00 +00:00
{
2014-06-26 17:17:35 +02:00
if ( $this -> db -> get_sql_layer () != 'postgres' )
2007-07-22 22:23:00 +00:00
{
2012-07-22 16:50:09 +05:30
return $this -> user -> lang [ 'FULLTEXT_POSTGRES_INCOMPATIBLE_DATABASE' ];
2007-07-22 22:23:00 +00:00
}
return false ;
}
/**
* Splits keywords entered by a user into an array of words stored in $this -> split_words
* Stores the tidied search query in $this -> search_query
*
2012-06-23 02:14:46 +05:30
* @ param string & $keywords Contains the keyword as entered by the user
* @ param string $terms is either 'all' or 'any'
* @ return bool false if no valid keywords were found and otherwise true
2007-07-22 22:23:00 +00:00
*/
2012-08-10 11:30:02 +05:30
public function split_keywords ( & $keywords , $terms )
2007-07-22 22:23:00 +00:00
{
if ( $terms == 'all' )
{
2013-05-04 18:56:52 +05:30
$match = array ( '#\sand\s#iu' , '#\sor\s#iu' , '#\snot\s#iu' , '#(^|\s)\+#' , '#(^|\s)-#' , '#(^|\s)\|#' );
2007-07-22 22:23:00 +00:00
$replace = array ( ' +' , ' |' , ' -' , ' +' , ' -' , ' |' );
$keywords = preg_replace ( $match , $replace , $keywords );
}
// Filter out as above
2022-04-05 05:54:33 +01:00
$split_keywords = preg_replace ( " #[ \" \n \r \t ]+# " , ' ' , trim ( html_entity_decode ( $keywords , ENT_COMPAT )));
2007-07-22 22:23:00 +00:00
// Split words
2012-06-12 04:18:39 +05:30
$split_keywords = preg_replace ( '#([^\p{L}\p{N}\'*"()])#u' , '$1$1' , str_replace ( '\'\'' , '\' \'' , trim ( $split_keywords )));
$matches = array ();
preg_match_all ( '#(?:[^\p{L}\p{N}*"()]|^)([+\-|]?(?:[\p{L}\p{N}*"()]+\'?)*[\p{L}\p{N}*"()])(?:[^\p{L}\p{N}*"()]|$)#u' , $split_keywords , $matches );
$this -> split_words = $matches [ 1 ];
2007-07-22 22:23:00 +00:00
foreach ( $this -> split_words as $i => $word )
{
$clean_word = preg_replace ( '#^[+\-|"]#' , '' , $word );
// check word length
$clean_len = utf8_strlen ( str_replace ( '*' , '' , $clean_word ));
2012-07-22 16:50:09 +05:30
if (( $clean_len < $this -> config [ 'fulltext_postgres_min_word_len' ]) || ( $clean_len > $this -> config [ 'fulltext_postgres_max_word_len' ]))
2007-07-22 22:23:00 +00:00
{
$this -> common_words [] = $word ;
unset ( $this -> split_words [ $i ]);
}
}
if ( $terms == 'any' )
{
$this -> search_query = '' ;
$this -> tsearch_query = '' ;
foreach ( $this -> split_words as $word )
{
if (( strpos ( $word , '+' ) === 0 ) || ( strpos ( $word , '-' ) === 0 ) || ( strpos ( $word , '|' ) === 0 ))
{
$word = substr ( $word , 1 );
}
$this -> search_query .= $word . ' ' ;
$this -> tsearch_query .= '|' . $word . ' ' ;
}
}
else
{
$this -> search_query = '' ;
$this -> tsearch_query = '' ;
foreach ( $this -> split_words as $word )
{
if ( strpos ( $word , '+' ) === 0 )
{
$this -> search_query .= $word . ' ' ;
$this -> tsearch_query .= '&' . substr ( $word , 1 ) . ' ' ;
}
2014-06-15 21:34:02 +02:00
else if ( strpos ( $word , '-' ) === 0 )
2007-07-22 22:23:00 +00:00
{
$this -> search_query .= $word . ' ' ;
$this -> tsearch_query .= '&!' . substr ( $word , 1 ) . ' ' ;
}
2014-06-15 21:34:02 +02:00
else if ( strpos ( $word , '|' ) === 0 )
2007-07-22 22:23:00 +00:00
{
$this -> search_query .= $word . ' ' ;
$this -> tsearch_query .= '|' . substr ( $word , 1 ) . ' ' ;
}
else
{
$this -> search_query .= '+' . $word . ' ' ;
$this -> tsearch_query .= '&' . $word . ' ' ;
}
}
}
$this -> tsearch_query = substr ( $this -> tsearch_query , 1 );
$this -> search_query = utf8_htmlspecialchars ( $this -> search_query );
if ( $this -> search_query )
{
$this -> split_words = array_values ( $this -> split_words );
sort ( $this -> split_words );
return true ;
}
return false ;
}
/**
* Turns text into an array of words
2012-06-23 02:14:46 +05:30
* @ param string $text contains post text / subject
2007-07-22 22:23:00 +00:00
*/
2012-08-10 11:30:02 +05:30
public function split_message ( $text )
2007-07-22 22:23:00 +00:00
{
// Split words
2012-06-12 04:18:39 +05:30
$text = preg_replace ( '#([^\p{L}\p{N}\'*])#u' , '$1$1' , str_replace ( '\'\'' , '\' \'' , trim ( $text )));
$matches = array ();
preg_match_all ( '#(?:[^\p{L}\p{N}*]|^)([+\-|]?(?:[\p{L}\p{N}*]+\'?)*[\p{L}\p{N}*])(?:[^\p{L}\p{N}*]|$)#u' , $text , $matches );
$text = $matches [ 1 ];
2007-07-22 22:23:00 +00:00
// remove too short or too long words
$text = array_values ( $text );
2017-06-28 00:58:03 +07:00
for ( $i = 0 , $n = count ( $text ); $i < $n ; $i ++ )
2007-07-22 22:23:00 +00:00
{
$text [ $i ] = trim ( $text [ $i ]);
2012-07-22 16:50:09 +05:30
if ( utf8_strlen ( $text [ $i ]) < $this -> config [ 'fulltext_postgres_min_word_len' ] || utf8_strlen ( $text [ $i ]) > $this -> config [ 'fulltext_postgres_max_word_len' ])
2007-07-22 22:23:00 +00:00
{
unset ( $text [ $i ]);
}
}
return array_values ( $text );
}
/**
2012-08-15 23:49:51 +05:30
* Performs a search on keywords depending on display specific params . You have to run split_keywords () first
2007-07-22 22:23:00 +00:00
*
* @ param string $type contains either posts or topics depending on what should be searched for
2010-02-10 10:31:00 +00:00
* @ param string $fields contains either titleonly ( topic titles should be searched ), msgonly ( only message bodies should be searched ), firstpost ( only subject and body of the first post should be searched ) or all ( all post bodies and subjects should be searched )
* @ param string $terms is either 'all' ( use query as entered , words without prefix should default to " have to be in field " ) or 'any' ( ignore search query parts and just return all posts that contain any of the specified words )
* @ param array $sort_by_sql contains SQL code for the ORDER BY part of a query
* @ param string $sort_key is the key of $sort_by_sql for the selected sorting
* @ param string $sort_dir is either a or d representing ASC and DESC
* @ param string $sort_days specifies the maximum amount of days a post may be old
* @ param array $ex_fid_ary specifies an array of forum ids which should not be searched
2012-08-30 22:20:52 +02:00
* @ param string $post_visibility specifies which types of posts the user can view in which forums
2010-02-10 10:31:00 +00:00
* @ param int $topic_id is set to 0 or a topic id , if it is not 0 then only posts in this topic should be searched
* @ param array $author_ary an array of author ids if the author should be ignored during the search the array is empty
* @ param string $author_name specifies the author match , when ANONYMOUS is also a search - match
2007-07-22 22:23:00 +00:00
* @ param array & $id_ary passed by reference , to be filled with ids for the page specified by $start and $per_page , should be ordered
* @ param int $start indicates the first index of the page
* @ param int $per_page number of ids each page is supposed to contain
* @ return boolean | int total number of results
*/
2013-03-03 20:06:52 +01:00
public function keyword_search ( $type , $fields , $terms , $sort_by_sql , $sort_key , $sort_dir , $sort_days , $ex_fid_ary , $post_visibility , $topic_id , $author_ary , $author_name , & $id_ary , & $start , $per_page )
2007-07-22 22:23:00 +00:00
{
2012-08-15 23:49:51 +05:30
// No keywords? No posts
2007-07-22 22:23:00 +00:00
if ( ! $this -> search_query )
{
return false ;
}
2012-08-18 00:26:36 +05:30
// When search query contains queries like -foo
if ( strpos ( $this -> search_query , '+' ) === false )
{
return false ;
}
2007-07-22 22:23:00 +00:00
// generate a search_key from all the options to identify the results
2015-08-15 14:46:09 +07:00
$search_key_array = array (
2007-07-22 22:23:00 +00:00
implode ( ', ' , $this -> split_words ),
$type ,
$fields ,
$terms ,
$sort_days ,
$sort_key ,
$topic_id ,
implode ( ',' , $ex_fid_ary ),
2012-08-30 22:20:52 +02:00
$post_visibility ,
2007-07-22 22:23:00 +00:00
implode ( ',' , $author_ary )
2015-08-15 14:46:09 +07:00
);
/**
* Allow changing the search_key for cached results
*
* @ event core . search_postgres_by_keyword_modify_search_key
* @ var array search_key_array Array with search parameters to generate the search_key
* @ var string type Searching type ( 'posts' , 'topics' )
* @ var string fields Searching fields ( 'titleonly' , 'msgonly' , 'firstpost' , 'all' )
* @ var string terms Searching terms ( 'all' , 'any' )
* @ var int sort_days Time , in days , of the oldest possible post to list
* @ var string sort_key The sort type used from the possible sort types
* @ var int topic_id Limit the search to this topic_id only
* @ var array ex_fid_ary Which forums not to search on
* @ var string post_visibility Post visibility data
* @ var array author_ary Array of user_id containing the users to filter the results to
* @ since 3.1 . 7 - RC1
*/
$vars = array (
'search_key_array' ,
'type' ,
'fields' ,
'terms' ,
'sort_days' ,
'sort_key' ,
'topic_id' ,
'ex_fid_ary' ,
'post_visibility' ,
'author_ary' ,
);
extract ( $this -> phpbb_dispatcher -> trigger_event ( 'core.search_postgres_by_keyword_modify_search_key' , compact ( $vars )));
$search_key = md5 ( implode ( '#' , $search_key_array ));
2007-07-22 22:23:00 +00:00
2012-11-10 15:35:05 +01:00
if ( $start < 0 )
{
$start = 0 ;
}
2007-07-22 22:23:00 +00:00
// try reading the results from cache
$result_count = 0 ;
if ( $this -> obtain_ids ( $search_key , $result_count , $id_ary , $start , $per_page , $sort_dir ) == SEARCH_RESULT_IN_CACHE )
{
return $result_count ;
}
$id_ary = array ();
$join_topic = ( $type == 'posts' ) ? false : true ;
// Build sql strings for sorting
$sql_sort = $sort_by_sql [ $sort_key ] . (( $sort_dir == 'a' ) ? ' ASC' : ' DESC' );
$sql_sort_table = $sql_sort_join = '' ;
switch ( $sql_sort [ 0 ])
{
case 'u' :
$sql_sort_table = USERS_TABLE . ' u, ' ;
$sql_sort_join = ( $type == 'posts' ) ? ' AND u.user_id = p.poster_id ' : ' AND u.user_id = t.topic_poster ' ;
break ;
case 't' :
$join_topic = true ;
break ;
case 'f' :
$sql_sort_table = FORUMS_TABLE . ' f, ' ;
$sql_sort_join = ' AND f.forum_id = p.forum_id ' ;
break ;
}
// Build some display specific sql strings
switch ( $fields )
{
case 'titleonly' :
$sql_match = 'p.post_subject' ;
$sql_match_where = ' AND p.post_id = t.topic_first_post_id' ;
$join_topic = true ;
break ;
case 'msgonly' :
$sql_match = 'p.post_text' ;
$sql_match_where = '' ;
break ;
case 'firstpost' :
$sql_match = 'p.post_subject, p.post_text' ;
$sql_match_where = ' AND p.post_id = t.topic_first_post_id' ;
$join_topic = true ;
break ;
default :
$sql_match = 'p.post_subject, p.post_text' ;
$sql_match_where = '' ;
break ;
}
2015-03-10 22:55:17 +00:00
$tsearch_query = $this -> tsearch_query ;
/**
* Allow changing the query used to search for posts using fulltext_postgres
*
* @ event core . search_postgres_keywords_main_query_before
* @ var string tsearch_query The parsed keywords used for this search
* @ var int result_count The previous result count for the format of the query .
* Set to 0 to force a re - count
* @ var bool join_topic Weather or not TOPICS_TABLE should be CROSS JOIN ' ED
* @ var array author_ary Array of user_id containing the users to filter the results to
* @ var string author_name An extra username to search on ( ! empty ( author_ary ) must be true , to be relevant )
* @ var array ex_fid_ary Which forums not to search on
* @ var int topic_id Limit the search to this topic_id only
* @ var string sql_sort_table Extra tables to include in the SQL query .
* Used in conjunction with sql_sort_join
* @ var string sql_sort_join SQL conditions to join all the tables used together .
* Used in conjunction with sql_sort_table
* @ var int sort_days Time , in days , of the oldest possible post to list
* @ var string sql_match Which columns to do the search on .
* @ var string sql_match_where Extra conditions to use to properly filter the matching process
* @ var string sort_by_sql The possible predefined sort types
* @ var string sort_key The sort type used from the possible sort types
* @ var string sort_dir " a " for ASC or " d " dor DESC for the sort order used
* @ var string sql_sort The result SQL when processing sort_by_sql + sort_key + sort_dir
* @ var int start How many posts to skip in the search results ( used for pagination )
2015-05-06 22:59:05 +01:00
* @ since 3.1 . 5 - RC1
2015-03-10 22:55:17 +00:00
*/
$vars = array (
'tsearch_query' ,
'result_count' ,
'join_topic' ,
'author_ary' ,
'author_name' ,
'ex_fid_ary' ,
'topic_id' ,
'sql_sort_table' ,
'sql_sort_join' ,
'sort_days' ,
'sql_match' ,
'sql_match_where' ,
'sort_by_sql' ,
'sort_key' ,
'sort_dir' ,
'sql_sort' ,
'start' ,
);
extract ( $this -> phpbb_dispatcher -> trigger_event ( 'core.search_postgres_keywords_main_query_before' , compact ( $vars )));
2018-01-06 16:06:59 +01:00
$sql_select = ( $type == 'posts' ) ? 'p.post_id' : 'DISTINCT t.topic_id, ' . $sort_by_sql [ $sort_key ];
2007-07-22 22:23:00 +00:00
$sql_from = ( $join_topic ) ? TOPICS_TABLE . ' t, ' : '' ;
$field = ( $type == 'posts' ) ? 'post_id' : 'topic_id' ;
2010-04-29 15:15:23 -04:00
2017-06-28 00:58:03 +07:00
if ( count ( $author_ary ) && $author_name )
2010-02-10 10:31:00 +00:00
{
// first one matches post of registered users, second one guests and deleted users
2012-07-22 16:50:09 +05:30
$sql_author = '(' . $this -> db -> sql_in_set ( 'p.poster_id' , array_diff ( $author_ary , array ( ANONYMOUS )), false , true ) . ' OR p.post_username ' . $author_name . ')' ;
2010-02-10 10:31:00 +00:00
}
2017-06-28 00:58:03 +07:00
else if ( count ( $author_ary ))
2010-02-10 10:31:00 +00:00
{
2012-07-22 16:50:09 +05:30
$sql_author = ' AND ' . $this -> db -> sql_in_set ( 'p.poster_id' , $author_ary );
2010-02-10 10:31:00 +00:00
}
else
{
$sql_author = '' ;
}
2010-04-29 15:15:23 -04:00
2007-07-22 22:23:00 +00:00
$sql_where_options = $sql_sort_join ;
$sql_where_options .= ( $topic_id ) ? ' AND p.topic_id = ' . $topic_id : '' ;
$sql_where_options .= ( $join_topic ) ? ' AND t.topic_id = p.topic_id' : '' ;
2017-06-28 00:58:03 +07:00
$sql_where_options .= ( count ( $ex_fid_ary )) ? ' AND ' . $this -> db -> sql_in_set ( 'p.forum_id' , $ex_fid_ary , true ) : '' ;
2012-08-30 22:20:52 +02:00
$sql_where_options .= ' AND ' . $post_visibility ;
2010-02-10 10:31:00 +00:00
$sql_where_options .= $sql_author ;
2007-07-22 22:23:00 +00:00
$sql_where_options .= ( $sort_days ) ? ' AND p.post_time >= ' . ( time () - ( $sort_days * 86400 )) : '' ;
$sql_where_options .= $sql_match_where ;
2012-08-12 01:25:01 +05:30
$sql_match = str_replace ( ',' , " || ' ' || " , $sql_match );
$tmp_sql_match = " to_tsvector (' " . $this -> db -> sql_escape ( $this -> config [ 'fulltext_postgres_ts_name' ]) . " ', " . $sql_match . " ) @@ to_tsquery (' " . $this -> db -> sql_escape ( $this -> config [ 'fulltext_postgres_ts_name' ]) . " ', ' " . $this -> db -> sql_escape ( $this -> tsearch_query ) . " ') " ;
2007-07-22 22:23:00 +00:00
2012-12-03 00:48:19 +05:30
$this -> db -> sql_transaction ( 'begin' );
2012-12-29 19:34:21 -05:00
$sql_from = " FROM $sql_from $sql_sort_table " . POSTS_TABLE . " p " ;
2012-08-12 01:25:01 +05:30
$sql_where = " WHERE ( " . $tmp_sql_match . " )
2012-12-29 19:34:21 -05:00
$sql_where_options " ;
2007-07-22 22:23:00 +00:00
$sql = " SELECT $sql_select
2012-12-29 19:34:21 -05:00
$sql_from
$sql_where
2007-07-22 22:23:00 +00:00
ORDER BY $sql_sort " ;
2012-07-22 16:50:09 +05:30
$result = $this -> db -> sql_query_limit ( $sql , $this -> config [ 'search_block_size' ], $start );
2007-07-22 22:23:00 +00:00
2012-07-22 16:50:09 +05:30
while ( $row = $this -> db -> sql_fetchrow ( $result ))
2007-07-22 22:23:00 +00:00
{
$id_ary [] = $row [ $field ];
}
2012-07-22 16:50:09 +05:30
$this -> db -> sql_freeresult ( $result );
2007-07-22 22:23:00 +00:00
$id_ary = array_unique ( $id_ary );
// if the total result count is not cached yet, retrieve it from the db
if ( ! $result_count )
{
2022-03-25 20:58:36 +07:00
$sql_count = " SELECT COUNT(DISTINCT " . (( $type == 'posts' ) ? 'p.post_id' : 't.topic_id' ) . " ) as result_count
2012-12-29 19:34:21 -05:00
$sql_from
$sql_where " ;
2012-12-03 00:48:19 +05:30
$result = $this -> db -> sql_query ( $sql_count );
$result_count = ( int ) $this -> db -> sql_fetchfield ( 'result_count' );
$this -> db -> sql_freeresult ( $result );
2007-07-22 22:23:00 +00:00
if ( ! $result_count )
{
return false ;
}
}
2012-12-03 00:48:19 +05:30
$this -> db -> sql_transaction ( 'commit' );
2012-11-10 15:35:05 +01:00
if ( $start >= $result_count )
{
$start = floor (( $result_count - 1 ) / $per_page ) * $per_page ;
2012-12-02 14:31:12 +05:30
$result = $this -> db -> sql_query_limit ( $sql , $this -> config [ 'search_block_size' ], $start );
2012-11-10 15:35:05 +01:00
2012-12-02 14:31:12 +05:30
while ( $row = $this -> db -> sql_fetchrow ( $result ))
{
$id_ary [] = $row [ $field ];
}
$this -> db -> sql_freeresult ( $result );
2012-11-10 15:35:05 +01:00
2012-12-02 14:31:12 +05:30
$id_ary = array_unique ( $id_ary );
}
2012-11-10 15:35:05 +01:00
2007-07-22 22:23:00 +00:00
// store the ids, from start on then delete anything that isn't on the current page because we only need ids for one page
$this -> save_ids ( $search_key , implode ( ' ' , $this -> split_words ), $author_ary , $result_count , $id_ary , $start , $sort_dir );
$id_ary = array_slice ( $id_ary , 0 , ( int ) $per_page );
return $result_count ;
}
/**
* Performs a search on an author ' s posts without caring about message contents . Depends on display specific params
*
2010-02-10 10:31:00 +00:00
* @ param string $type contains either posts or topics depending on what should be searched for
* @ param boolean $firstpost_only if true , only topic starting posts will be considered
* @ param array $sort_by_sql contains SQL code for the ORDER BY part of a query
* @ param string $sort_key is the key of $sort_by_sql for the selected sorting
* @ param string $sort_dir is either a or d representing ASC and DESC
* @ param string $sort_days specifies the maximum amount of days a post may be old
* @ param array $ex_fid_ary specifies an array of forum ids which should not be searched
2012-08-30 22:20:52 +02:00
* @ param string $post_visibility specifies which types of posts the user can view in which forums
2010-02-10 10:31:00 +00:00
* @ param int $topic_id is set to 0 or a topic id , if it is not 0 then only posts in this topic should be searched
* @ param array $author_ary an array of author ids
* @ param string $author_name specifies the author match , when ANONYMOUS is also a search - match
* @ param array & $id_ary passed by reference , to be filled with ids for the page specified by $start and $per_page , should be ordered
* @ param int $start indicates the first index of the page
* @ param int $per_page number of ids each page is supposed to contain
* @ return boolean | int total number of results
2007-07-22 22:23:00 +00:00
*/
2013-03-05 18:23:13 +01:00
public function author_search ( $type , $firstpost_only , $sort_by_sql , $sort_key , $sort_dir , $sort_days , $ex_fid_ary , $post_visibility , $topic_id , $author_ary , $author_name , & $id_ary , & $start , $per_page )
2007-07-22 22:23:00 +00:00
{
2012-08-15 23:49:51 +05:30
// No author? No posts
2017-06-28 00:58:03 +07:00
if ( ! count ( $author_ary ))
2007-07-22 22:23:00 +00:00
{
return 0 ;
}
// generate a search_key from all the options to identify the results
2015-08-15 14:46:09 +07:00
$search_key_array = array (
2007-07-22 22:23:00 +00:00
'' ,
$type ,
( $firstpost_only ) ? 'firstpost' : '' ,
'' ,
'' ,
$sort_days ,
$sort_key ,
$topic_id ,
implode ( ',' , $ex_fid_ary ),
2012-08-30 22:20:52 +02:00
$post_visibility ,
2010-02-10 10:31:00 +00:00
implode ( ',' , $author_ary ),
$author_name ,
2015-08-15 14:46:09 +07:00
);
/**
* Allow changing the search_key for cached results
*
* @ event core . search_postgres_by_author_modify_search_key
* @ var array search_key_array Array with search parameters to generate the search_key
* @ var string type Searching type ( 'posts' , 'topics' )
* @ var boolean firstpost_only Flag indicating if only topic starting posts are considered
* @ var int sort_days Time , in days , of the oldest possible post to list
* @ var string sort_key The sort type used from the possible sort types
* @ var int topic_id Limit the search to this topic_id only
* @ var array ex_fid_ary Which forums not to search on
* @ var string post_visibility Post visibility data
* @ var array author_ary Array of user_id containing the users to filter the results to
* @ var string author_name The username to search on
* @ since 3.1 . 7 - RC1
*/
$vars = array (
'search_key_array' ,
'type' ,
'firstpost_only' ,
'sort_days' ,
'sort_key' ,
'topic_id' ,
'ex_fid_ary' ,
'post_visibility' ,
'author_ary' ,
'author_name' ,
);
extract ( $this -> phpbb_dispatcher -> trigger_event ( 'core.search_postgres_by_author_modify_search_key' , compact ( $vars )));
$search_key = md5 ( implode ( '#' , $search_key_array ));
2007-07-22 22:23:00 +00:00
2012-11-10 15:44:16 +01:00
if ( $start < 0 )
{
$start = 0 ;
}
2007-07-22 22:23:00 +00:00
// try reading the results from cache
$result_count = 0 ;
if ( $this -> obtain_ids ( $search_key , $result_count , $id_ary , $start , $per_page , $sort_dir ) == SEARCH_RESULT_IN_CACHE )
{
return $result_count ;
}
$id_ary = array ();
2010-04-29 15:15:23 -04:00
2007-07-22 22:23:00 +00:00
// Create some display specific sql strings
2010-02-10 10:31:00 +00:00
if ( $author_name )
{
// first one matches post of registered users, second one guests and deleted users
2012-07-22 16:50:09 +05:30
$sql_author = '(' . $this -> db -> sql_in_set ( 'p.poster_id' , array_diff ( $author_ary , array ( ANONYMOUS )), false , true ) . ' OR p.post_username ' . $author_name . ')' ;
2010-02-10 10:31:00 +00:00
}
else
{
2012-07-22 16:50:09 +05:30
$sql_author = $this -> db -> sql_in_set ( 'p.poster_id' , $author_ary );
2010-02-10 10:31:00 +00:00
}
2017-06-28 00:58:03 +07:00
$sql_fora = ( count ( $ex_fid_ary )) ? ' AND ' . $this -> db -> sql_in_set ( 'p.forum_id' , $ex_fid_ary , true ) : '' ;
2007-07-22 22:23:00 +00:00
$sql_topic_id = ( $topic_id ) ? ' AND p.topic_id = ' . ( int ) $topic_id : '' ;
$sql_time = ( $sort_days ) ? ' AND p.post_time >= ' . ( time () - ( $sort_days * 86400 )) : '' ;
$sql_firstpost = ( $firstpost_only ) ? ' AND p.post_id = t.topic_first_post_id' : '' ;
// Build sql strings for sorting
$sql_sort = $sort_by_sql [ $sort_key ] . (( $sort_dir == 'a' ) ? ' ASC' : ' DESC' );
$sql_sort_table = $sql_sort_join = '' ;
switch ( $sql_sort [ 0 ])
{
case 'u' :
$sql_sort_table = USERS_TABLE . ' u, ' ;
$sql_sort_join = ( $type == 'posts' ) ? ' AND u.user_id = p.poster_id ' : ' AND u.user_id = t.topic_poster ' ;
break ;
case 't' :
2010-02-10 10:31:00 +00:00
$sql_sort_table = ( $type == 'posts' && ! $firstpost_only ) ? TOPICS_TABLE . ' t, ' : '' ;
$sql_sort_join = ( $type == 'posts' && ! $firstpost_only ) ? ' AND t.topic_id = p.topic_id ' : '' ;
2007-07-22 22:23:00 +00:00
break ;
case 'f' :
$sql_sort_table = FORUMS_TABLE . ' f, ' ;
$sql_sort_join = ' AND f.forum_id = p.forum_id ' ;
break ;
}
2012-08-30 22:20:52 +02:00
$m_approve_fid_sql = ' AND ' . $post_visibility ;
2010-04-29 15:15:23 -04:00
2015-03-11 19:58:23 +00:00
/**
* Allow changing the query used to search for posts by author in fulltext_postgres
*
* @ event core . search_postgres_author_count_query_before
* @ var int result_count The previous result count for the format of the query .
* Set to 0 to force a re - count
* @ var string sql_sort_table CROSS JOIN ' ed table to allow doing the sort chosen
* @ var string sql_sort_join Condition to define how to join the CROSS JOIN ' ed table specifyed in sql_sort_table
* @ var array author_ary Array of user_id containing the users to filter the results to
* @ var string author_name An extra username to search on
* @ var string sql_author SQL WHERE condition for the post author ids
* @ var int topic_id Limit the search to this topic_id only
* @ var string sql_topic_id SQL of topic_id
* @ var string sort_by_sql The possible predefined sort types
* @ var string sort_key The sort type used from the possible sort types
* @ var string sort_dir " a " for ASC or " d " dor DESC for the sort order used
* @ var string sql_sort The result SQL when processing sort_by_sql + sort_key + sort_dir
* @ var string sort_days Time , in days , that the oldest post showing can have
* @ var string sql_time The SQL to search on the time specifyed by sort_days
* @ var bool firstpost_only Wether or not to search only on the first post of the topics
* @ var array ex_fid_ary Forum ids that must not be searched on
* @ var array sql_fora SQL query for ex_fid_ary
* @ var string m_approve_fid_sql WHERE clause condition on post_visibility restrictions
* @ var int start How many posts to skip in the search results ( used for pagination )
2015-05-06 23:05:30 +01:00
* @ since 3.1 . 5 - RC1
2015-03-11 19:58:23 +00:00
*/
$vars = array (
'result_count' ,
'sql_sort_table' ,
'sql_sort_join' ,
'author_ary' ,
'author_name' ,
'sql_author' ,
'topic_id' ,
'sql_topic_id' ,
'sort_by_sql' ,
'sort_key' ,
'sort_dir' ,
'sql_sort' ,
'sort_days' ,
'sql_time' ,
'firstpost_only' ,
'ex_fid_ary' ,
'sql_fora' ,
'm_approve_fid_sql' ,
'start' ,
);
extract ( $this -> phpbb_dispatcher -> trigger_event ( 'core.search_postgres_author_count_query_before' , compact ( $vars )));
2007-07-22 22:23:00 +00:00
// Build the query for really selecting the post_ids
if ( $type == 'posts' )
{
$sql = " SELECT p.post_id
FROM " . $sql_sort_table . POSTS_TABLE . ' p' . (( $firstpost_only ) ? ', ' . TOPICS_TABLE . ' t ' : ' ') . "
WHERE $sql_author
$sql_topic_id
$sql_firstpost
$m_approve_fid_sql
$sql_fora
$sql_sort_join
$sql_time
ORDER BY $sql_sort " ;
$field = 'post_id' ;
}
else
{
$sql = " SELECT t.topic_id
FROM " . $sql_sort_table . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p
WHERE $sql_author
$sql_topic_id
$sql_firstpost
$m_approve_fid_sql
$sql_fora
AND t . topic_id = p . topic_id
$sql_sort_join
$sql_time
2010-02-10 10:31:00 +00:00
GROUP BY t . topic_id , $sort_by_sql [ $sort_key ]
2007-07-22 22:23:00 +00:00
ORDER BY $sql_sort " ;
$field = 'topic_id' ;
}
2012-12-03 01:07:47 +05:30
$this -> db -> sql_transaction ( 'begin' );
2007-07-22 22:23:00 +00:00
// Only read one block of posts from the db and then cache it
2012-07-22 16:50:09 +05:30
$result = $this -> db -> sql_query_limit ( $sql , $this -> config [ 'search_block_size' ], $start );
2007-07-22 22:23:00 +00:00
2012-07-22 16:50:09 +05:30
while ( $row = $this -> db -> sql_fetchrow ( $result ))
2007-07-22 22:23:00 +00:00
{
$id_ary [] = $row [ $field ];
}
2012-07-22 16:50:09 +05:30
$this -> db -> sql_freeresult ( $result );
2007-07-22 22:23:00 +00:00
// retrieve the total result count if needed
if ( ! $result_count )
{
2012-12-03 01:07:47 +05:30
if ( $type == 'posts' )
{
$sql_count = " SELECT COUNT(*) as result_count
FROM " . $sql_sort_table . POSTS_TABLE . ' p' . (( $firstpost_only ) ? ', ' . TOPICS_TABLE . ' t ' : ' ') . "
WHERE $sql_author
$sql_topic_id
$sql_firstpost
$m_approve_fid_sql
$sql_fora
$sql_sort_join
$sql_time " ;
}
else
{
$sql_count = " SELECT COUNT(*) as result_count
FROM " . $sql_sort_table . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p
WHERE $sql_author
$sql_topic_id
$sql_firstpost
$m_approve_fid_sql
$sql_fora
AND t . topic_id = p . topic_id
$sql_sort_join
$sql_time
GROUP BY t . topic_id , $sort_by_sql [ $sort_key ] " ;
}
2021-11-01 00:51:45 +07:00
$result = $this -> db -> sql_query ( $sql_count );
$result_count = ( $type == 'posts' ) ? ( int ) $this -> db -> sql_fetchfield ( 'result_count' ) : count ( $this -> db -> sql_fetchrowset ( $result ));
$this -> db -> sql_freeresult ( $result );
2007-07-22 22:23:00 +00:00
if ( ! $result_count )
{
return false ;
}
}
2012-12-03 01:07:47 +05:30
$this -> db -> sql_transaction ( 'commit' );
2012-11-10 15:44:16 +01:00
if ( $start >= $result_count )
{
$start = floor (( $result_count - 1 ) / $per_page ) * $per_page ;
2012-12-02 14:31:12 +05:30
$result = $this -> db -> sql_query_limit ( $sql , $this -> config [ 'search_block_size' ], $start );
while ( $row = $this -> db -> sql_fetchrow ( $result ))
{
$id_ary [] = ( int ) $row [ $field ];
}
$this -> db -> sql_freeresult ( $result );
2012-11-10 15:44:16 +01:00
2012-12-02 14:31:12 +05:30
$id_ary = array_unique ( $id_ary );
}
2012-11-10 15:44:16 +01:00
2017-06-28 00:58:03 +07:00
if ( count ( $id_ary ))
2007-07-22 22:23:00 +00:00
{
$this -> save_ids ( $search_key , '' , $author_ary , $result_count , $id_ary , $start , $sort_dir );
$id_ary = array_slice ( $id_ary , 0 , $per_page );
return $result_count ;
}
return false ;
}
/**
2013-09-16 05:20:27 +02:00
* Destroys cached search results , that contained one of the new words in a post so the results won ' t be outdated
2007-07-22 22:23:00 +00:00
*
2012-06-23 02:14:46 +05:30
* @ param string $mode contains the post mode : edit , post , reply , quote ...
* @ param int $post_id contains the post id of the post to index
* @ param string $message contains the post text of the post
* @ param string $subject contains the subject of the post to index
* @ param int $poster_id contains the user id of the poster
* @ param int $forum_id contains the forum id of parent forum of the post
2007-07-22 22:23:00 +00:00
*/
2012-08-10 11:30:02 +05:30
public function index ( $mode , $post_id , & $message , & $subject , $poster_id , $forum_id )
2007-07-22 22:23:00 +00:00
{
2013-09-19 15:27:03 +02:00
// Split old and new post/subject to obtain array of words
2007-07-22 22:23:00 +00:00
$split_text = $this -> split_message ( $message );
$split_title = ( $subject ) ? $this -> split_message ( $subject ) : array ();
$words = array_unique ( array_merge ( $split_text , $split_title ));
2018-01-28 16:14:29 +01:00
/**
* Event to modify method arguments and words before the PostgreSQL search index is updated
*
* @ event core . search_postgres_index_before
* @ var string mode Contains the post mode : edit , post , reply , quote
* @ var int post_id The id of the post which is modified / created
* @ var string message New or updated post content
* @ var string subject New or updated post subject
* @ var int poster_id Post author ' s user id
* @ var int forum_id The id of the forum in which the post is located
* @ var array words Array of words added to the index
* @ var array split_text Array of words from the message
* @ var array split_title Array of words from the title
* @ since 3.2 . 3 - RC1
*/
$vars = array (
'mode' ,
'post_id' ,
'message' ,
'subject' ,
'poster_id' ,
'forum_id' ,
'words' ,
'split_text' ,
'split_title' ,
);
extract ( $this -> phpbb_dispatcher -> trigger_event ( 'core.search_postgres_index_before' , compact ( $vars )));
2007-07-22 22:23:00 +00:00
unset ( $split_text );
unset ( $split_title );
// destroy cached search results containing any of the words removed or added
$this -> destroy_cache ( $words , array ( $poster_id ));
unset ( $words );
}
/**
* Destroy cached results , that might be outdated after deleting a post
*/
2012-08-10 11:30:02 +05:30
public function index_remove ( $post_ids , $author_ids , $forum_ids )
2007-07-22 22:23:00 +00:00
{
$this -> destroy_cache ( array (), $author_ids );
}
/**
* Destroy old cache entries
*/
2012-08-10 11:30:02 +05:30
public function tidy ()
2007-07-22 22:23:00 +00:00
{
// destroy too old cached search results
$this -> destroy_cache ( array ());
2015-01-11 17:32:31 +01:00
$this -> config -> set ( 'search_last_gc' , time (), false );
2007-07-22 22:23:00 +00:00
}
/**
* Create fulltext index
2012-06-23 02:14:46 +05:30
*
* @ return string | bool error string is returned incase of errors otherwise false
2007-07-22 22:23:00 +00:00
*/
2012-08-10 11:30:02 +05:30
public function create_index ( $acp_module , $u_action )
2007-07-22 22:23:00 +00:00
{
// Make sure we can actually use PostgreSQL with fulltext indexes
if ( $error = $this -> init ())
{
return $error ;
}
if ( empty ( $this -> stats ))
{
$this -> get_stats ();
}
2018-02-16 21:31:36 +01:00
$sql_queries = [];
2007-07-22 22:23:00 +00:00
if ( ! isset ( $this -> stats [ 'post_subject' ]))
{
2018-02-16 21:31:36 +01:00
$sql_queries [] = " CREATE INDEX " . POSTS_TABLE . " _ " . $this -> config [ 'fulltext_postgres_ts_name' ] . " _post_subject ON " . POSTS_TABLE . " USING gin (to_tsvector (' " . $this -> db -> sql_escape ( $this -> config [ 'fulltext_postgres_ts_name' ]) . " ', post_subject)) " ;
2007-07-22 22:23:00 +00:00
}
2012-08-12 01:40:30 +05:30
if ( ! isset ( $this -> stats [ 'post_content' ]))
{
2020-01-26 13:11:55 +01:00
$sql_queries [] = " CREATE INDEX " . POSTS_TABLE . " _ " . $this -> config [ 'fulltext_postgres_ts_name' ] . " _post_content ON " . POSTS_TABLE . " USING gin (to_tsvector (' " . $this -> db -> sql_escape ( $this -> config [ 'fulltext_postgres_ts_name' ]) . " ', post_text)) " ;
}
if ( ! isset ( $this -> stats [ 'post_subject_content' ]))
{
$sql_queries [] = " CREATE INDEX " . POSTS_TABLE . " _ " . $this -> config [ 'fulltext_postgres_ts_name' ] . " _post_subject_content ON " . POSTS_TABLE . " USING gin (to_tsvector (' " . $this -> db -> sql_escape ( $this -> config [ 'fulltext_postgres_ts_name' ]) . " ', post_subject || ' ' || post_text)) " ;
2018-02-16 21:31:36 +01:00
}
$stats = $this -> stats ;
/**
* Event to modify SQL queries before the Postgres search index is created
*
* @ event core . search_postgres_create_index_before
* @ var array sql_queries Array with queries for creating the search index
* @ var array stats Array with statistics of the current index ( read only )
* @ since 3.2 . 3 - RC1
*/
$vars = array (
'sql_queries' ,
'stats' ,
);
extract ( $this -> phpbb_dispatcher -> trigger_event ( 'core.search_postgres_create_index_before' , compact ( $vars )));
foreach ( $sql_queries as $sql_query )
{
$this -> db -> sql_query ( $sql_query );
2012-08-12 01:40:30 +05:30
}
2012-07-22 16:50:09 +05:30
$this -> db -> sql_query ( 'TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE );
2007-07-22 22:23:00 +00:00
return false ;
}
/**
* Drop fulltext index
2012-06-23 02:14:46 +05:30
*
* @ return string | bool error string is returned incase of errors otherwise false
2007-07-22 22:23:00 +00:00
*/
2012-08-10 11:30:02 +05:30
public function delete_index ( $acp_module , $u_action )
2007-07-22 22:23:00 +00:00
{
// Make sure we can actually use PostgreSQL with fulltext indexes
if ( $error = $this -> init ())
{
return $error ;
}
if ( empty ( $this -> stats ))
{
$this -> get_stats ();
}
2018-02-16 21:31:36 +01:00
$sql_queries = [];
2007-07-22 22:23:00 +00:00
if ( isset ( $this -> stats [ 'post_subject' ]))
{
2018-02-16 21:31:36 +01:00
$sql_queries [] = 'DROP INDEX ' . $this -> stats [ 'post_subject' ][ 'relname' ];
2007-07-22 22:23:00 +00:00
}
2012-08-12 01:40:30 +05:30
if ( isset ( $this -> stats [ 'post_content' ]))
{
2018-02-16 21:31:36 +01:00
$sql_queries [] = 'DROP INDEX ' . $this -> stats [ 'post_content' ][ 'relname' ];
}
2020-01-26 13:11:55 +01:00
if ( isset ( $this -> stats [ 'post_subject_content' ]))
{
$sql_queries [] = 'DROP INDEX ' . $this -> stats [ 'post_subject_content' ][ 'relname' ];
}
2018-02-16 21:31:36 +01:00
$stats = $this -> stats ;
/**
* Event to modify SQL queries before the Postgres search index is created
*
* @ event core . search_postgres_delete_index_before
* @ var array sql_queries Array with queries for deleting the search index
* @ var array stats Array with statistics of the current index ( read only )
* @ since 3.2 . 3 - RC1
*/
$vars = array (
'sql_queries' ,
'stats' ,
);
extract ( $this -> phpbb_dispatcher -> trigger_event ( 'core.search_postgres_delete_index_before' , compact ( $vars )));
foreach ( $sql_queries as $sql_query )
{
$this -> db -> sql_query ( $sql_query );
2012-08-12 01:40:30 +05:30
}
2012-07-22 16:50:09 +05:30
$this -> db -> sql_query ( 'TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE );
2007-07-22 22:23:00 +00:00
return false ;
}
/**
* Returns true if both FULLTEXT indexes exist
*/
2012-08-10 11:30:02 +05:30
public function index_created ()
2007-07-22 22:23:00 +00:00
{
if ( empty ( $this -> stats ))
{
$this -> get_stats ();
}
2013-08-26 15:09:01 +05:30
return ( isset ( $this -> stats [ 'post_subject' ]) && isset ( $this -> stats [ 'post_content' ])) ? true : false ;
2007-07-22 22:23:00 +00:00
}
/**
* Returns an associative array containing information about the indexes
*/
2012-08-10 11:30:02 +05:30
public function index_stats ()
2007-07-22 22:23:00 +00:00
{
if ( empty ( $this -> stats ))
{
$this -> get_stats ();
}
return array (
2012-07-22 16:50:09 +05:30
$this -> user -> lang [ 'FULLTEXT_POSTGRES_TOTAL_POSTS' ] => ( $this -> index_created ()) ? $this -> stats [ 'total_posts' ] : 0 ,
2007-07-22 22:23:00 +00:00
);
}
2012-06-23 02:14:46 +05:30
/**
* Computes the stats and store them in the $this -> stats associative array
*/
2012-08-14 17:47:01 +05:30
protected function get_stats ()
2007-07-22 22:23:00 +00:00
{
2014-06-26 17:17:35 +02:00
if ( $this -> db -> get_sql_layer () != 'postgres' )
2012-06-10 17:13:03 +05:30
{
$this -> stats = array ();
return ;
}
2007-07-22 22:23:00 +00:00
$sql = " SELECT c2.relname, pg_catalog.pg_get_indexdef(i.indexrelid, 0, true) AS indexdef
FROM pg_catalog . pg_class c1 , pg_catalog . pg_index i , pg_catalog . pg_class c2
WHERE c1 . relname = '" . POSTS_TABLE . "'
AND pg_catalog . pg_table_is_visible ( c1 . oid )
AND c1 . oid = i . indrelid
AND i . indexrelid = c2 . oid " ;
2012-07-22 16:50:09 +05:30
$result = $this -> db -> sql_query ( $sql );
2007-07-22 22:23:00 +00:00
2012-07-22 16:50:09 +05:30
while ( $row = $this -> db -> sql_fetchrow ( $result ))
2007-07-22 22:23:00 +00:00
{
// deal with older PostgreSQL versions which didn't use Index_type
if ( strpos ( $row [ 'indexdef' ], 'to_tsvector' ) !== false )
{
2013-08-26 15:09:01 +05:30
if ( $row [ 'relname' ] == POSTS_TABLE . '_' . $this -> config [ 'fulltext_postgres_ts_name' ] . '_post_subject' || $row [ 'relname' ] == POSTS_TABLE . '_post_subject' )
2007-07-22 22:23:00 +00:00
{
$this -> stats [ 'post_subject' ] = $row ;
}
2012-08-12 01:40:30 +05:30
else if ( $row [ 'relname' ] == POSTS_TABLE . '_' . $this -> config [ 'fulltext_postgres_ts_name' ] . '_post_content' || $row [ 'relname' ] == POSTS_TABLE . '_post_content' )
{
$this -> stats [ 'post_content' ] = $row ;
}
2020-01-26 13:11:55 +01:00
else if ( $row [ 'relname' ] == POSTS_TABLE . '_' . $this -> config [ 'fulltext_postgres_ts_name' ] . '_post_subject_content' || $row [ 'relname' ] == POSTS_TABLE . '_post_subject_content' )
{
$this -> stats [ 'post_subject_content' ] = $row ;
}
2007-07-22 22:23:00 +00:00
}
}
2012-07-22 16:50:09 +05:30
$this -> db -> sql_freeresult ( $result );
2007-07-22 22:23:00 +00:00
2012-07-22 16:50:09 +05:30
$this -> stats [ 'total_posts' ] = $this -> config [ 'num_posts' ];
2007-07-22 22:23:00 +00:00
}
/**
2012-06-23 02:14:46 +05:30
* Display various options that can be configured for the backend from the acp
*
* @ return associative array containing template and config variables
2007-07-22 22:23:00 +00:00
*/
2012-08-10 11:30:02 +05:30
public function acp ()
2007-07-22 22:23:00 +00:00
{
$tpl = '
< dl >
2012-07-22 16:50:09 +05:30
< dt >< label > ' . $this->user->lang[' FULLTEXT_POSTGRES_VERSION_CHECK '] . ' </ label >< br />< span > ' . $this->user->lang[' FULLTEXT_POSTGRES_VERSION_CHECK_EXPLAIN '] . ' </ span ></ dt >
2014-06-25 21:48:24 +02:00
< dd > ' . (($this->db->get_sql_layer() == ' postgres ') ? $this->user->lang[' YES '] : $this->user->lang[' NO ']) . ' </ dd >
2007-07-22 22:23:00 +00:00
</ dl >
< dl >
2012-07-22 16:50:09 +05:30
< dt >< label > ' . $this->user->lang[' FULLTEXT_POSTGRES_TS_NAME '] . ' </ label >< br />< span > ' . $this->user->lang[' FULLTEXT_POSTGRES_TS_NAME_EXPLAIN '] . ' </ span ></ dt >
2007-07-22 22:23:00 +00:00
< dd >< select name = " config[fulltext_postgres_ts_name] " > ' ;
2014-06-25 21:48:24 +02:00
if ( $this -> db -> get_sql_layer () == 'postgres' )
2007-07-22 22:23:00 +00:00
{
2012-06-10 17:11:30 +05:30
$sql = ' SELECT cfgname AS ts_name
FROM pg_ts_config ' ;
2012-07-22 16:50:09 +05:30
$result = $this -> db -> sql_query ( $sql );
2007-07-22 22:23:00 +00:00
2012-07-22 16:50:09 +05:30
while ( $row = $this -> db -> sql_fetchrow ( $result ))
2007-07-22 22:23:00 +00:00
{
2012-07-22 16:50:09 +05:30
$tpl .= '<option value="' . $row [ 'ts_name' ] . '"' . ( $row [ 'ts_name' ] === $this -> config [ 'fulltext_postgres_ts_name' ] ? ' selected="selected"' : '' ) . '>' . $row [ 'ts_name' ] . '</option>' ;
2007-07-22 22:23:00 +00:00
}
2012-07-22 16:50:09 +05:30
$this -> db -> sql_freeresult ( $result );
2007-07-22 22:23:00 +00:00
}
else
{
2012-07-22 16:50:09 +05:30
$tpl .= '<option value="' . $this -> config [ 'fulltext_postgres_ts_name' ] . '" selected="selected">' . $this -> config [ 'fulltext_postgres_ts_name' ] . '</option>' ;
2007-07-22 22:23:00 +00:00
}
$tpl .= ' </ select ></ dd >
</ dl >
< dl >
2012-11-10 00:30:46 +01:00
< dt >< label for = " fulltext_postgres_min_word_len " > ' . $this->user->lang[' FULLTEXT_POSTGRES_MIN_WORD_LEN '] . $this->user->lang[' COLON '] . ' </ label >< br />< span > ' . $this->user->lang[' FULLTEXT_POSTGRES_MIN_WORD_LEN_EXPLAIN '] . ' </ span ></ dt >
2015-11-06 10:20:05 +01:00
< dd >< input id = " fulltext_postgres_min_word_len " type = " number " min = " 0 " max = " 255 " name = " config[fulltext_postgres_min_word_len] " value = " ' . (int) $this->config ['fulltext_postgres_min_word_len'] . ' " /></ dd >
2007-07-22 22:23:00 +00:00
</ dl >
< dl >
2012-11-10 00:30:46 +01:00
< dt >< label for = " fulltext_postgres_max_word_len " > ' . $this->user->lang[' FULLTEXT_POSTGRES_MAX_WORD_LEN '] . $this->user->lang[' COLON '] . ' </ label >< br />< span > ' . $this->user->lang[' FULLTEXT_POSTGRES_MAX_WORD_LEN_EXPLAIN '] . ' </ span ></ dt >
2015-11-06 10:20:05 +01:00
< dd >< input id = " fulltext_postgres_max_word_len " type = " number " min = " 0 " max = " 255 " name = " config[fulltext_postgres_max_word_len] " value = " ' . (int) $this->config ['fulltext_postgres_max_word_len'] . ' " /></ dd >
2007-07-22 22:23:00 +00:00
</ dl >
' ;
// These are fields required in the config table
return array (
'tpl' => $tpl ,
'config' => array ( 'fulltext_postgres_ts_name' => 'string' , 'fulltext_postgres_min_word_len' => 'integer:0:255' , 'fulltext_postgres_max_word_len' => 'integer:0:255' )
);
}
}