Version 4.5.0
This commit is contained in:
1 parent
1a0c7fd3c2
commit
f79dcf067a
3791 files changed
+248032
-76372
No files matched your search
@@ -11,7 +11,7 @@
|
||||
namespace IPS\Content\Search\Mysql;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -56,7 +56,7 @@ class _Index extends \IPS\Content\Search\Index
|
||||
{
|
||||
/* Get the index data */
|
||||
$indexData = $this->indexData( $object );
|
||||
$class = get_class( $object );
|
||||
$class = \get_class( $object );
|
||||
|
||||
/* If we got the data... */
|
||||
if( $indexData )
|
||||
@@ -167,7 +167,7 @@ class _Index extends \IPS\Content\Search\Index
|
||||
}
|
||||
|
||||
/* Add add them back if we have any */
|
||||
if ( count( $tags ) )
|
||||
if ( \count( $tags ) )
|
||||
{
|
||||
foreach( $tags as $tag )
|
||||
{
|
||||
@@ -229,7 +229,7 @@ class _Index extends \IPS\Content\Search\Index
|
||||
public function getIndexId( \IPS\Content\Searchable $object )
|
||||
{
|
||||
$databaseColumnId = $object::$databaseColumnId;
|
||||
return \IPS\Db::i()->select( 'index_id', 'core_search_index', array( 'index_class=? AND index_object_id=?', get_class( $object ),$object->$databaseColumnId ) )->first();
|
||||
return \IPS\Db::i()->select( 'index_id', 'core_search_index', array( 'index_class=? AND index_object_id=?', \get_class( $object ),$object->$databaseColumnId ) )->first();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -240,7 +240,7 @@ class _Index extends \IPS\Content\Search\Index
|
||||
*/
|
||||
public function removeFromSearchIndex( \IPS\Content\Searchable $object )
|
||||
{
|
||||
$class = get_class( $object );
|
||||
$class = \get_class( $object );
|
||||
$idColumn = $class::$databaseColumnId;
|
||||
|
||||
/* Tags */
|
||||
@@ -266,7 +266,7 @@ class _Index extends \IPS\Content\Search\Index
|
||||
|
||||
try
|
||||
{
|
||||
$this->resetLastComment( $classes, $object->mapped('item') );
|
||||
$this->resetLastComment( $classes, $object->mapped('item'), $object->$idColumn );
|
||||
}
|
||||
catch( \Exception $ex ) { }
|
||||
|
||||
@@ -300,6 +300,41 @@ class _Index extends \IPS\Content\Search\Index
|
||||
\IPS\Db::i()->delete( 'core_search_index', array( 'index_class=? AND index_item_id=?', $reviewClass, $object->$idColumn ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Direct removal from the search index - only used when we don't need to perform ancillary cleanup (i.e. orphaned data)
|
||||
*
|
||||
* @param string $class Class
|
||||
* @param int $id ID
|
||||
* @return void
|
||||
*/
|
||||
public function directIndexRemoval( $class, $id )
|
||||
{
|
||||
/* Tags */
|
||||
$this->_deleteTagsFromIndex( $class, $id );
|
||||
|
||||
\IPS\Db::i()->delete( 'core_search_index', array( 'index_class=? AND index_object_id=?', $class, $id ) );
|
||||
|
||||
/* If this was a comment, we really need to reset the index_is_last_comment flag if it was set */
|
||||
if ( is_subclass_of( $class, 'IPS\Content\Item' ) )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_search_index_item_map', array( 'index_class=? AND index_item_id=?', $class, $id ) );
|
||||
}
|
||||
|
||||
if ( isset( $class::$commentClass ) )
|
||||
{
|
||||
$commentClass = $class::$commentClass;
|
||||
$this->_deleteTagsFromIndex( $commentClass, $id );
|
||||
\IPS\Db::i()->delete( 'core_search_index', array( 'index_class=? AND index_item_id=?', $commentClass, $id ) );
|
||||
}
|
||||
|
||||
if ( isset( $class::$reviewClass ) )
|
||||
{
|
||||
$reviewClass = $class::$reviewClass;
|
||||
$this->_deleteTagsFromIndex( $reviewClass, $id );
|
||||
\IPS\Db::i()->delete( 'core_search_index', array( 'index_class=? AND index_item_id=?', $reviewClass, $id ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index IDs associated with this class and $id
|
||||
@@ -319,7 +354,7 @@ class _Index extends \IPS\Content\Search\Index
|
||||
$ids = FALSE;
|
||||
}
|
||||
|
||||
if ( is_array( $ids ) and count( $ids ) < 1000 )
|
||||
if ( \is_array( $ids ) and \count( $ids ) < 1000 )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_search_index_tags', array( \IPS\Db::i()->in( 'index_id', $ids ) ) );
|
||||
}
|
||||
@@ -328,6 +363,52 @@ class _Index extends \IPS\Content\Search\Index
|
||||
\IPS\Db::i()->delete( 'core_search_index_tags', array( 'index_id IN( ? )', \IPS\Db::i()->select( 'index_id', 'core_search_index', array( 'index_class=? AND index_item_id=?', $class, $id ) ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all content for a specific application from the index (for example, when uninstalling).
|
||||
*
|
||||
* @param \IPS\Application $application The application
|
||||
* @return void
|
||||
*/
|
||||
public function removeApplicationContent( \IPS\Application $application )
|
||||
{
|
||||
$classes = array();
|
||||
|
||||
foreach ( $application->extensions( 'core', 'ContentRouter' ) as $router )
|
||||
{
|
||||
foreach( $router->classes AS $class )
|
||||
{
|
||||
if ( is_subclass_of( $class, 'IPS\Content\Searchable' ) )
|
||||
{
|
||||
$classes[] = $class;
|
||||
|
||||
if ( isset( $class::$commentClass ) )
|
||||
{
|
||||
$commentClass = $class::$commentClass;
|
||||
if ( is_subclass_of( $commentClass, 'IPS\Content\Searchable' ) )
|
||||
{
|
||||
$classes[] = $commentClass;
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $class::$reviewClass ) )
|
||||
{
|
||||
$reviewClass = $class::$reviewClass;
|
||||
if ( is_subclass_of( $reviewClass, 'IPS\Content\Searchable' ) )
|
||||
{
|
||||
$classes[] = $reviewClass;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$where = array( \IPS\Db::i()->in( 'index_class', $classes ) );
|
||||
|
||||
\IPS\Db::i()->delete( 'core_search_index_item_map', $where );
|
||||
\IPS\Db::i()->delete( 'core_search_index_tags', array( 'index_id IN( ? )', \IPS\Db::i()->select( 'index_id', 'core_search_index', $where ) ) );
|
||||
\IPS\Db::i()->delete( 'core_search_index', $where );
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all content for a classs
|
||||
@@ -394,7 +475,7 @@ class _Index extends \IPS\Content\Search\Index
|
||||
{
|
||||
$update['index_container_id'] = $newContainer;
|
||||
|
||||
if ( $itemClass = ( in_array( 'IPS\Content\Item', class_parents( $class ) ) ? $class : $class::$itemClass ) and $containerClass = $itemClass::$containerNodeClass and \IPS\IPS::classUsesTrait( $containerClass, 'IPS\Content\ClubContainer' ) and $clubIdColumn = $containerClass::clubIdColumn() )
|
||||
if ( $itemClass = ( \in_array( 'IPS\Content\Item', class_parents( $class ) ) ? $class : $class::$itemClass ) and $containerClass = $itemClass::$containerNodeClass and \IPS\IPS::classUsesTrait( $containerClass, 'IPS\Content\ClubContainer' ) and $clubIdColumn = $containerClass::clubIdColumn() )
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -415,7 +496,7 @@ class _Index extends \IPS\Content\Search\Index
|
||||
$update['index_item_author'] = $newItemAuthorId;
|
||||
}
|
||||
|
||||
if ( count( $update ) )
|
||||
if ( \count( $update ) )
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_search_index', $update, $where );
|
||||
}
|
||||
@@ -423,7 +504,7 @@ class _Index extends \IPS\Content\Search\Index
|
||||
{
|
||||
$addAuthorToPermissionsWhere = $where;
|
||||
$addAuthorToPermissionsWhere[] = array( 'index_author<>0' );
|
||||
\IPS\Db::i()->update( 'core_search_index', "index_permissions = CONCAT( index_permissions, ',m.', index_author )", $addAuthorToPermissionsWhere );
|
||||
\IPS\Db::i()->update( 'core_search_index', "index_permissions = CONCAT( index_permissions, ',m', index_author )", $addAuthorToPermissionsWhere );
|
||||
}
|
||||
|
||||
if ( $newHiddenStatus !== NULL )
|
||||
@@ -486,8 +567,8 @@ class _Index extends \IPS\Content\Search\Index
|
||||
{
|
||||
$prefix = \IPS\Db::i()->prefix;
|
||||
|
||||
\IPS\Db::i()->query( "DELETE {$prefix}core_search_index_item_map FROM {$prefix}core_search_index_item_map, {$prefix}core_search_index WHERE {$prefix}core_search_index_item_map.index_item_id={$prefix}core_search_index.index_item_id AND index_date_updated < " . $cutoff->getTimestamp() );
|
||||
\IPS\Db::i()->query( "DELETE {$prefix}core_search_index_tags FROM {$prefix}core_search_index_tags, {$prefix}core_search_index WHERE {$prefix}core_search_index_tags.index_id={$prefix}core_search_index.index_id AND index_date_updated < " . $cutoff->getTimestamp() );
|
||||
\IPS\Db::i()->delete( array( 'core_search_index_item_map', 'core_search_index' ), array( "core_search_index_item_map.index_item_id=core_search_index.index_item_id AND (core_search_index.index_id=core_search_index.index_item_index_id AND index_date_updated < ?)", $cutoff->getTimestamp() ), NULL, NULL, NULL, 'core_search_index_item_map' );
|
||||
\IPS\Db::i()->delete( array( 'core_search_index_tags', 'core_search_index' ), array( "core_search_index_tags.index_id=core_search_index.index_id AND (core_search_index.index_id=core_search_index.index_item_index_id AND index_date_updated < ?)", $cutoff->getTimestamp() ), NULL, NULL, NULL, 'core_search_index_tags' );
|
||||
\IPS\Db::i()->delete( 'core_search_index', array( 'index_date_updated < ?', $cutoff->getTimestamp() ) );
|
||||
}
|
||||
else
|
||||
@@ -503,9 +584,10 @@ class _Index extends \IPS\Content\Search\Index
|
||||
*
|
||||
* @param array $classes The classes (when first post is required, this is typically just \IPS\forums\Topic\Post but for others, it will be both item and comment classes)
|
||||
* @param int|NULL $indexItemId The index item ID
|
||||
* @param int|NULL $ignoreId ID to ignore because it is being removed
|
||||
* @return void
|
||||
*/
|
||||
public function resetLastComment( $classes, $indexItemId )
|
||||
public function resetLastComment( $classes, $indexItemId, $ignoreId = NULL )
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_search_index', array( 'index_is_last_comment' => 0 ), array( \IPS\Db::i()->in( 'index_class', $classes ) . ' AND index_item_id=?', $indexItemId ) );
|
||||
|
||||
@@ -537,14 +619,15 @@ class _Index extends \IPS\Content\Search\Index
|
||||
*
|
||||
* @param array $itemIndexIds Item index IDs
|
||||
* @param \IPS\Member $member The member
|
||||
* @param int|NULL $limit Number of results to return
|
||||
* @return array
|
||||
*/
|
||||
public function hashesWithPermission( array $hashes, \IPS\Member $member )
|
||||
public function hashesWithPermission( array $hashes, \IPS\Member $member, $limit = NULL )
|
||||
{
|
||||
return iterator_to_array( \IPS\Db::i()->select( 'index_class_type_id_hash', array( 'core_search_index', 'si' ), array(
|
||||
array( "( si.index_permissions = '*' OR " . \IPS\Db::i()->findInSet( 'si.index_permissions', \IPS\Member::loggedIn()->permissionArray() ) . ' AND si.index_hidden=0 )' ),
|
||||
array( \IPS\Db::i()->in( 'si.index_class_type_id_hash', $hashes ) )
|
||||
) )->setKeyField('index_class_type_id_hash') );
|
||||
), NULL, $limit )->setKeyField('index_class_type_id_hash') );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\Content\Search\Mysql;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -72,7 +72,13 @@ class _Query extends \IPS\Content\Search\Query
|
||||
* @see filterByItemsIPostedIn()
|
||||
*/
|
||||
protected $filterByItemsIPostedIn = FALSE;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Filter by unread items?
|
||||
* @see filterByUnread()
|
||||
*/
|
||||
protected $filterByUnread = FALSE;
|
||||
|
||||
/**
|
||||
* Filter by multiple content types
|
||||
*
|
||||
@@ -100,7 +106,7 @@ class _Query extends \IPS\Content\Search\Query
|
||||
}
|
||||
|
||||
/* Set the class */
|
||||
if ( count( $filter->classes ) > 1 )
|
||||
if ( \count( $filter->classes ) > 1 )
|
||||
{
|
||||
$clause[] = \IPS\Db::i()->in( 'index_class', $filter->classes );
|
||||
}
|
||||
@@ -134,7 +140,14 @@ class _Query extends \IPS\Content\Search\Query
|
||||
/* Are we excluding certain container classes? */
|
||||
if( $filter->containerClasses !== NULL )
|
||||
{
|
||||
$clause[] = \IPS\Db::i()->in( 'index_container_class', $filter->containerClasses );
|
||||
if( $filter->containerClassExclusions !== NULL )
|
||||
{
|
||||
$clause[] = '(' . \IPS\Db::i()->in( 'index_container_class', $filter->containerClasses ) . ' OR ' . \IPS\Db::i()->in( 'index_class', $filter->containerClassExclusions ) . ')';
|
||||
}
|
||||
else
|
||||
{
|
||||
$clause[] = \IPS\Db::i()->in( 'index_container_class', $filter->containerClasses );
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the item IDs */
|
||||
@@ -157,19 +170,19 @@ class _Query extends \IPS\Content\Search\Query
|
||||
if ( $filter->minimumComments )
|
||||
{
|
||||
$this->select[ $class::$databaseTable . '_comments' ] = $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnMap['num_comments'];
|
||||
$clause[] = $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnMap['num_comments'] . '>=' . intval( $filter->minimumComments );
|
||||
$clause[] = $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnMap['num_comments'] . '>=' . \intval( $filter->minimumComments );
|
||||
}
|
||||
|
||||
if ( $filter->minimumReviews )
|
||||
{
|
||||
$this->select[ $class::$databaseTable . '_reviews' ] = $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnMap['num_reviews'];
|
||||
$clause[] = $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnMap['num_reviews'] . '>=' . intval( $filter->minimumReviews );
|
||||
$clause[] = $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnMap['num_reviews'] . '>=' . \intval( $filter->minimumReviews );
|
||||
}
|
||||
|
||||
if ( $filter->minimumViews )
|
||||
{
|
||||
$this->select[ $class::$databaseTable . '_views' ] = $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnMap['views'];
|
||||
$clause[] = $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnMap['views'] . '>=' . intval( $filter->minimumViews );
|
||||
$clause[] = $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnMap['views'] . '>=' . \intval( $filter->minimumViews );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +199,7 @@ class _Query extends \IPS\Content\Search\Query
|
||||
}
|
||||
|
||||
/* Put it together */
|
||||
if ( count( $clause ) > 1 )
|
||||
if ( \count( $clause ) > 1 )
|
||||
{
|
||||
$filters[] = '( ' . implode( ' AND ', $clause ) . ' )';
|
||||
}
|
||||
@@ -211,7 +224,7 @@ class _Query extends \IPS\Content\Search\Query
|
||||
*/
|
||||
public function filterByAuthor( $author )
|
||||
{
|
||||
if ( is_array( $author ) )
|
||||
if ( \is_array( $author ) )
|
||||
{
|
||||
$this->where[] = array( \IPS\Db::i()->in( 'index_author', $author ) );
|
||||
}
|
||||
@@ -236,7 +249,7 @@ class _Query extends \IPS\Content\Search\Query
|
||||
{
|
||||
$this->where[] = 'index_club_id IS NULL';
|
||||
}
|
||||
if ( is_array( $club ) )
|
||||
if ( \is_array( $club ) )
|
||||
{
|
||||
$this->where[] = array( \IPS\Db::i()->in( 'index_club_id', $club ) );
|
||||
}
|
||||
@@ -244,6 +257,26 @@ class _Query extends \IPS\Content\Search\Query
|
||||
{
|
||||
$this->where[] = array( 'index_club_id=?', $club instanceof \IPS\Member\Club ? $club->id : $club );
|
||||
}
|
||||
|
||||
/* Get the list of valid classes */
|
||||
foreach ( \IPS\Application::allExtensions( 'core', 'ContentRouter', FALSE ) as $object )
|
||||
{
|
||||
foreach ( $object->classes as $class )
|
||||
{
|
||||
if ( \in_array( 'IPS\Content\Item', class_parents( $class ) ) )
|
||||
{
|
||||
$classesChecked[] = $class;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Give content item classes a chance to inspect and manipulate filters */
|
||||
$filters = array();
|
||||
foreach( $classesChecked as $itemClass )
|
||||
{
|
||||
$itemClass::searchEngineFiltering( $filters, $this );
|
||||
}
|
||||
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -261,14 +294,7 @@ class _Query extends \IPS\Content\Search\Query
|
||||
|
||||
if ( $count )
|
||||
{
|
||||
if ( $count > 500 )
|
||||
{
|
||||
$this->where[] = array( '( index_author=? OR ( index_class=? AND index_container_id=? ) )', $member->member_id, 'IPS\core\Statuses\Status', $member->member_id );
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->where[] = array( '( index_author=? OR (' . \IPS\Db::i()->in( 'index_id', iterator_to_array( \IPS\Db::i()->select( 'index_id', 'core_search_index', array( 'index_class=? AND index_container_id=?', 'IPS\core\Statuses\Status', $member->member_id ) ) ) ) . ') )', $member->member_id );
|
||||
}
|
||||
$this->where[] = array( '( index_author=? OR ( index_class=? AND index_container_id=? ) )', $member->member_id, 'IPS\core\Statuses\Status', $member->member_id );
|
||||
|
||||
$filterResult = $this;
|
||||
}
|
||||
@@ -282,7 +308,7 @@ class _Query extends \IPS\Content\Search\Query
|
||||
{
|
||||
foreach ( $object->classes as $class )
|
||||
{
|
||||
if ( in_array( 'IPS\Content\Item', class_parents( $class ) ) )
|
||||
if ( \in_array( 'IPS\Content\Item', class_parents( $class ) ) )
|
||||
{
|
||||
$classesChecked[] = $class;
|
||||
}
|
||||
@@ -428,7 +454,7 @@ class _Query extends \IPS\Content\Search\Query
|
||||
{
|
||||
$followedItems[ $follow['follow_area'] ][] = $follow['follow_rel_id'];
|
||||
}
|
||||
else if( in_array( $follow['follow_area'], $containerCase ) )
|
||||
else if( \in_array( $follow['follow_area'], $containerCase ) )
|
||||
{
|
||||
$followedContainers[ $follow['follow_area'] ][] = $follow['follow_rel_id'];
|
||||
}
|
||||
@@ -463,13 +489,13 @@ class _Query extends \IPS\Content\Search\Query
|
||||
{
|
||||
$followed = iterator_to_array( \IPS\Db::i()->select( 'follow_rel_id', 'core_follow', array( 'follow_app=? AND follow_area=? AND follow_member_id=?', 'core', 'member', $this->member->member_id ), 'follow_rel_id asc', array( 0, 501 ) ) );
|
||||
|
||||
if ( count( $followed ) == 501 )
|
||||
if ( \count( $followed ) == 501 )
|
||||
{
|
||||
/* Assume we have loads of matches, so do a full query */
|
||||
$where[] = 'index_author IN(?)';
|
||||
$params[] = \IPS\Db::i()->select( 'follow_rel_id', 'core_follow', array( 'follow_app=? AND follow_area=? AND follow_member_id=?', 'core', 'member', $this->member->member_id ) );
|
||||
}
|
||||
else if ( count( $followed ) )
|
||||
else if ( \count( $followed ) )
|
||||
{
|
||||
/* IN is not a SIN. It's been a long day */
|
||||
$where[] = \IPS\Db::i()->in( 'index_author', $followed );
|
||||
@@ -488,7 +514,7 @@ class _Query extends \IPS\Content\Search\Query
|
||||
}
|
||||
|
||||
/* Put it all together */
|
||||
if ( count( $where ) )
|
||||
if ( \count( $where ) )
|
||||
{
|
||||
$this->where[] = array_merge( array( '( ' . implode( ' OR ', $where ) . ' )' ), $params );
|
||||
}
|
||||
@@ -570,11 +596,13 @@ class _Query extends \IPS\Content\Search\Query
|
||||
}
|
||||
}
|
||||
|
||||
if ( count( $where ) )
|
||||
if ( \count( $where ) )
|
||||
{
|
||||
/* Put it all together */
|
||||
$this->where[] = array_merge( array( '( ' . implode( ' OR ', $where ) . ' )' ), $params );
|
||||
}
|
||||
|
||||
$this->filterByUnread = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -595,7 +623,7 @@ class _Query extends \IPS\Content\Search\Query
|
||||
$where = array();
|
||||
$unreadWheres = array();
|
||||
$containerIds = array();
|
||||
$containerClass = ( $class::$containerNodeClass ) ? $class::$containerNodeClass : NULL;
|
||||
$containerClass = isset( $class::$containerNodeClass ) ? $class::$containerNodeClass : NULL;
|
||||
|
||||
foreach( $resetTimes as $containerId => $timestamp )
|
||||
{
|
||||
@@ -615,7 +643,7 @@ class _Query extends \IPS\Content\Search\Query
|
||||
|
||||
$items = $this->member->markersItems( $application, \IPS\Content\Item::makeMarkerKey( $containerId ) );
|
||||
|
||||
if ( count( $items ) )
|
||||
if ( \count( $items ) )
|
||||
{
|
||||
foreach( $items as $mid => $mtime )
|
||||
{
|
||||
@@ -625,10 +653,10 @@ class _Query extends \IPS\Content\Search\Query
|
||||
in it's old location, with the previously 'read' time. In this circumstance, we need
|
||||
to only use more recent read time, otherwise the topic may be incorrectly included
|
||||
in the results */
|
||||
if ( in_array( $mid, $markers ) )
|
||||
if ( \in_array( $mid, $markers ) )
|
||||
{
|
||||
$_key = array_search( $mid, $markers );
|
||||
$_mtime = intval( mb_substr( $_key, 0, mb_strpos( $_key, '.' ) ) );
|
||||
$_mtime = \intval( mb_substr( $_key, 0, mb_strpos( $_key, '.' ) ) );
|
||||
if ( $_mtime < $mtime )
|
||||
{
|
||||
unset( $markers[ $_key ] );
|
||||
@@ -646,25 +674,25 @@ class _Query extends \IPS\Content\Search\Query
|
||||
}
|
||||
}
|
||||
|
||||
if( count( $containerIds ) )
|
||||
if( \count( $containerIds ) )
|
||||
{
|
||||
$unreadWheres[] = "( index_date_updated > " . intval( $this->member->marked_site_read ) . " AND ( index_container_id NOT IN(" . implode( ',', $containerIds ) . ") ) )";
|
||||
$unreadWheres[] = "( index_date_updated > " . \intval( $this->member->marked_site_read ) . " AND ( index_container_id NOT IN(" . implode( ',', $containerIds ) . ") ) )";
|
||||
}
|
||||
else
|
||||
{
|
||||
$unreadWheres[] = "( index_date_updated > " . intval( $this->member->marked_site_read ) . ")";
|
||||
$unreadWheres[] = "( index_date_updated > " . \intval( $this->member->marked_site_read ) . ")";
|
||||
}
|
||||
|
||||
if( count( $unreadWheres ) )
|
||||
if( \count( $unreadWheres ) )
|
||||
{
|
||||
$where[] = array( "(" . implode( " OR ", $unreadWheres ) . ")" );
|
||||
}
|
||||
|
||||
if ( count( $markers ) )
|
||||
if ( \count( $markers ) )
|
||||
{
|
||||
/* Avoid packet issues */
|
||||
krsort( $markers );
|
||||
$useIds = array_flip( array_slice( $markers, 0, 500, TRUE ) );
|
||||
$useIds = array_flip( \array_slice( $markers, 0, 500, TRUE ) );
|
||||
$select = '';
|
||||
$from = '';
|
||||
$notIn = array();
|
||||
@@ -675,7 +703,7 @@ class _Query extends \IPS\Content\Search\Query
|
||||
{
|
||||
if ( isset( $class::$databaseColumnMap[ $k ] ) )
|
||||
{
|
||||
if ( is_array( $class::$databaseColumnMap[ $k ] ) )
|
||||
if ( \is_array( $class::$databaseColumnMap[ $k ] ) )
|
||||
{
|
||||
foreach ( $class::$databaseColumnMap[ $k ] as $v )
|
||||
{
|
||||
@@ -688,7 +716,7 @@ class _Query extends \IPS\Content\Search\Query
|
||||
}
|
||||
}
|
||||
}
|
||||
$dateColumnExpression = count( $dateColumns ) > 1 ? ( 'GREATEST(' . implode( ',', $dateColumns ) . ')' ) : array_pop( $dateColumns );
|
||||
$dateColumnExpression = \count( $dateColumns ) > 1 ? ( 'GREATEST(' . implode( ',', $dateColumns ) . ')' ) : array_pop( $dateColumns );
|
||||
|
||||
foreach( \IPS\Db::i()->select( $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnId. ' as _id, ' . $dateColumnExpression . ' as _date', $class::$databaseTable, \IPS\Db::i()->in( $class::$databasePrefix . $class::$databaseColumnId, array_keys( $useIds ) ) ) as $row )
|
||||
{
|
||||
@@ -697,12 +725,12 @@ class _Query extends \IPS\Content\Search\Query
|
||||
if ( $useIds[ $row['_id'] ] >= $row['_date'] )
|
||||
{
|
||||
/* Still read */
|
||||
$notIn[] = intval( $row['_id'] );
|
||||
$notIn[] = \intval( $row['_id'] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( count( $notIn ) )
|
||||
if ( \count( $notIn ) )
|
||||
{
|
||||
$where[] = array( "( index_item_id NOT IN (" . implode( ',', $notIn ) . ") )" );
|
||||
}
|
||||
@@ -759,11 +787,11 @@ class _Query extends \IPS\Content\Search\Query
|
||||
*/
|
||||
public function setHiddenFilter( $statuses )
|
||||
{
|
||||
if ( is_null( $statuses ) )
|
||||
if ( \is_null( $statuses ) )
|
||||
{
|
||||
$this->hiddenClause = NULL;
|
||||
}
|
||||
if ( is_array( $statuses ) )
|
||||
if ( \is_array( $statuses ) )
|
||||
{
|
||||
$this->hiddenClause = array( \IPS\Db::i()->in( 'index_hidden', $statuses ) );
|
||||
}
|
||||
@@ -856,7 +884,7 @@ class _Query extends \IPS\Content\Search\Query
|
||||
$tagIds = iterator_to_array( \IPS\Db::i()->select( 'index_id', 'core_search_index_tags', array( \IPS\Db::i()->in( 'index_tag', $tags ) ), 'index_id asc', array( 0, 501 ) ) );
|
||||
|
||||
/* Now, if we have 501 results, then we have to assume there are more, so the join is required */
|
||||
if ( count( $tagIds ) == 501 )
|
||||
if ( \count( $tagIds ) == 501 )
|
||||
{
|
||||
$tagWhere = array( $itemsOnlyTagSearch . 'index_item_index_id IN ( ? )', \IPS\Db::i()->select( 'index_id', 'core_search_index_tags', array( \IPS\Db::i()->in( 'index_tag', $tags ) ) ) );
|
||||
}
|
||||
@@ -937,16 +965,16 @@ class _Query extends \IPS\Content\Search\Query
|
||||
}
|
||||
}
|
||||
|
||||
$results = iterator_to_array( \IPS\Db::i()->select( 'index_item_id, index_class', array( 'core_search_index_item_map', 'sub' ), array( array( 'index_author_id=' . intval( $this->member->member_id ) . ' AND ' . \IPS\Db::i()->in( 'index_class', $classes ) ) ), 'index_item_id desc', array( 0, 501 ) ) );
|
||||
$results = iterator_to_array( \IPS\Db::i()->select( 'index_item_id, index_class', array( 'core_search_index_item_map', 'sub' ), array( array( 'index_author_id=' . \intval( $this->member->member_id ) . ' AND ' . \IPS\Db::i()->in( 'index_class', $classes ) ) ), 'index_item_id desc', array( 0, 501 ) ) );
|
||||
|
||||
if ( count( $results ) == 501 )
|
||||
if ( \count( $results ) == 501 )
|
||||
{
|
||||
/* Assume we have loads of matches, so do a full query */
|
||||
$subClause = array( array( 'sub.index_item_id=main.index_item_id AND index_author_id=' . intval( $this->member->member_id ) . ' AND ' . $this->makeEmbeddedIfClauseForSearchMapTable('sub.index_class') ) );
|
||||
$subClause = array( array( 'sub.index_item_id=main.index_item_id AND index_author_id=' . \intval( $this->member->member_id ) . ' AND ' . $this->makeEmbeddedIfClauseForSearchMapTable('sub.index_class') ) );
|
||||
$query = \IPS\Db::i()->select( 'index_item_id', array( 'core_search_index_item_map', 'sub' ), $subClause );
|
||||
$where[] = array( 'EXISTS(?)', $query );
|
||||
}
|
||||
else if ( count( $results ) )
|
||||
else if ( \count( $results ) )
|
||||
{
|
||||
$classIds = array();
|
||||
foreach( $results as $result )
|
||||
@@ -1027,7 +1055,7 @@ class _Query extends \IPS\Content\Search\Query
|
||||
}
|
||||
}
|
||||
|
||||
if ( count( $stack ) )
|
||||
if ( \count( $stack ) )
|
||||
{
|
||||
$if = '';
|
||||
foreach( $stack as $commentClass => $class )
|
||||
@@ -1035,7 +1063,7 @@ class _Query extends \IPS\Content\Search\Query
|
||||
$if .= " IF( main.index_class='" . \IPS\Db::i()->escape_string( $commentClass ) . "', '" . \IPS\Db::i()->escape_string( $class ) . "', ";
|
||||
}
|
||||
|
||||
$if .= 'main.index_class' . str_repeat( ' )', count( $stack ) );
|
||||
$if .= 'main.index_class' . str_repeat( ' )', \count( $stack ) );
|
||||
}
|
||||
|
||||
return $column . '=' . ( $if == '' ? $column : $if );
|
||||
@@ -1066,25 +1094,14 @@ class _Query extends \IPS\Content\Search\Query
|
||||
foreach ( static::termAsWordsArray( $term ) as $word )
|
||||
{
|
||||
/* Operators are not allowed */
|
||||
$word = preg_replace( '/^([\+\-~<>]){1,}/', '', $word );
|
||||
$word = preg_replace( '/([\+\-~\*<>]){2,}$/', '$1', $word );
|
||||
|
||||
/* +* and +- are not allowed anywhere in the word */
|
||||
$word = str_replace( array( '+*', '+-', '+' ), '', $word );
|
||||
|
||||
/* Trailing + or -s are not allowed */
|
||||
$word = rtrim( $word, '+-' );
|
||||
|
||||
/* Nor is @ or parenthesis (while paranthesis can be used to group words and apply operators to the group,
|
||||
(e.g. "+apple +(>turnover <strudel)") - it's unlikely a user intends this behaviour) */
|
||||
$word = str_replace( array( '(', ')' ), '', str_replace( '@', ' ', $word ) );
|
||||
$word = preg_replace( '/[+\-><\(\)~*\"@%]+/', '', $word );
|
||||
|
||||
if ( $word )
|
||||
{
|
||||
$words[] = $word;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$booleanTerm = implode( ' +', $words );
|
||||
|
||||
/* Return */
|
||||
@@ -1119,7 +1136,7 @@ class _Query extends \IPS\Content\Search\Query
|
||||
foreach ( static::termAsWordsArray( $term ) as $word )
|
||||
{
|
||||
/* Add the default operator */
|
||||
if ( $defaultOperator and !in_array( mb_substr( $word, 0, 1 ), array( '+', '-', '~', '<', '>' ) ) )
|
||||
if ( $defaultOperator and !\in_array( mb_substr( $word, 0, 1 ), array( '+', '-', '~', '<', '>' ) ) )
|
||||
{
|
||||
/* Clear out leading * symbols so we don't end up with +*a** */
|
||||
$word = $defaultOperator . ltrim( $word, '*' );
|
||||
@@ -1179,11 +1196,11 @@ class _Query extends \IPS\Content\Search\Query
|
||||
if ( $prepared )
|
||||
{
|
||||
/* Force newest as of 4.2.6 to test search results */
|
||||
if ( count( $likeWhere ) and count( $words ) )
|
||||
if ( \count( $likeWhere ) and \count( $words ) )
|
||||
{
|
||||
$return = array( implode( ' AND ', $likeWhere ) . " AND MATCH({$columns}) AGAINST (? IN BOOLEAN MODE)", $term );
|
||||
}
|
||||
else if ( count( $likeWhere ) )
|
||||
else if ( \count( $likeWhere ) )
|
||||
{
|
||||
$return = array( implode( ' AND ', $likeWhere ) );
|
||||
}
|
||||
@@ -1195,7 +1212,7 @@ class _Query extends \IPS\Content\Search\Query
|
||||
else
|
||||
{
|
||||
/* Force newest as of 4.2.6 to test search results */
|
||||
if ( count( $likeWhere ) )
|
||||
if ( \count( $likeWhere ) )
|
||||
{
|
||||
$return[] = implode( ' AND ', $likeWhere );
|
||||
}
|
||||
@@ -1231,7 +1248,13 @@ class _Query extends \IPS\Content\Search\Query
|
||||
|
||||
/* Set order clause */
|
||||
$order = $this->order;
|
||||
|
||||
|
||||
/* This forces MySQL to strongly hint a better index to the optimiser for MySQL 5.7+, even though sorting will not be affected */
|
||||
if ( $this->filterByUnread and ( ! mb_stristr( \IPS\Db::i()->server_info, '-MariaDB' ) and \IPS\Db::i()->server_version >= 50700 ) )
|
||||
{
|
||||
$order .= ", index_date_updated";
|
||||
}
|
||||
|
||||
/* But we're sorting by relevancy, we need to actually select that value with our fancy algorithm */
|
||||
if ( mb_substr( $this->order, 0, 9 ) === 'calcscore' )
|
||||
{
|
||||
@@ -1240,7 +1263,7 @@ class _Query extends \IPS\Content\Search\Query
|
||||
{
|
||||
if ( \IPS\Settings::i()->search_title_boost )
|
||||
{
|
||||
$titleField = '(' . static::matchClause( 'index_title', $term, $operator === static::OPERATOR_AND ? '+' : '', FALSE ) . '*' . intval( \IPS\Settings::i()->search_title_boost ) . ')'; // The title score times multiplier
|
||||
$titleField = '(' . static::matchClause( 'index_title', $term, $operator === static::OPERATOR_AND ? '+' : '', FALSE ) . '*' . \intval( \IPS\Settings::i()->search_title_boost ) . ')'; // The title score times multiplier
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1394,11 +1417,11 @@ class _Query extends \IPS\Content\Search\Query
|
||||
{
|
||||
if ( $row['Variable_name'] === $minVariable )
|
||||
{
|
||||
\IPS\Data\Store::i()->mysqlMinWord = intval( $row['Value'] );
|
||||
\IPS\Data\Store::i()->mysqlMinWord = \intval( $row['Value'] );
|
||||
}
|
||||
elseif ( $row['Variable_name'] === $maxVariable )
|
||||
{
|
||||
\IPS\Data\Store::i()->mysqlMaxWord = intval( $row['Value'] );
|
||||
\IPS\Data\Store::i()->mysqlMaxWord = \intval( $row['Value'] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user