Version 4.2.0

This commit is contained in:
Neo committed 2025-12-19 05:44:59 -08:00
1 parent 0dc2aee5ed
commit 96997ddd8e
2074 files changed
+125454 -55780

No files matched your search

+20 -15
View File
@@ -1,12 +1,11 @@
<?php
/**
* @brief Content Filter for Search Queries
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 6 Jul 2015
* @version SVN_VERSION_NUMBER
*/
namespace IPS\Content\Search;
@@ -32,6 +31,12 @@ class _ContentFilter
* @brief Classes to include
*/
public $classes = array();
/**
* @brief Container classes to include
* @note NULL means not to filter by container classes
*/
public $containerClasses = NULL;
/**
* @brief Container ID filter
@@ -85,7 +90,7 @@ class _ContentFilter
* @param bool $includeItems Include items in results?
* @param bool $includeComments Include comments in results?
* @param bool $includeReviews Include reviews in results?
* @return \IPS\Content\Search\ContainerFilter
* @return \IPS\Content\Search\ContentFilter
*/
public static function init( $itemClass, $includeItems=TRUE, $includeComments=TRUE, $includeReviews=TRUE )
{
@@ -114,7 +119,7 @@ class _ContentFilter
* Only include results in containers
*
* @param array $ids Acceptable container IDs
* @return \IPS\Content\Search\ContainerFilter (for daisy chaining)
* @return \IPS\Content\Search\ContentFilter (for daisy chaining)
*/
public function onlyInContainers( array $ids )
{
@@ -128,7 +133,7 @@ class _ContentFilter
* Exclude results in containers
*
* @param array $ids Acceptable container IDs
* @return \IPS\Content\Search\ContainerFilter (for daisy chaining)
* @return \IPS\Content\Search\ContentFilter (for daisy chaining)
*/
public function excludeInContainers( array $ids )
{
@@ -142,7 +147,7 @@ class _ContentFilter
* Only include results in items
*
* @param array $ids Acceptable item IDs
* @return \IPS\Content\Search\ContainerFilter (for daisy chaining)
* @return \IPS\Content\Search\ContentFilter (for daisy chaining)
*/
public function onlyInItems( array $ids )
{
@@ -156,7 +161,7 @@ class _ContentFilter
* Exclude results in items
*
* @param array $ids Acceptable container IDs
* @return \IPS\Content\Search\ContainerFilter (for daisy chaining)
* @return \IPS\Content\Search\ContentFilter (for daisy chaining)
*/
public function excludeInItems( array $ids )
{
@@ -170,7 +175,7 @@ class _ContentFilter
* Set minimum number of comments
*
* @param int $minimumComments The minimum number of comments
* @return \IPS\Content\Search\ContainerFilter (for daisy chaining)
* @return \IPS\Content\Search\ContentFilter (for daisy chaining)
*/
public function minimumComments( $minimumComments )
{
@@ -183,7 +188,7 @@ class _ContentFilter
* Set minimum number of reviews
*
* @param int $minimumReviews The minimum number of reviews
* @return \IPS\Content\Search\ContainerFilter (for daisy chaining)
* @return \IPS\Content\Search\ContentFilter (for daisy chaining)
*/
public function minimumReviews( $minimumReviews )
{
@@ -196,7 +201,7 @@ class _ContentFilter
* Set minimum number of views
*
* @param int $minimumViews The minimum number of views
* @return \IPS\Content\Search\ContainerFilter (for daisy chaining)
* @return \IPS\Content\Search\ContentFilter (for daisy chaining)
*/
public function minimumViews( $minimumViews )
{
@@ -208,7 +213,7 @@ class _ContentFilter
/**
* Only include results which are the first comment on an item requiring a comment
*
* @return \IPS\Content\Search\ContainerFilter (for daisy chaining)
* @return \IPS\Content\Search\ContentFilter (for daisy chaining)
*/
public function onlyFirstComment()
{
@@ -220,7 +225,7 @@ class _ContentFilter
/**
* Only include results which are the last comment on an item requiring a comment
*
* @return \IPS\Content\Search\ContainerFilter (for daisy chaining)
* @return \IPS\Content\Search\ContentFilter (for daisy chaining)
*/
public function onlyLastComment()
{
+27 -7
View File
@@ -1,12 +1,11 @@
<?php
/**
* @brief Abstract Search Index
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 21 Aug 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\Content\Search;
@@ -250,12 +249,32 @@ abstract class _Index extends \IPS\Patterns\Singleton
catch ( \Exception $e ) { }
}
}
/* Club */
$container = NULL;
$containerId = NULL;
$clubId = NULL;
if ( $object instanceof \IPS\Content\Item )
{
$containerId = (int) $object->searchIndexContainer();
$container = $object->containerWrapper();
}
else
{
$containerId = (int) $object->item()->mapped('container');
$container = $object->item()->containerWrapper();
}
if ( $container and \IPS\IPS::classUsesTrait( $container, 'IPS\Content\ClubContainer' ) )
{
$clubId = $container->{$container::clubIdColumn()};
}
/* Return */
return array(
'index_class' => $class,
'index_object_id' => $object->$idColumn,
'index_item_id' => ( $object instanceof \IPS\Content\Item ) ? $object->$idColumn : $object->mapped('item'),
'index_container_class' => ( $object instanceof \IPS\Content\Item ) ? get_class( $object->searchIndexContainerClass() ) : get_class( $object->item()->searchIndexContainerClass() ),
'index_container_id' => ( $object instanceof \IPS\Content\Item ) ? (int) $object->searchIndexContainer() : (int) $object->item()->mapped('container'),
'index_title' => $title,
'index_content' => $content,
@@ -268,7 +287,8 @@ abstract class _Index extends \IPS\Patterns\Singleton
'index_hidden' => $hiddenStatus,
'index_item_index_id' => $itemIndexId,
'index_item_author' => intval( ( $object instanceof \IPS\Content\Item ) ? $object->mapped('author') : $object->item()->mapped('author') ),
'index_is_last_comment' => $isLastComment
'index_is_last_comment' => $isLastComment,
'index_club_id' => $clubId
);
}
+17 -6
View File
@@ -1,12 +1,11 @@
<?php
/**
* @brief MySQL Search Index
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 21 Aug 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\Content\Search\Mysql;
@@ -331,7 +330,7 @@ class _Index extends \IPS\Content\Search\Index
$where[] = array( 'index_container_id=?', $containerId );
}
\IPS\Db::i()->delete( 'core_search_index_item_map', array( 'index_item_id IN( ? )', \IPS\Db::i()->select( 'index_item_id', 'core_search_index', $where ) ) );
\IPS\Db::i()->delete( 'core_search_index_item_map', array( 'index_class=? and index_item_id IN( ? )', $class, \IPS\Db::i()->select( 'index_item_id', 'core_search_index', $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 );
}
@@ -375,6 +374,18 @@ class _Index extends \IPS\Content\Search\Index
if ( $newContainer )
{
$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() )
{
try
{
$update['index_club_id'] = $containerClass::load( $newContainer )->$clubIdColumn;
}
catch ( \OutOfRangeException $e )
{
$update['index_club_id'] = NULL;
}
}
}
if ( $newItemId )
{
+67 -6
View File
@@ -1,12 +1,11 @@
<?php
/**
* @brief MySQL Search Query
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 21 Aug 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\Content\Search\Mysql;
@@ -128,6 +127,12 @@ class _Query extends \IPS\Content\Search\Query
$clause[] = \IPS\Db::i()->in( 'index_container_id', $unsearchableIds, TRUE );
}
}
/* Are we excluding certain container classes? */
if( $filter->containerClasses !== NULL )
{
$clause[] = \IPS\Db::i()->in( 'index_container_class', $filter->containerClasses );
}
/* Set the item IDs */
if ( $filter->itemIdFilter !== NULL )
@@ -209,7 +214,32 @@ class _Query extends \IPS\Content\Search\Query
}
return $this;
}
}
/**
* Filter by club
*
* @param \IPS\Member\Club|int|array|null $club The club, or array of club IDs, or NULL to exclude content from clubs
* @return \IPS\Content\Search\Query (for daisy chaining)
*/
public function filterByClub( $club )
{
if ( $club === NULL )
{
$this->where[] = 'index_club_id IS NULL';
}
if ( is_array( $club ) )
{
$this->where[] = array( \IPS\Db::i()->in( 'index_club_id', $club ) );
}
else
{
$this->where[] = array( 'index_club_id=?', $club instanceof \IPS\Member\Club ? $club->id : $club );
}
return $this;
}
/**
* Filter for profile
@@ -253,6 +283,37 @@ class _Query extends \IPS\Content\Search\Query
return $this;
}
/**
* Filter by container class
*
* @param array $classes Container classes to exclude from results.
* @param array $exclude Content classes to exclude from the filter. For cases where multiple content classes may have the same container class
* such as Gallery images, comments and reviews.
* @return \IPS\Content\Search\Query (for daisy chaining)
*/
public function filterByContainerClasses( $classes=array(), $exclude=array() )
{
if( empty( $exclude ) )
{
$this->where[] = \IPS\Db::i()->in( 'index_container_class', $classes, TRUE );
}
else
{
foreach( $classes as $i => $class )
{
$classes[$i] = "'" . \IPS\DB::i()->real_escape_string( $class ) . "'";
}
foreach( $exclude as $i => $class )
{
$exclude[$i] = "'" . \IPS\DB::i()->real_escape_string( $class ) . "'";
}
$this->where[] = '( index_container_class NOT IN(' . implode( ',', $classes ) . ') OR index_class IN(' . implode( ',', $exclude ) . ') )';
}
return $this;
}
/**
* Filter by content the user follows
+13 -6
View File
@@ -1,12 +1,11 @@
<?php
/**
* @brief Abstract Search Query
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 21 Aug 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\Content\Search;
@@ -46,7 +45,7 @@ abstract class _Query
* Create new query
*
* @param \IPS\Member $member The member performing the search (NULL for currently logged in member)
* @return \IPS\Content\Search
* @return \IPS\Content\Search\Query
*/
public static function init( \IPS\Member $member = NULL )
{
@@ -108,6 +107,14 @@ abstract class _Query
*/
abstract public function filterByAuthor( $author );
/**
* Filter by club
*
* @param \IPS\Member\Club|int|array $club The club, or array of club IDs
* @return \IPS\Content\Search\Query (for daisy chaining)
*/
abstract public function filterByClub( $club );
/**
* Filter for profile
*
+8 -7
View File
@@ -1,12 +1,11 @@
<?php
/**
* @brief Search Result from Index
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 15 Sep 2015
* @version SVN_VERSION_NUMBER
*/
namespace IPS\Content\Search\Result;
@@ -63,9 +62,10 @@ class _Content extends \IPS\Content\Search\Result
* @param array $reputationData Array of people who have given reputation and the reputation they gave
* @param int|NULL $reviewRating If this is a review, the rating
* @param bool $iPostedIn If the user has posted in the item
* @param array $reactions Reaction Data
* @return void
*/
public function __construct( array $indexData, array $authorData, array $itemData, array $containerData = NULL, array $reputationData, $reviewRating = NULL, $iPostedIn = FALSE )
public function __construct( array $indexData, array $authorData, array $itemData, array $containerData = NULL, array $reputationData, $reviewRating = NULL, $iPostedIn = FALSE, $reactions=array() )
{
$this->createdDate = \IPS\DateTime::ts( $indexData['index_date_created'] );
$this->lastUpdatedDate = \IPS\DateTime::ts( $indexData['index_date_updated'] );
@@ -76,6 +76,7 @@ class _Content extends \IPS\Content\Search\Result
$this->reputationData = $reputationData;
$this->reviewRating = $reviewRating;
$this->iPostedIn = $iPostedIn;
$this->reactions = $reactions;
}
/**
@@ -89,7 +90,7 @@ class _Content extends \IPS\Content\Search\Result
*/
public function html( $view = 'expanded', $asItem = FALSE, $canIgnoreComments=FALSE, $template=NULL )
{
return call_user_func( array( $this->indexData['index_class'], 'searchResult' ), $this->indexData, $this->authorData, $this->itemData, $this->containerData, $this->reputationData, $this->reviewRating, $this->iPostedIn, $view, $asItem, $canIgnoreComments, $template );
return call_user_func( array( $this->indexData['index_class'], 'searchResult' ), $this->indexData, $this->authorData, $this->itemData, $this->containerData, $this->reputationData, $this->reviewRating, $this->iPostedIn, $view, $asItem, $canIgnoreComments, $template, $this->reactions );
}
/**
+35 -6
View File
@@ -1,12 +1,11 @@
<?php
/**
* @brief Search Result not from Index
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 15 Sep 2015
* @version SVN_VERSION_NUMBER
*/
namespace IPS\Content\Search\Result;
@@ -32,6 +31,11 @@ class _Custom extends \IPS\Content\Search\Result
* @brief Image
*/
protected $image;
/**
* @brief Data used for merging multiple extra items
*/
protected $mergeData;
/**
* Constructor
@@ -39,14 +43,39 @@ class _Custom extends \IPS\Content\Search\Result
* @param \IPS\DateTime $time The time for this result
* @param string $html HTML to display
* @param string|NULL $image HTML for image to display
* @param string|NULL $mergeData Data for merging
* @return void
*/
public function __construct( \IPS\DateTime $time, $html, $image = NULL )
public function __construct( \IPS\DateTime $time, $html, $image = NULL, $mergeData = NULL )
{
$this->createdDate = $time;
$this->lastUpdatedDate = $time;
$this->html = $html;
$this->image = $image;
$this->mergeData = array( $mergeData );
}
/**
* Merge in new data
*
* @param string $html New HTML to merge in as a list
* @param string|NULL $mergeData Data for merging
* @return void
*/
public function mergeInData( $html, $mergeData = NULL )
{
$this->html = $html;
$this->mergeData[] = $mergeData;
}
/**
* Get data for merging
*
* @return array
*/
public function getMergeData()
{
return $this->mergeData ?: array();
}
/**
+4 -5
View File
@@ -1,12 +1,11 @@
<?php
/**
* @brief Search Result
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 15 Sep 2015
* @version SVN_VERSION_NUMBER
*/
namespace IPS\Content\Search;
+157 -65
View File
@@ -1,12 +1,11 @@
<?php
/**
* @brief Search Results
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 21 Aug 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\Content\Search;
@@ -53,6 +52,11 @@ class _Results extends \ArrayIterator
*/
protected $reputationData = array();
/**
* @brief Reaction Data
*/
protected $reactions = array();
/**
* @brief Review Ratings
*/
@@ -139,7 +143,7 @@ class _Results extends \ArrayIterator
}
}
if ( in_array( 'IPS\Content\Reputation', class_implements( $result['index_class'] ) ) )
if ( \IPS\IPS::classUsesTrait( $result['index_class'], 'IPS\Content\Reactable' ) )
{
$reputationIds[ $result['index_class'] ][ $result['index_object_id'] ] = $result['index_object_id'];
}
@@ -153,8 +157,13 @@ class _Results extends \ArrayIterator
{
$itemIndexIds[] = $result['index_item_index_id'];
}
if ( $result['index_club_id'] )
{
$containersToLoad[ 'IPS\Member\Club' ][ $result['index_club_id'] ] = $result['index_club_id'];
}
}
/* Load item data */
foreach ( $itemsToLoad as $itemClass => $itemIds )
{
@@ -162,7 +171,7 @@ class _Results extends \ArrayIterator
{
$this->itemData[ $itemClass ][ $itemId ] = $itemData;
if ( isset( $itemData[ $itemClass::$databasePrefix . $itemClass::$databaseColumnMap['author'] ] ) )
if ( isset( $itemClass::$databaseColumnMap ) and isset( $itemData[ $itemClass::$databasePrefix . $itemClass::$databaseColumnMap['author'] ] ) )
{
$memberId = $itemData[ $itemClass::$databasePrefix . $itemClass::$databaseColumnMap['author'] ];
$membersToLoad[ $memberId ] = $memberId;
@@ -198,26 +207,23 @@ class _Results extends \ArrayIterator
$binds = array();
foreach ( $reputationIds as $class => $ids )
{
$clause[] = "( app=? AND type=? AND " . \IPS\Db::i()->in( 'type_id', $ids ) . " )";
$clause[] = "( reaction_enabled=? AND app=? AND type=? AND " . \IPS\Db::i()->in( 'type_id', $ids ) . " )";
$binds[] = 1;
$binds[] = $class::$application;
$binds[] = $class::$reputationType;
$binds[] = $class::reactionType();
}
$where = array( array_merge( array( implode( ' OR ', $clause ) ), $binds ) );
switch( \IPS\Settings::i()->reputation_point_types )
foreach ( \IPS\Db::i()->select( array( 'app', 'type', 'type_id', 'member_id', 'rep_rating', 'reaction' ), 'core_reputation_index', $where )->join( 'core_reactions', 'reaction=reaction_id' ) as $rep )
{
case 'positive':
case 'like':
$where[] = array( 'rep_rating=?', "1" );
break;
case 'negative':
$where[] = array( 'rep_rating=?', "-1" );
break;
}
foreach ( \IPS\Db::i()->select( array( 'app', 'type', 'type_id', 'member_id', 'rep_rating' ), 'core_reputation_index', $where ) as $rep )
{
$this->reputationData[ $rep['app'] ][ $rep['type'] ][ $rep['type_id'] ][ $rep['member_id'] ] = $rep['rep_rating'];
$this->reputationData[ $rep['app'] ][ $rep['type'] ][ $rep['type_id'] ][ $rep['member_id'] ] = $rep['reaction'];
if ( !isset( $this->reactions[ $rep['app'] ][ $rep['type'] ][ $rep['type_id' ] ][ $rep['reaction'] ] ) )
{
$this->reactions[ $rep['app'] ][ $rep['type'] ][ $rep['type_id' ] ][ $rep['reaction'] ] = 0;
}
$this->reactions[ $rep['app'] ][ $rep['type'] ][ $rep['type_id' ] ][ $rep['reaction'] ]++;
}
}
@@ -258,9 +264,15 @@ class _Results extends \ArrayIterator
$containerClass = isset( $itemClass::$containerNodeClass ) ? $itemClass::$containerNodeClass : NULL;
$reputationData = array();
if ( in_array( 'IPS\Content\Reputation', class_implements( $class ) ) and isset( $this->reputationData[ $class::$application ][ $class::$reputationType ][ $data['index_object_id'] ] ) )
if ( \IPS\IPS::classUsesTrait( $class, 'IPS\Content\Reactable' ) and isset( $this->reputationData[ $class::$application ][ $class::reactionType() ][ $data['index_object_id'] ] ) )
{
$reputationData = $this->reputationData[ $class::$application ][ $class::$reputationType ][ $data['index_object_id'] ];
$reputationData = $this->reputationData[ $class::$application ][ $class::reactionType() ][ $data['index_object_id'] ];
}
$reactions = array();
if ( \IPS\IPS::classUsesTrait( $class, 'IPS\Content\Reactable' ) and isset( $this->reactions[ $class::$application ][ $class::reactionType() ][ $data['index_object_id'] ] ) )
{
$reactions = $this->reactions[ $class::$application ][ $class::reactionType() ][ $data['index_object_id'] ];
}
/* Ensure we have an item if results are gathered from the map table */
@@ -295,14 +307,25 @@ class _Results extends \ArrayIterator
$data['index_prefix'] = $this->prefixes[ $data['index_item_index_id'] ]['index_prefix'];
}
$containerData = NULL;
if ( $containerClass and isset( $this->containerData[ $containerClass ] ) and isset( $this->containerData[ $containerClass ][ $data['index_container_id'] ] ) )
{
$containerData = $this->containerData[ $containerClass ][ $data['index_container_id'] ];
if ( $data['index_club_id'] and isset( $this->containerData[ 'IPS\Member\Club' ][ $data['index_club_id'] ] ) )
{
$containerData['_club'] = $this->containerData[ 'IPS\Member\Club' ][ $data['index_club_id'] ];
}
}
return new Result\Content(
$data,
isset( $this->authorData[ $data['index_author'] ] ) ? $this->authorData[ $data['index_author'] ] : array( 'member_id' => 0, 'name' => \IPS\Member::loggedIn()->language()->addToStack('guest'), 'members_seo_name' => '', 'pp_main_photo' => NULL, 'pp_photo_type' => 'none' ),
$itemData,
( $containerClass and isset( $this->containerData[ $containerClass ] ) and isset( $this->containerData[ $containerClass ][ $data['index_container_id'] ] ) ) ? $this->containerData[ $containerClass ][ $data['index_container_id'] ] : NULL,
$containerData,
$reputationData,
isset( $this->reviewRatings[ $data['index_class'] ][ $data['index_object_id'] ] ) ? $this->reviewRatings[ $data['index_class'] ][ $data['index_object_id'] ] : NULL,
in_array( $data['index_item_index_id'], $this->iPostedIn )
in_array( $data['index_item_index_id'], $this->iPostedIn ),
$reactions
);
}
@@ -383,8 +406,15 @@ class _Results extends \ArrayIterator
}
else
{
foreach ( $results as $result )
foreach ( $results as $key => $result )
{
/* If an item has been removed incorrectly an orphan search index entry can be left. This is already logged in current() so let's not fail catastrophically */
if( !$result )
{
unset( $results[ $key ] );
continue;
}
$lastTime = $result->createdDate->getTimestamp();
}
}
@@ -481,6 +511,9 @@ class _Results extends \ArrayIterator
/* If an application was not updated or is not installed, do not try to fetch it or we can get a class does not exist fatal error */
$where[] = array( "follow_app IN('" . implode( "','", array_keys( \IPS\Application::enabledApplications() ) ) . "')" );
$lastClass = NULL;
$lastMember = NULL;
foreach ( \IPS\Db::i()->select( array( 'follow_app', 'follow_area', 'follow_rel_id', 'follow_member_id', 'follow_added' ), 'core_follow', $where, 'follow_added DESC', 10 ) as $follow )
{
if ( $follow['follow_app'] == 'core' and $follow['follow_area'] == 'member' )
@@ -493,66 +526,121 @@ class _Results extends \ArrayIterator
else
{
$class = 'IPS\\' . $follow['follow_app'] . '\\' . ucfirst( $follow['follow_area'] );
try
{
if ( class_exists( $class ) )
{
$thingBeingFollowed = $class::loadAndCheckPerms( $follow['follow_rel_id'] );
$thingBeingFollowed = $class::loadAndCheckPerms( $follow['follow_rel_id'] );
$urlToThing = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->basicUrl( $thingBeingFollowed->url(), FALSE, $thingBeingFollowed instanceof \IPS\Node\Model ? $thingBeingFollowed->_title : $thingBeingFollowed->mapped('title'), FALSE );
/* Do we need to merge with the last result? */
if( $lastClass !== NULL AND $lastClass === $class AND $lastMember === $follow['follow_member_id'] AND count( $extraItems ) )
{
$extraItem = array_pop( $extraItems );
$extraItems[] = new Result\Custom(
\IPS\DateTime::ts( $follow['follow_added'] ),
\IPS\Member::loggedIn()->language()->addToStack( 'activity_member_followed', FALSE, array( 'htmlsprintf' => array( \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->userLink( \IPS\Member::load( $follow['follow_member_id'] ) ), \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->basicUrl( $thingBeingFollowed->url(), FALSE, $thingBeingFollowed instanceof \IPS\Node\Model ? $thingBeingFollowed->_title : $thingBeingFollowed->mapped('title'), FALSE ) ) ) )
);
$mergeList = array_merge( array( $urlToThing ), $extraItem->getMergeData() );
$listToDisplay = $mergeList;
if( count( $mergeList ) > 3 )
{
$listToDisplay = array_slice( $mergeList, 0, 3 );
$listToDisplay[] = \IPS\Member::loggedIn()->language()->addToStack( 'and_x_others', FALSE, array( 'pluralize' => array( count( $mergeList ) - 3 ) ) );
}
$extraItem->mergeInData( \IPS\Member::loggedIn()->language()->addToStack( 'activity_member_followed', FALSE, array( 'htmlsprintf' => array( \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->userLink( \IPS\Member::load( $follow['follow_member_id'] ) ), \IPS\Member::loggedIn()->language()->formatList( $listToDisplay ) ) ) ), $urlToThing );
$extraItems[] = $extraItem;
}
else
{
$extraItems[] = new Result\Custom(
\IPS\DateTime::ts( $follow['follow_added'] ),
\IPS\Member::loggedIn()->language()->addToStack( 'activity_member_followed', FALSE, array( 'htmlsprintf' => array( \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->userLink( \IPS\Member::load( $follow['follow_member_id'] ) ), $urlToThing ) ) ),
NULL,
$urlToThing
);
}
}
}
catch ( \OutOfRangeException $e ) { }
$lastClass = $class;
$lastMember = $follow['follow_member_id'];
}
}
}
/* Likes */
if ( \IPS\Settings::i()->reputation_enabled and \IPS\Member::loggedIn()->group['gbw_view_reps'] and ( in_array( 'like', $extra ) or in_array( 'rep_neg', $extra ) ) )
if ( \IPS\Settings::i()->reputation_enabled and \IPS\Member::loggedIn()->group['gbw_view_reps'] and ( in_array( 'like', $extra ) or in_array( 'react', $extra ) ) )
{
$where = array( array( 'rep_date>?', $lastTime ) );
$where[] = array( 'reaction_enabled=?', 1 );
if ( $firstTime )
{
$where[] = array( 'rep_date<?', $firstTime );
}
if ( !in_array( 'rep_neg', $extra ) or ( \IPS\Settings::i()->reputation_point_types != 'both' and \IPS\Settings::i()->reputation_point_types != 'negative' ) )
{
$where[] = array( 'rep_rating=1' );
}
elseif ( !in_array( 'like', $extra ) or ( \IPS\Settings::i()->reputation_point_types == 'negative' ) )
{
$where[] = array( 'rep_rating=-1' );
}
/* get only the reputation data for installed applications */
$where[] = \IPS\Db::i()->in( 'app', array_keys( \IPS\Application::applications() ) ) ;
if ( $author )
{
foreach ( \IPS\Db::i()->select( '*', 'core_reputation_index', array_merge( $where, array( array( 'member_id=?', $author->member_id ) ) ), 'rep_date DESC', 10 ) as $rep )
foreach ( \IPS\Db::i()->select( '*', 'core_reputation_index', array_merge( $where, array( array( 'member_id=?', $author->member_id ) ) ), 'rep_date DESC', 10 )->join( 'core_reactions', 'reaction=reaction_id' ) as $rep )
{
$this->addReputationExtraItem( $rep, $extraItems );
}
foreach ( \IPS\Db::i()->select( '*', 'core_reputation_index', array_merge( $where, array( array( 'member_received=?', $author->member_id ) ) ), 'rep_date DESC', 10 ) as $rep )
foreach ( \IPS\Db::i()->select( '*', 'core_reputation_index', array_merge( $where, array( array( 'member_received=?', $author->member_id ) ) ), 'rep_date DESC', 10 )->join( 'core_reactions', 'reaction=reaction_id' ) as $rep )
{
$this->addReputationExtraItem( $rep, $extraItems );
}
}
else
{
foreach ( \IPS\Db::i()->select( '*', 'core_reputation_index', $where, 'rep_date DESC', 10 ) as $rep )
foreach ( \IPS\Db::i()->select( '*', 'core_reputation_index', $where, 'rep_date DESC', 10 )->join( 'core_reactions', 'reaction=reaction_id' ) as $rep )
{
$this->addReputationExtraItem( $rep, $extraItems );
}
}
}
/* Clubs */
if ( \IPS\Settings::i()->clubs and in_array( 'clubs', $extra ) )
{
$where = array( array( 'created>?', $lastTime ) );
if ( $firstTime )
{
$where[] = array( 'created<?', $firstTime );
}
if ( $author )
{
$where[] = array( 'owner=?', $author->member_id );
}
foreach ( \IPS\Member\Club::clubs( \IPS\Member::loggedIn(), NULL, 'created', FALSE, array(), $where ) as $club )
{
if ( $club->owner AND $club->owner->member_id )
{
$extraItems[] = new Result\Custom(
$club->created,
\IPS\Member::loggedIn()->language()->addToStack( 'activity_club', FALSE, array( 'htmlsprintf' => array( \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->userLink( $club->owner ), \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->basicUrl( $club->url(), FALSE, $club->name, FALSE ) ) ) )
);
}
}
}
/* Extensions */
foreach ( \IPS\Application::allExtensions( 'core', 'StreamItems', TRUE, 'core' ) as $key => $extension )
{
$settingKey = "all_activity_" . mb_strtolower( $key );
if( method_exists( $extension, 'extraItems' ) and \IPS\Settings::i()->$settingKey )
{
$extraItems = array_merge( $extraItems, $extension->extraItems( $author, $lastTime, $firstTime ) );
}
}
}
/* Merge them in */
if ( !empty( $extraItems ) )
{
@@ -594,7 +682,7 @@ class _Results extends \ArrayIterator
{
foreach ( $ext->classes as $class )
{
if ( in_array( 'IPS\Content\Reputation', class_implements( $class ) ) and $class::$reputationType == $rep['type'] )
if ( \IPS\IPS::classUsesTrait( $class, 'IPS\Content\Reactable' ) and $class::reactionType() == $rep['type'] )
{
$thingBeingRepped = $class::loadAndCheckPerms( $rep['type_id'] );
break;
@@ -602,7 +690,7 @@ class _Results extends \ArrayIterator
if ( isset( $class::$commentClass ) )
{
$commentClass = $class::$commentClass;
if ( in_array( 'IPS\Content\Reputation', class_implements( $commentClass ) ) and $commentClass::$reputationType == $rep['type'] )
if ( \IPS\IPS::classUsesTrait( $commentClass, 'IPS\Content\Reactable' ) and $commentClass::reactionType() == $rep['type'] )
{
$thingBeingRepped = $commentClass::loadAndCheckPerms( $rep['type_id'] );
break;
@@ -611,7 +699,7 @@ class _Results extends \ArrayIterator
if ( isset( $class::$reviewClass ) )
{
$reviewClass = $class::$reviewClass;
if ( in_array( 'IPS\Content\Reputation', class_implements( $reviewClass ) ) and $reviewClass::$reputationType == $rep['type'] )
if ( \IPS\IPS::classUsesTrait( $reviewClass, 'IPS\Content\Reactable' ) and $reviewClass::reactionType() == $rep['type'] )
{
$thingBeingRepped = $reviewClass::loadAndCheckPerms( $rep['type_id'] );
break;
@@ -624,27 +712,31 @@ class _Results extends \ArrayIterator
throw new \OutOfRangeException;
}
if ( \IPS\Settings::i()->reputation_point_types == 'like' )
if ( \IPS\Content\Reaction::isLikeMode() )
{
$lang = 'activity_member_liked';
}
elseif ( $rep['rep_rating'] > 0 )
{
$lang = 'activity_rep_pos';
$extraItems[] = new Result\Custom(
\IPS\DateTime::ts( $rep['rep_date'] ),
\IPS\Member::loggedIn()->language()->addToStack( 'activity_member_liked', FALSE, array( 'htmlsprintf' => array(
\IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->userLink( \IPS\Member::load( $rep['member_id'] ) ),
$thingBeingRepped->indefiniteArticle(),
\IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->basicUrl( $thingBeingRepped->url(), FALSE, $thingBeingRepped instanceof \IPS\Content\Item ? $thingBeingRepped->mapped('title') : $thingBeingRepped->item()->mapped('title'), FALSE )
) ) )
);
}
else
{
$lang = 'activity_rep_neg';
$reaction = \IPS\Content\Reaction::load( $rep['reaction'] );
$extraItems[] = new Result\Custom(
\IPS\DateTime::ts( $rep['rep_date'] ),
\IPS\Member::loggedIn()->language()->addToStack( 'activity_member_reacted', FALSE, array( 'htmlsprintf' => array(
(string) $reaction->_icon,
$reaction->_title,
\IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->userLink( \IPS\Member::load( $rep['member_id'] ) ),
$thingBeingRepped->indefiniteArticle(),
\IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->basicUrl( $thingBeingRepped->url(), FALSE, $thingBeingRepped instanceof \IPS\Content\Item ? $thingBeingRepped->mapped('title') : $thingBeingRepped->item()->mapped('title'), FALSE )
) ) )
);
}
$extraItems[] = new Result\Custom(
\IPS\DateTime::ts( $rep['rep_date'] ),
\IPS\Member::loggedIn()->language()->addToStack( $lang, FALSE, array( 'htmlsprintf' => array(
\IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->userLink( \IPS\Member::load( $rep['member_id'] ) ),
$thingBeingRepped->indefiniteArticle(),
\IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->basicUrl( $thingBeingRepped->url(), FALSE, $thingBeingRepped instanceof \IPS\Content\Item ? $thingBeingRepped->mapped('title') : $thingBeingRepped->item()->mapped('title'), FALSE )
) ) )
);
}
catch ( \OutOfRangeException $e ) { }
}