Version 4.3.0
This commit is contained in:
1 parent
96997ddd8e
commit
fe1acf984a
1349 files changed
+116159
-67711
No files matched your search
+137
-76
@@ -32,6 +32,16 @@ trait Reactable
|
||||
throw new \BadMethodCallException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reaction class
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function reactionClass()
|
||||
{
|
||||
return get_called_class();
|
||||
}
|
||||
|
||||
/**
|
||||
* React
|
||||
*
|
||||
@@ -54,9 +64,9 @@ trait Reactable
|
||||
{
|
||||
$owner = $this->owner();
|
||||
}
|
||||
|
||||
|
||||
/* Can we react? */
|
||||
if ( $this->canReact( $member ) === FALSE )
|
||||
if ( !$this->canView( $member ) or !$this->canReact( $member ) or !$reaction->enabled )
|
||||
{
|
||||
throw new \DomainException( 'cannot_react' );
|
||||
}
|
||||
@@ -92,7 +102,10 @@ trait Reactable
|
||||
}
|
||||
|
||||
/* Have we already reacted? */
|
||||
if ( $this->reacted( $member ) )
|
||||
$reacted = $this->reacted( $member );
|
||||
|
||||
/* Remove the initial reaction, if we have reacted */
|
||||
if ( $reacted )
|
||||
{
|
||||
$this->removeReaction( $member );
|
||||
}
|
||||
@@ -107,16 +120,16 @@ trait Reactable
|
||||
'rep_date' => \IPS\DateTime::create()->getTimestamp(),
|
||||
'rep_rating' => $reaction->value,
|
||||
'member_received' => $owner->member_id,
|
||||
'rep_class' => get_class( $this ),
|
||||
'class_type_id_hash' => md5( get_class( $this ) . ':' . $this->$idColumn ),
|
||||
'rep_class' => static::reactionClass(),
|
||||
'class_type_id_hash' => md5( static::reactionClass() . ':' . $this->$idColumn ),
|
||||
'item_id' => $itemId,
|
||||
'reaction' => $reaction->id
|
||||
) );
|
||||
|
||||
/* Send the notification */
|
||||
if ( $this->author()->member_id AND $this->author() != \IPS\Member::loggedIn() AND $this->canView( $owner ) )
|
||||
|
||||
/* Send the notification but only if we aren't reacting to our own content, we can view the content, the user isn't ignored and we aren't changing from one reaction to another */
|
||||
if ( $this->author()->member_id AND $this->author() != \IPS\Member::loggedIn() AND $this->canView( $owner ) AND !$reacted AND !$member->isIgnoring( $this->author(), 'posts' ) )
|
||||
{
|
||||
$notification = new \IPS\Notification( \IPS\Application::load('core'), 'new_likes', $this, array( $this, $member ) );
|
||||
$notification = new \IPS\Notification( \IPS\Application::load('core'), 'new_likes', $this, array( $this, $member ), array(), TRUE, \IPS\Content\Reaction::isLikeMode() ? NULL : 'notification_new_react' );
|
||||
$notification->recipients->attach( $owner );
|
||||
$notification->send();
|
||||
}
|
||||
@@ -126,6 +139,12 @@ trait Reactable
|
||||
$owner->pp_reputation_points += $reaction->value;
|
||||
$owner->save();
|
||||
}
|
||||
|
||||
/* Reset some cached values */
|
||||
$this->_reactionCount = NULL;
|
||||
$this->_reactions = NULL;
|
||||
|
||||
$this->hasReacted[ $member->member_id ] = $reaction;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -143,7 +162,10 @@ trait Reactable
|
||||
try
|
||||
{
|
||||
$idColumn = static::$databaseColumnId;
|
||||
$rep = \IPS\Db::i()->select( '*', 'core_reputation_index', array( "member_id=? AND rep_class=? AND type=? AND type_id=?", $member->member_id, get_class( $this ), static::reactionType(), $this->$idColumn ) )->first();
|
||||
|
||||
$where = $this->getReactionWhereClause( NULL, FALSE );
|
||||
$where[] = array( 'member_id=?', $member->member_id );
|
||||
$rep = \IPS\Db::i()->select( '*', 'core_reputation_index', $where )->first();
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
@@ -165,6 +187,30 @@ trait Reactable
|
||||
}
|
||||
|
||||
\IPS\Db::i()->delete( 'core_reputation_index', array( "id=?", $rep['id'] ) );
|
||||
|
||||
/* Remove Notifications */
|
||||
$memberIds = array();
|
||||
|
||||
foreach( \IPS\Db::i()->select( 'member', 'core_notifications', array( 'notification_key=? AND item_class=? AND item_id=?', 'new_likes', (string) get_class( $this ), (int) $this->$idColumn ) ) as $member )
|
||||
{
|
||||
$memberIds[ $member ] = $member;
|
||||
}
|
||||
|
||||
\IPS\Db::i()->delete( 'core_notifications', array( 'notification_key=? AND item_class=? AND item_id=?', 'new_likes', (string) get_class( $this ), (int) $this->$idColumn ) );
|
||||
|
||||
foreach( $memberIds as $member )
|
||||
{
|
||||
\IPS\Member::load( $member )->recountNotifications();
|
||||
}
|
||||
|
||||
/* Reset some cached values */
|
||||
$this->_reactionCount = NULL;
|
||||
$this->_reactions = NULL;
|
||||
|
||||
if( isset( $this->hasReacted[ $member->member_id ] ) )
|
||||
{
|
||||
unset( $this->hasReacted[ $member->member_id ] );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -244,20 +290,25 @@ trait Reactable
|
||||
|
||||
if ( is_array( $this->reputation ) )
|
||||
{
|
||||
foreach( $this->reputation AS $memberId => $reactionId )
|
||||
if ( $enabledReactions = \IPS\Content\Reaction::enabledReactions() )
|
||||
{
|
||||
try
|
||||
foreach( $this->reputation AS $memberId => $reactionId )
|
||||
{
|
||||
$this->_reactionCount += \IPS\Content\Reaction::load( $reactionId )->value;
|
||||
$this->_reactions[ $memberId ][] = $reactionId;
|
||||
if( isset( $enabledReactions[ $reactionId ] ) )
|
||||
{
|
||||
$this->_reactionCount += $enabledReactions[ $reactionId ]->value;
|
||||
$this->_reactions[ $memberId ][] = $reactionId;
|
||||
}
|
||||
}
|
||||
catch( \OutOfRangeException $e ) { }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the data in $this->reputation to save queries later */
|
||||
$this->reputation = array();
|
||||
foreach( \IPS\Db::i()->select( '*', 'core_reputation_index', $this->getReactionWhereClause() )->join( 'core_reactions', 'reaction=reaction_id' ) AS $reaction )
|
||||
{
|
||||
$this->reputation[ $reaction['member_id'] ] = $reaction['reaction'];
|
||||
$this->_reactions[ $reaction['member_id'] ][] = $reaction['reaction'];
|
||||
$this->_reactionCount += $reaction['rep_rating'];
|
||||
}
|
||||
@@ -279,20 +330,30 @@ trait Reactable
|
||||
*/
|
||||
public function reactionCount()
|
||||
{
|
||||
$this->reactions();
|
||||
if( $this->_reactionCount === NULL )
|
||||
{
|
||||
$this->reactions();
|
||||
}
|
||||
|
||||
return $this->_reactionCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reaction Where Clause
|
||||
*
|
||||
* @param \IPS\Content\Reaction|array|int|NULL This can be any one of the following: An \IPS\Content\Reaction object, an array of \IPS\Content\Reaction objects, and integer, or an array of integers, or NULL
|
||||
* @param \IPS\Content\Reaction|array|int|NULL $reactions This can be any one of the following: An \IPS\Content\Reaction object, an array of \IPS\Content\Reaction objects, and integer, or an array of integers, or NULL
|
||||
* @param bool $enabledTypesOnly If TRUE, only reactions of the enabled reaction types will be included (must join core_reactions)
|
||||
* @return array
|
||||
*/
|
||||
public function getReactionWhereClause( $reactions = NULL )
|
||||
public function getReactionWhereClause( $reactions = NULL, $enabledTypesOnly=TRUE )
|
||||
{
|
||||
$idColumn = static::$databaseColumnId;
|
||||
$where = array( array( 'rep_class=? AND type=? AND type_id=? AND reaction_enabled=?', get_class( $this ), static::reactionType(), $this->$idColumn, 1 ) );
|
||||
$where = array( array( 'rep_class=? AND type=? AND type_id=?', static::reactionClass(), static::reactionType(), $this->$idColumn ) );
|
||||
|
||||
if ( $enabledTypesOnly )
|
||||
{
|
||||
$where[] = array( 'reaction_enabled=1' );
|
||||
}
|
||||
|
||||
if ( $reactions !== NULL )
|
||||
{
|
||||
@@ -330,7 +391,7 @@ trait Reactable
|
||||
*/
|
||||
public function reactionTable( $reaction=NULL )
|
||||
{
|
||||
if ( !\IPS\Member::loggedIn()->group['gbw_view_reps'] )
|
||||
if ( !\IPS\Member::loggedIn()->group['gbw_view_reps'] or !$this->canView() )
|
||||
{
|
||||
throw new \DomainException;
|
||||
}
|
||||
@@ -358,7 +419,12 @@ trait Reactable
|
||||
|
||||
return $table;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Cached Reacted
|
||||
*/
|
||||
protected $hasReacted = array();
|
||||
|
||||
/**
|
||||
* Has reacted?
|
||||
*
|
||||
@@ -368,30 +434,31 @@ trait Reactable
|
||||
public function reacted( \IPS\Member $member = NULL )
|
||||
{
|
||||
$member = $member ?: \IPS\Member::loggedIn();
|
||||
|
||||
$idColumn = static::$databaseColumnId;
|
||||
try
|
||||
|
||||
if( !isset( $this->hasReacted[ $member->member_id ] ) )
|
||||
{
|
||||
if ( is_array( $this->reputation ) )
|
||||
$this->hasReacted[ $member->member_id ] = FALSE;
|
||||
|
||||
try
|
||||
{
|
||||
if ( isset( $this->reputation[ $member->member_id ] ) )
|
||||
if ( is_array( $this->reputation ) )
|
||||
{
|
||||
return \IPS\Content\Reaction::load( $this->reputation[ $member->member_id ] );
|
||||
if ( isset( $this->reputation[ $member->member_id ] ) )
|
||||
{
|
||||
$this->hasReacted[ $member->member_id ] = \IPS\Content\Reaction::load( $this->reputation[ $member->member_id ] );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
$where = $this->getReactionWhereClause( NULL, FALSE );
|
||||
$where[] = array( 'member_id=?', $member->member_id );
|
||||
$this->hasReacted[ $member->member_id ] = \IPS\Content\Reaction::load( \IPS\Db::i()->select( 'reaction', 'core_reputation_index', $where )->first() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return \IPS\Content\Reaction::load( \IPS\Db::i()->select( 'reaction', 'core_reputation_index', array( "member_id=? AND rep_class=? AND type=? AND type_id=?", $member->member_id, get_class( $this ), static::reactionType(), $this->$idColumn ) )->first() );
|
||||
}
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
return FALSE;
|
||||
catch( \UnderflowException $e ){}
|
||||
}
|
||||
|
||||
return $this->hasReacted[ $member->member_id ];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -413,51 +480,44 @@ trait Reactable
|
||||
if ( count( $this->reactions() ) )
|
||||
{
|
||||
$idColumn = static::$databaseColumnId;
|
||||
/* Figure out our app - we do it this way as content items and nodes will always have a lowercase namespace for the app, so if the match below fails, then 'core' can be assumed */
|
||||
$app = explode( '\\', get_class( $this ) );
|
||||
if ( \strtolower( $app[1] ) === $app[1] )
|
||||
if ( is_array( $this->reputation ) )
|
||||
{
|
||||
$app = $app[1];
|
||||
foreach( $this->reputation AS $memberId => $reaction )
|
||||
{
|
||||
if ( !isset( $this->reactBlurb[ $reaction ] ) )
|
||||
{
|
||||
$this->reactBlurb[ $reaction ] = 0;
|
||||
}
|
||||
|
||||
$this->reactBlurb[ $reaction ]++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$app = 'core';
|
||||
}
|
||||
foreach( \IPS\Db::i()->select( 'reaction', 'core_reputation_index', array( "app=? AND rep_class=? AND type=? AND type_id=?", $app, get_class( $this ), static::reactionType(), $this->$idColumn ) ) AS $rep )
|
||||
{
|
||||
if ( !isset( $this->reactBlurb[ $rep ] ) )
|
||||
foreach( \IPS\Db::i()->select( 'reaction', 'core_reputation_index', $this->getReactionWhereClause() )->join( 'core_reactions', 'reaction=reaction_id' ) AS $rep )
|
||||
{
|
||||
$this->reactBlurb[ $rep ] = 0;
|
||||
if ( !isset( $this->reactBlurb[ $rep ] ) )
|
||||
{
|
||||
$this->reactBlurb[ $rep ] = 0;
|
||||
}
|
||||
|
||||
$this->reactBlurb[ $rep ]++;
|
||||
}
|
||||
|
||||
$this->reactBlurb[ $rep ]++;
|
||||
}
|
||||
|
||||
/* Error suppressor for https://bugs.php.net/bug.php?id=50688 */
|
||||
@uksort( $this->reactBlurb, function( $a, $b ) {
|
||||
try
|
||||
{
|
||||
$a = \IPS\Content\Reaction::load( $a );
|
||||
$b = \IPS\Content\Reaction::load( $b );
|
||||
}
|
||||
/* One of the reactions does not exist */
|
||||
catch( \OutOfRangeException $e )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
$enabledReactions = \IPS\Content\Reaction::enabledReactions();
|
||||
|
||||
@uksort( $this->reactBlurb, function( $a, $b ) use( $enabledReactions ) {
|
||||
$positionA = $enabledReactions[ $a ]->position;
|
||||
$positionB = $enabledReactions[ $b ]->position;
|
||||
|
||||
if ( $a->position < $b->position )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
elseif ( $a->position == $b->position )
|
||||
if ( $positionA == $positionB )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return ( $positionA < $positionB ) ? -1 : 1;
|
||||
} );
|
||||
}
|
||||
else
|
||||
@@ -495,9 +555,9 @@ trait Reactable
|
||||
}
|
||||
|
||||
/* Did anyone like it? */
|
||||
$numberOfLikes = $this->reactionCount(); # int
|
||||
$numberOfLikes = count( $this->reactions() ); # int
|
||||
if ( $numberOfLikes )
|
||||
{
|
||||
{
|
||||
/* Is it just us? */
|
||||
$userLiked = ( $this->reacted() );
|
||||
if ( $userLiked and $numberOfLikes < 2 )
|
||||
@@ -521,11 +581,10 @@ trait Reactable
|
||||
$peopleToDisplayInSecondaryView = array();
|
||||
|
||||
/* Some random names */
|
||||
$idColumn = static::$databaseColumnId;
|
||||
$i = 0;
|
||||
$peopleToDisplayInSecondaryView = array();
|
||||
/* Figure out our app - we do it this way as content items and nodes will always have a lowercase namespace for the app, so if the match below fails, then 'core' can be assumed */
|
||||
$app = explode( '\\', get_class( $this ) );
|
||||
$app = explode( '\\', static::reactionClass() );
|
||||
if ( \strtolower( $app[1] ) === $app[1] )
|
||||
{
|
||||
$app = $app[1];
|
||||
@@ -534,16 +593,18 @@ trait Reactable
|
||||
{
|
||||
$app = 'core';
|
||||
}
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_reputation_index', array( 'app=? AND type=? AND type_id=? AND member_id!=?', $app, static::reactionType(), $this->$idColumn, ( \IPS\Member::loggedIn()->member_id ) ?: 0 ), 'RAND()', $userLiked ? 17 : 18 ) as $rep )
|
||||
$where = $this->getReactionWhereClause();
|
||||
$where[] = array( 'member_id!=?', \IPS\Member::loggedIn()->member_id ?: 0 );
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_reputation_index', $where, 'RAND()', $userLiked ? 17 : 18 )->join( 'core_reactions', 'reaction=reaction_id' ) as $rep )
|
||||
{
|
||||
if ( $i < ( $userLiked ? 2 : 3 ) )
|
||||
{
|
||||
$peopleToDisplayInMainView[] = htmlspecialchars( \IPS\Member::load( $rep['member_id'] )->name, ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE );
|
||||
$peopleToDisplayInMainView[] = htmlspecialchars( \IPS\Member::load( $rep['member_id'] )->name, ENT_QUOTES | ENT_DISALLOWED, 'UTF-8', FALSE );
|
||||
$andXOthers--;
|
||||
}
|
||||
else
|
||||
{
|
||||
$peopleToDisplayInSecondaryView[] = htmlspecialchars( \IPS\Member::load( $rep['member_id'] )->name, ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE );
|
||||
$peopleToDisplayInSecondaryView[] = htmlspecialchars( \IPS\Member::load( $rep['member_id'] )->name, ENT_QUOTES | ENT_DISALLOWED, 'UTF-8', FALSE );
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
@@ -569,7 +630,7 @@ trait Reactable
|
||||
$this->likeBlurb = '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $this->likeBlurb;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user