Version 4.1.2
This commit is contained in:
1 parent
3ba79295ee
commit
28bd025b35
1131 files changed
+63658
-20579
No files matched your search
+116
-105
@@ -25,6 +25,8 @@ abstract class _Query
|
||||
{
|
||||
const TERM_OR_TAGS = 1;
|
||||
const TERM_AND_TAGS = 2;
|
||||
const TERM_OR_MODE = 4;
|
||||
const TERM_TITLES_ONLY = 8;
|
||||
|
||||
const HIDDEN_VISIBLE = 0;
|
||||
const HIDDEN_UNAPPROVED = 1;
|
||||
@@ -34,6 +36,8 @@ abstract class _Query
|
||||
const ORDER_NEWEST_UPDATED = 1;
|
||||
const ORDER_NEWEST_CREATED = 2;
|
||||
const ORDER_RELEVANCY = 3;
|
||||
const ORDER_OLDEST_UPDATED = 4;
|
||||
const ORDER_OLDEST_CREATED = 5;
|
||||
|
||||
const SUPPORTS_JOIN_FILTERS = TRUE;
|
||||
|
||||
@@ -45,8 +49,7 @@ abstract class _Query
|
||||
*/
|
||||
public static function init( \IPS\Member $member = NULL )
|
||||
{
|
||||
$class = '\\IPS\\Content\\Search\\' . ucfirst( \IPS\Settings::i()->search_engine ) . '\\Query';
|
||||
return new $class( $member ?: \IPS\Member::loggedIn() );
|
||||
return new \IPS\Content\Search\Mysql\Query( $member ?: \IPS\Member::loggedIn() );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,7 +61,7 @@ abstract class _Query
|
||||
* @brief The member performing the search
|
||||
*/
|
||||
protected $member;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@@ -69,129 +72,90 @@ abstract class _Query
|
||||
{
|
||||
$this->member = $member;
|
||||
|
||||
/* Exclude hidden items */
|
||||
if ( !$member->modPermission('can_view_hidden_content') )
|
||||
{
|
||||
$this->setHiddenFilter( static::HIDDEN_VISIBLE );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exclude "first post" content items
|
||||
* Useful for cases such as activity streams where you do not want both the topic and the first post to show
|
||||
*
|
||||
* @return \IPS\Content\Search\Query (for daisy chaining)
|
||||
*/
|
||||
public function excludeFirstPostContentItems()
|
||||
{
|
||||
$classes = array();
|
||||
foreach ( \IPS\Content::routedClasses( TRUE, FALSE, TRUE ) as $class )
|
||||
{
|
||||
if ( in_array( 'IPS\Content\Searchable', class_implements( $class ) ) and $class::$firstCommentRequired )
|
||||
{
|
||||
$classes[] = $class;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !empty( $classes ) )
|
||||
/* Exclude disabled applications */
|
||||
$filters = array();
|
||||
foreach ( \IPS\Application::applications() as $application )
|
||||
{
|
||||
return $this->filterByExcludeContent( $classes );
|
||||
if ( !$application->enabled )
|
||||
{
|
||||
foreach ( $application->extensions( 'core', 'ContentRouter' ) as $extension )
|
||||
{
|
||||
foreach ( $extension->classes as $class )
|
||||
{
|
||||
$filters[] = \IPS\Content\Search\ContentFilter::init( $class );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if ( !empty( $filters ) )
|
||||
{
|
||||
return $this;
|
||||
$this->filterByContent( $filters, FALSE );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Exclude disabled applications
|
||||
* Filter by multiple content types
|
||||
*
|
||||
* @param array $contentFilters Array of \IPS\Content\Search\ContentFilter objects
|
||||
* @param bool $type TRUE means only include results matching the filters, FALSE means exclude all results matching the filters
|
||||
* @return \IPS\Content\Search\Query (for daisy chaining)
|
||||
*/
|
||||
public function excludeDisabledApps()
|
||||
{
|
||||
$includeClasses = array();
|
||||
foreach ( \IPS\Content::routedClasses( TRUE, FALSE, TRUE ) as $class )
|
||||
{
|
||||
if ( in_array( 'IPS\Content\Searchable', class_implements( $class ) ) )
|
||||
{
|
||||
$includeClasses[] = $class;
|
||||
|
||||
if ( isset( $class::$commentClass ) )
|
||||
{
|
||||
$includeClasses[] = $class::$commentClass;
|
||||
}
|
||||
if ( isset( $class::$reviewClass ) )
|
||||
{
|
||||
$includeClasses[] = $class::$reviewClass;
|
||||
}
|
||||
}
|
||||
}
|
||||
$allClasses = array();
|
||||
foreach ( \IPS\Content::routedClasses( FALSE, FALSE, TRUE ) as $class )
|
||||
{
|
||||
if ( in_array( 'IPS\Content\Searchable', class_implements( $class ) ) )
|
||||
{
|
||||
$allClasses[] = $class;
|
||||
|
||||
if ( isset( $class::$commentClass ) )
|
||||
{
|
||||
$allClasses[] = $class::$commentClass;
|
||||
}
|
||||
if ( isset( $class::$reviewClass ) )
|
||||
{
|
||||
$allClasses[] = $class::$reviewClass;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$classes = array_diff( $allClasses, $includeClasses );
|
||||
abstract public function filterByContent( array $contentFilters, $type = TRUE );
|
||||
|
||||
if ( !empty( $classes ) )
|
||||
{
|
||||
return $this->filterByExcludeContent( $classes );
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter by content type
|
||||
*
|
||||
* @param string $class The type of content to search (including all comment/review classes)
|
||||
* @param array|NULL $containers An array of container IDs to filter by, or NULL to not filter by containers
|
||||
* @param int|NULL $minimumComments The minimum number of comments
|
||||
* @param int|NULL $minimumReviews The minimum number of reviews
|
||||
* @param int|NULL $minimumViews The minimum number of views
|
||||
* @return \IPS\Content\Search\Query (for daisy chaining)
|
||||
*/
|
||||
abstract public function filterByContent( $class, $containers = NULL, $minimumComments = NULL, $minimumReviews = NULL, $minimumViews = NULL );
|
||||
|
||||
/**
|
||||
* Filter by content type to exclude
|
||||
*
|
||||
* @param string $classes The types of content to search (not including all comment/review classes)
|
||||
* @param bool $allowedContiners If TRUE, $class should be an array of allowed containers for that class - e.g. array( 'IPS\forums\Topic' => array( 1, 2 ) - otherwise, a simple array - e.g. array( 'IPS\forums\Topic' )
|
||||
* @return \IPS\Content\Search\Query (for daisy chaining)
|
||||
*/
|
||||
abstract public function filterByExcludeContent( array $classes, $allowedContiners=FALSE );
|
||||
|
||||
/**
|
||||
* Filter by content item
|
||||
*
|
||||
* @param \IPS\Content\Item $item The item
|
||||
* @return \IPS\Content\Search\Query (for daisy chaining)
|
||||
*/
|
||||
abstract public function filterByItem( \IPS\Content\Item $item );
|
||||
|
||||
/**
|
||||
* Filter by author
|
||||
*
|
||||
* @param \IPS\Member|int|array $author The author, or an array of author IDs
|
||||
* @return \IPS\Content\Search\Query (for daisy chaining)
|
||||
*/
|
||||
abstract public function filterByAuthor( $author );
|
||||
|
||||
/**
|
||||
* Filter for profile
|
||||
*
|
||||
* @param \IPS\Member $member The member whose profile is being viewed
|
||||
* @return \IPS\Content\Search\Query (for daisy chaining)
|
||||
*/
|
||||
abstract public function filterForProfile( \IPS\Member $member );
|
||||
|
||||
/**
|
||||
* Filter by item author
|
||||
*
|
||||
* @param \IPS\Member $author The author
|
||||
* @return \IPS\Content\Search\Query (for daisy chaining)
|
||||
*/
|
||||
abstract public function filterByAuthor( \IPS\Member $author );
|
||||
abstract public function filterByItemAuthor( \IPS\Member $author );
|
||||
|
||||
/**
|
||||
* Filter by content the user follows
|
||||
*
|
||||
* @param bool $includeContainers Include content in containers the user follows?
|
||||
* @param bool $includeItems Include items and comments/reviews on items the user follows?
|
||||
* @param bool $includeContainers Include content posted by members the user follows?
|
||||
* @return \IPS\Content\Search\Query (for daisy chaining)
|
||||
*/
|
||||
abstract public function filterByFollowed( $includeContainers, $includeItems, $includeMembers );
|
||||
|
||||
/**
|
||||
* Filter by content the user has posted in
|
||||
*
|
||||
* @return \IPS\Content\Search\Query (for daisy chaining)
|
||||
*/
|
||||
abstract public function filterByItemsIPostedIn();
|
||||
|
||||
/**
|
||||
* Filter by content the user has not read
|
||||
*
|
||||
* @note If applicable, it is more efficient to call filterByContent() before calling this method
|
||||
* @return \IPS\Content\Search\Query (for daisy chaining)
|
||||
*/
|
||||
abstract public function filterByUnread();
|
||||
|
||||
/**
|
||||
* Filter by start date
|
||||
@@ -279,4 +243,51 @@ abstract class _Query
|
||||
{
|
||||
return $this->search( $term, $tags, $method )->count( TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this term a phrase?
|
||||
*
|
||||
* @param string $term The term to search for
|
||||
* @return boolean
|
||||
*/
|
||||
public static function termIsPhrase( $term )
|
||||
{
|
||||
return (boolean) preg_match( '#^".*"$#', $term );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @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
|
||||
* @return array
|
||||
*/
|
||||
public static function termAsWordsArray( $term, $ignorePhrase=FALSE, $minLength=3 )
|
||||
{
|
||||
if ( static::termIsPhrase( $term ) )
|
||||
{
|
||||
if ( ! $ignorePhrase )
|
||||
{
|
||||
return array( $term );
|
||||
}
|
||||
else
|
||||
{
|
||||
$term = str_replace( '"', '', $term );
|
||||
}
|
||||
}
|
||||
|
||||
$theWords = array();
|
||||
foreach( explode( ' ', $term ) as $_term )
|
||||
{
|
||||
if ( mb_strlen( $_term ) > $minLength )
|
||||
{
|
||||
$theWords[] = $_term;
|
||||
}
|
||||
}
|
||||
|
||||
return $theWords;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user