Version 4.1.19

This commit is contained in:
Neo committed 2025-12-19 05:38:56 -08:00
1 parent 28bd025b35
commit 2bd5025018
2674 files changed
+233518 -77766

No files matched your search

+155 -33
View File
@@ -2,9 +2,9 @@
/**
* @brief Abstract Search Query
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @package IPS Community Suite
* @since 21 Aug 2014
* @version SVN_VERSION_NUMBER
*/
@@ -27,6 +27,7 @@ abstract class _Query
const TERM_AND_TAGS = 2;
const TERM_OR_MODE = 4;
const TERM_TITLES_ONLY = 8;
const TAGS_MATCH_ITEMS_ONLY = 16;
const HIDDEN_VISIBLE = 0;
const HIDDEN_UNAPPROVED = 1;
@@ -80,22 +81,13 @@ abstract class _Query
/* Exclude disabled applications */
$filters = array();
foreach ( \IPS\Application::applications() as $application )
foreach ( \IPS\Content::routedClasses( $member, FALSE, TRUE ) as $class )
{
if ( !$application->enabled )
{
foreach ( $application->extensions( 'core', 'ContentRouter' ) as $extension )
{
foreach ( $extension->classes as $class )
{
$filters[] = \IPS\Content\Search\ContentFilter::init( $class );
}
}
}
$filters[] = \IPS\Content\Search\ContentFilter::init( $class );
}
if ( !empty( $filters ) )
{
$this->filterByContent( $filters, FALSE );
$this->filterByContent( $filters );
}
}
@@ -231,6 +223,26 @@ abstract class _Query
*/
abstract public function search( $term = NULL, $tags = NULL, $method = 1 );
/**
* Get the default date cut off
*
* @return string
*/
public function getDefaultDateCutOff()
{
return 'any';
}
/**
* Get the default sort method
*
* @return string
*/
public function getDefaultSortMethod()
{
return 'relevancy';
}
/**
* Get count
*
@@ -256,38 +268,148 @@ abstract class _Query
}
/**
* Term as words array
* Returns an array of words. A word is considered as either an entire phrase (eg "sticks stones") when $ignorePhrase is FALSE, or a sequence of characters delimited by a space.
* Words smaller than 2 characters are ignored.
* Convert the term into an array of words
*
* @param string $term The term to search for
* @param boolean $ignorePhrase When true, phrases are stripped of quotes and treated as normal words
* @param int $minLength The minimum length a sequence of characters has to be before it is considered a word
* @param string $term The term to search for
* @param boolean $ignorePhrase When true, phrases are stripped of quotes and treated as normal words
* @param int|NULL $minLength The minimum length a sequence of characters has to be before it is considered a word. If null, ft_min_word_len/innodb_ft_min_token_size is used.
* @param int|NULL $maxLength The maximum length a sequence of characters can be for it to be considered a word. If null, ft_max_word_len/innodb_ft_max_token_size is used.
* @return array
*/
public static function termAsWordsArray( $term, $ignorePhrase=FALSE, $minLength=3 )
{
if ( static::termIsPhrase( $term ) )
public static function termAsWordsArray( $term, $ignorePhrase=FALSE, $minLength=NULL, $maxLength=NULL )
{
/* If we haven't set a preferred min/max length, use the MySQL configuration */
if ( $minLength === NULL or $maxLength === NULL )
{
if ( ! $ignorePhrase )
/* If we don't already know what they are, get the values from the MySQL configuration */
if ( ( $minLength === NULL and !isset( \IPS\Data\Store::i()->mysqlMinWord ) ) or ( $maxLength === NULL and !isset( \IPS\Data\Store::i()->mysqlMaxWord ) ) )
{
return array( $term );
/* The variable we need depends on whether the table is MyISAM or InnoDB */
$tableDefinition = \IPS\Db::i()->getTableDefinition('core_search_index');
if ( $tableDefinition['engine'] == 'InnoDB' )
{
$minVariable = 'innodb_ft_min_token_size';
$maxVariable = 'innodb_ft_max_token_size';
}
else
{
$minVariable = 'ft_min_word_len';
$maxVariable = 'ft_max_word_len';
}
/* Now fetch those */
try
{
foreach ( new \IPS\Db\Select( 'SHOW VARIABLES WHERE Variable_Name=? OR Variable_Name=?', array( $minVariable, $maxVariable ), \IPS\Db::i() ) as $row )
{
if ( $row['Variable_name'] === $minVariable )
{
\IPS\Data\Store::i()->mysqlMinWord = intval( $row['Value'] );
}
elseif ( $row['Variable_name'] === $maxVariable )
{
\IPS\Data\Store::i()->mysqlMaxWord = intval( $row['Value'] );
}
}
}
catch( \IPS\Db\Exception $e ) { }
/* If we weren't able to get them, set sensible defaults */
if ( !isset( \IPS\Data\Store::i()->mysqlMinWord ) )
{
\IPS\Data\Store::i()->mysqlMinWord = 3;
}
if ( !isset( \IPS\Data\Store::i()->mysqlMaxWord ) )
{
\IPS\Data\Store::i()->mysqlMaxWord = 84;
}
}
else
/* Set */
if ( $minLength === NULL )
{
$term = str_replace( '"', '', $term );
$minLength = \IPS\Data\Store::i()->mysqlMinWord;
}
if ( $maxLength === NULL )
{
$maxLength = \IPS\Data\Store::i()->mysqlMaxWord;
}
}
$theWords = array();
foreach( explode( ' ', $term ) as $_term )
/* Sub quotes with smaller than min word strings can cause issues for larger tables, so we convert the sub quote into normal words for a boolean search */
if ( ! static::termIsPhrase( $term ) )
{
if ( mb_strlen( $_term ) > $minLength )
preg_match_all( '#"([^"]+?)"#', $term, $matches, PREG_SET_ORDER );
foreach( $matches as $match )
{
$theWords[] = $_term;
$allWordsInPhraseAreGood = true;
$subWords = array();
foreach( explode( ' ', $match[1] ) as $subWord )
{
if ( mb_strlen( $subWord ) <= $minLength or mb_strlen( $subWord ) >= $maxLength )
{
$allWordsInPhraseAreGood = false;
}
else
{
$subWords[] = $subWord;
}
}
if ( ! $allWordsInPhraseAreGood )
{
$term = str_replace( $match[0], implode( ' ', $subWords ), $term );
}
}
}
return $theWords;
/* Parse */
$words = array();
$currentWord = '';
$inQuote = false;
$termLength = mb_strlen( $term );
for ( $i = 0; $i < $termLength; $i++ )
{
$c = mb_substr( $term, $i, 1 );
if ( $c == '"' )
{
if ( $ignorePhrase )
{
continue;
}
$inQuote = !$inQuote;
}
elseif ( $c == ' ' and !$inQuote )
{
$words[] = trim( $currentWord );
$currentWord = '';
}
$currentWord .= $c;
}
$words[] = trim( $currentWord );
/* Now check each of the words is acceptable */
$finalWords = array();
foreach( $words as $word )
{
if ( mb_strlen( $word ) >= $minLength and mb_strlen( $word ) <= $maxLength )
{
$finalWords[] = $word;
}
}
/* And return */
return $finalWords;
}
/**
* Is a rebuild task running?
*
* @return boolean
*/
public static function isRebuildRunning()
{
return \IPS\Db::i()->select( 'COUNT(*)', 'core_queue', array( '`key`=?', 'RebuildSearchIndex' ) )->first() ? TRUE : FALSE;
}
}