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

+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 ) { }
}