Version 4.7.0
This commit is contained in:
1 parent
517a5e1f70
commit
8ba7d43898
1933 files changed
+65613
-11332
No files matched your search
+210
-20
@@ -59,15 +59,18 @@ abstract class _Comment extends \IPS\Content
|
||||
* @param \IPS\DateTime|NULL $time The time
|
||||
* @param string|NULL $ipAddress The IP address or NULL to detect automatically
|
||||
* @param int|NULL $hiddenStatus NULL to set automatically or override: 0 = unhidden; 1 = hidden, pending moderator approval; -1 = hidden (as if hidden by a moderator)
|
||||
* @param int|NULL $anonymous NULL for no value, 0 or 1 for a value (0=no, 1=yes)
|
||||
* @return static
|
||||
*/
|
||||
public static function create( $item, $comment, $first=FALSE, $guestName=NULL, $incrementPostCount=NULL, $member=NULL, \IPS\DateTime $time=NULL, $ipAddress=NULL, $hiddenStatus=NULL )
|
||||
public static function create( $item, $comment, $first=FALSE, $guestName=NULL, $incrementPostCount=NULL, $member=NULL, \IPS\DateTime $time=NULL, $ipAddress=NULL, $hiddenStatus=NULL, $anonymous=NULL )
|
||||
{
|
||||
if ( $member === NULL )
|
||||
{
|
||||
$member = \IPS\Member::loggedIn();
|
||||
}
|
||||
|
||||
$idColumn = $item::$databaseColumnId;
|
||||
|
||||
/* Create the object */
|
||||
$obj = new static;
|
||||
foreach ( array( 'item', 'date', 'author', 'author_name', 'content', 'ip_address', 'first', 'approved', 'hidden' ) as $k )
|
||||
@@ -78,7 +81,6 @@ abstract class _Comment extends \IPS\Content
|
||||
switch ( $k )
|
||||
{
|
||||
case 'item':
|
||||
$idColumn = $item::$databaseColumnId;
|
||||
$val = $item->$idColumn;
|
||||
break;
|
||||
|
||||
@@ -184,42 +186,52 @@ abstract class _Comment extends \IPS\Content
|
||||
}
|
||||
|
||||
/* Check if profanity filters should mod-queue this comment */
|
||||
$obj->checkProfanityFilters( $first );
|
||||
$obj->checkProfanityFilters( $first, FALSE );
|
||||
|
||||
/* Save the comment */
|
||||
$obj->save();
|
||||
|
||||
/* Set anonymous status */
|
||||
if( $anonymous !== NULL )
|
||||
{
|
||||
try
|
||||
{
|
||||
$obj->setAnonymous( (bool) $anonymous, $member );
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
}
|
||||
|
||||
/* Increment post count */
|
||||
try
|
||||
{
|
||||
if ( !$obj->isAnonymous() and !$obj->hidden() and ( $incrementPostCount === TRUE or ( $incrementPostCount === NULL and static::incrementPostCount( $item->container() ) ) ) )
|
||||
{
|
||||
$obj->author()->member_posts++;
|
||||
$member->member_posts++;
|
||||
}
|
||||
}
|
||||
catch( \BadMethodCallException $e ) { }
|
||||
|
||||
|
||||
/* Update member's last post and daily post limits */
|
||||
if( $obj->author()->member_id AND $obj::incrementPostCount() )
|
||||
if( $member->member_id AND $obj::incrementPostCount() )
|
||||
{
|
||||
$obj->author()->member_last_post = time();
|
||||
|
||||
$member->member_last_post = time();
|
||||
|
||||
/* Update posts per day limits */
|
||||
if ( $obj->author()->group['g_ppd_limit'] )
|
||||
if ( $member->group['g_ppd_limit'] )
|
||||
{
|
||||
$current = $obj->author()->members_day_posts;
|
||||
$current = $member->members_day_posts;
|
||||
|
||||
$current[0] += 1;
|
||||
if ( $current[1] == 0 )
|
||||
{
|
||||
$current[1] = \IPS\DateTime::create()->getTimestamp();
|
||||
}
|
||||
|
||||
$obj->author()->members_day_posts = $current;
|
||||
|
||||
$member->members_day_posts = $current;
|
||||
}
|
||||
|
||||
$obj->author()->save();
|
||||
|
||||
$member->save();
|
||||
}
|
||||
|
||||
/* Send notifications and dish out points */
|
||||
@@ -228,7 +240,7 @@ abstract class _Comment extends \IPS\Content
|
||||
if ( !$obj->hidden() and ( !$first or !$item::$firstCommentRequired ) )
|
||||
{
|
||||
$obj->sendNotifications();
|
||||
$obj->author()->achievementAction( 'core', 'Comment', $obj );
|
||||
$member->achievementAction( 'core', 'Comment', $obj );
|
||||
}
|
||||
else if( $obj->hidden() === 1 )
|
||||
{
|
||||
@@ -241,10 +253,45 @@ abstract class _Comment extends \IPS\Content
|
||||
{
|
||||
\IPS\Api\Webhook::fire( str_replace( '\\', '', \substr( \get_called_class(), 3 ) ) . '_create', $obj, $obj->webhookFilters() );
|
||||
}
|
||||
|
||||
|
||||
/* DataLayer Event */
|
||||
if ( \IPS\Settings::i()->core_datalayer_enabled and !( $item::$firstCommentRequired and $obj->isFirst() ) )
|
||||
{
|
||||
if ( isset( $item::$title ) and $item::$title === \IPS\core\Statuses\Status::$title )
|
||||
{
|
||||
$event = 'social_reply';
|
||||
$member = \IPS\Member::load( $item->member_id );
|
||||
$properties = array(
|
||||
'profile_id' => $member->member_id,
|
||||
'profile_name' => $member->name,
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$event = 'comment_create';
|
||||
$properties = $obj->getDataLayerProperties();
|
||||
}
|
||||
|
||||
if ( $properties['content_area'] === 'personal_messages' )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$properties = array_merge( $properties, array(
|
||||
'author_id' => $obj->author()->member_id,
|
||||
'author_name' => $obj->author()->name ?? 'Guest',
|
||||
) );
|
||||
|
||||
\IPS\core\DataLayer::i()->addEvent( $event, $properties );
|
||||
}
|
||||
|
||||
/* Update item */
|
||||
$obj->postCreate();
|
||||
|
||||
/* This needs to happen before the index is added */
|
||||
$parameters = array_merge( array( 'reply-' . $item::$application . '/' . $item::$module . '-' . $item->$idColumn ), $obj->attachmentIds() );
|
||||
\IPS\File::claimAttachments( ...$parameters );
|
||||
|
||||
/* Add to search index */
|
||||
if ( $obj instanceof \IPS\Content\Searchable )
|
||||
{
|
||||
@@ -254,6 +301,32 @@ abstract class _Comment extends \IPS\Content
|
||||
/* Return */
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Field cache for getDataLayerProperties
|
||||
*/
|
||||
protected $_dataLayerProperties = array();
|
||||
|
||||
/**
|
||||
* Get the properties that can be added to the datalayer for this key
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDataLayerProperties()
|
||||
{
|
||||
if ( empty( $this->_dataLayerProperties ) )
|
||||
{
|
||||
$item = $this->item();
|
||||
$this->_dataLayerProperties = $item->getDataLayerProperties( $this );
|
||||
if ( $this->_dataLayerProperties['content_type'] === 'question' )
|
||||
{
|
||||
$this->_dataLayerProperties['comment_type'] = 'answer';
|
||||
}
|
||||
$this->_dataLayerProperties = \IPS\core\DataLayer::i()->filterProperties( $this->_dataLayerProperties );
|
||||
}
|
||||
|
||||
return $this->_dataLayerProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join profile fields when loading comments?
|
||||
@@ -376,6 +449,18 @@ abstract class _Comment extends \IPS\Content
|
||||
{
|
||||
$item->container()->rebuildPostedIn( array( $item->$itemIdColumn ), array( $this->author() ) );
|
||||
}
|
||||
|
||||
/* Update trending */
|
||||
$class = \get_class( $item );
|
||||
if( \IPS\Application::appIsEnabled( 'cloud' ) and \IPS\cloud\Realtime::i()->isEnabled('trending') and $class::$includeInTrending )
|
||||
{
|
||||
/* Score by timestamp for trending */
|
||||
try
|
||||
{
|
||||
\IPS\Redis::i()->zIncrBy( 'trending', time(), $class . '__' . $item->$itemIdColumn );
|
||||
}
|
||||
catch( \Exception $e ) { }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -827,6 +912,12 @@ abstract class _Comment extends \IPS\Content
|
||||
{
|
||||
$item->clearCachedStatistics();
|
||||
}
|
||||
|
||||
/* Send the content items URL to IndexNow if the guest can view it */
|
||||
if( $item->canView( new \IPS\Member ) )
|
||||
{
|
||||
\IPS\core\IndexNow::addUrlToQueue( $item->url() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -844,6 +935,48 @@ abstract class _Comment extends \IPS\Content
|
||||
$itemColumn = static::$databaseColumnMap['item'];
|
||||
$commentIdColumn = static::$databaseColumnId;
|
||||
$this->$itemColumn = $item->$idColumn;
|
||||
|
||||
/* Does this comment's hidden status align with its item's hidden status? */
|
||||
if ( $this instanceof \IPS\Content\Hideable AND $this->hidden() !== 1 )
|
||||
{
|
||||
if ( $item->hidden() === -1 )
|
||||
{
|
||||
if ( isset( static::$databaseColumnMap['hidden'] ) )
|
||||
{
|
||||
$column = static::$databaseColumnMap['hidden'];
|
||||
|
||||
/* if this comment was directly hidden, we don't want to inherit its status from the item */
|
||||
if ( \intval( $this->$column ) !== -1 )
|
||||
{
|
||||
$this->$column = 2;
|
||||
}
|
||||
}
|
||||
elseif ( isset( static::$databaseColumnMap['approved'] ) )
|
||||
{
|
||||
$column = static::$databaseColumnMap['approved'];
|
||||
$this->$column = -1;
|
||||
}
|
||||
}
|
||||
elseif ( $this->hidden() === -1 )
|
||||
{
|
||||
if ( isset( static::$databaseColumnMap['hidden'] ) )
|
||||
{
|
||||
$column = static::$databaseColumnMap['hidden'];
|
||||
|
||||
/* if this comment was directly hidden, we don't want to inherit its status from the item */
|
||||
if ( \intval( $this->$column ) !== -1 )
|
||||
{
|
||||
$this->$column = 0;
|
||||
}
|
||||
}
|
||||
elseif ( isset( static::$databaseColumnMap['approved'] ) )
|
||||
{
|
||||
$column = static::$databaseColumnMap['approved'];
|
||||
$this->$column = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->save();
|
||||
|
||||
/* The new item needs to re-claim any attachments associated with this comment */
|
||||
@@ -865,7 +998,16 @@ abstract class _Comment extends \IPS\Content
|
||||
}
|
||||
|
||||
/* Update member map */
|
||||
\IPS\Db::i()->update( 'core_item_member_map', array( 'map_item_id' => $item->$idColumn ), array( 'map_class=? and map_item_id=?', \get_class( $oldItem ), $oldItem->$idColumn ) );
|
||||
try
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_item_member_map', array( 'map_item_id' => $item->$idColumn ), array( 'map_class=? and map_item_id=?', \get_class( $oldItem ), $oldItem->$idColumn ) );
|
||||
}
|
||||
catch( \IPS\Db\Exception $e )
|
||||
{
|
||||
/* If we are splitting to a topic that this member has already posted in, this will cause a duplicate key issue. Best to remove rows and let the next page load rebuild */
|
||||
\IPS\Db::i()->delete( 'core_item_member_map', array( 'map_class=? and map_item_id=?', \get_class( $oldItem ), $oldItem->$idColumn ) );
|
||||
\IPS\Db::i()->delete( 'core_item_member_map', array( 'map_class=? and map_item_id=?', \get_class( $item ), $item->$idColumn ) );
|
||||
}
|
||||
|
||||
if( $skip === FALSE )
|
||||
{
|
||||
@@ -883,6 +1025,23 @@ abstract class _Comment extends \IPS\Content
|
||||
$item->clearCachedStatistics();
|
||||
}
|
||||
}
|
||||
|
||||
/* Send the content items URL to IndexNow */
|
||||
$noIndexUrls = [];
|
||||
$guest = new \IPS\Member;
|
||||
|
||||
if( $oldItem->canView( $guest ) )
|
||||
{
|
||||
$noIndexUrls[] = $oldItem->url();
|
||||
}
|
||||
if( $item->canView( $guest ) )
|
||||
{
|
||||
$noIndexUrls[] = $item->url();
|
||||
}
|
||||
if( $oldItem->canView( new \IPS\Member ) )
|
||||
{
|
||||
\IPS\core\IndexNow::addUrlsToQueue( $noIndexUrls );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1505,7 +1664,7 @@ abstract class _Comment extends \IPS\Content
|
||||
$attachments[] = array( 'core_Clubs' => $club->cover_photo );
|
||||
}
|
||||
|
||||
return \count( $attachments ) ? $attachments : NULL;
|
||||
return \count( $attachments ) ? \array_slice( $attachments, 0, $limit ) : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1593,12 +1752,13 @@ abstract class _Comment extends \IPS\Content
|
||||
* @apiresponse string content The content
|
||||
* @apiresponse bool hidden Is hidden?
|
||||
* @apiresponse string url URL to content
|
||||
* @apiresponse array reactions Array of reactions given, array key is member_id of reaction giver ([member_id => [ title, id, value, icon ]])
|
||||
*/
|
||||
public function apiOutput( \IPS\Member $authorizedMember = NULL )
|
||||
{
|
||||
$idColumn = static::$databaseColumnId;
|
||||
$itemColumn = static::$databaseColumnMap['item'];
|
||||
return array(
|
||||
$return = array(
|
||||
'id' => $this->$idColumn,
|
||||
'item_id' => $this->$itemColumn,
|
||||
'author' => $this->author()->apiOutput( $authorizedMember ),
|
||||
@@ -1607,6 +1767,35 @@ abstract class _Comment extends \IPS\Content
|
||||
'hidden' => (bool) $this->hidden(),
|
||||
'url' => (string) $this->url()
|
||||
);
|
||||
|
||||
if ( \IPS\IPS::classUsesTrait( $this, 'IPS\Content\Reactable' ) )
|
||||
{
|
||||
if ( $reactions = $this->reactions() )
|
||||
{
|
||||
$enabledReactions = \IPS\Content\Reaction::enabledReactions();
|
||||
$finalReactions = [];
|
||||
foreach( $reactions as $memberId => $array )
|
||||
{
|
||||
foreach( $array as $reaction )
|
||||
{
|
||||
$finalReactions[ $memberId ][] = [
|
||||
'title' => $enabledReactions[ $reaction ]->_title,
|
||||
'id' => $reaction,
|
||||
'value' => $enabledReactions[ $reaction ]->value,
|
||||
'icon' => (string) $enabledReactions[ $reaction ]->_icon->url
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$return['reactions'] = $finalReactions;
|
||||
}
|
||||
else
|
||||
{
|
||||
$return['reactions'] = [];
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1618,9 +1807,10 @@ abstract class _Comment extends \IPS\Content
|
||||
{
|
||||
$filters = parent::webhookFilters();
|
||||
$item = $this->item();
|
||||
|
||||
|
||||
/* This is kept for legacy compatibility, but starting with 4.6.13 the Content and Item class handle this inside their own webhookFilter methods */
|
||||
$filters['hidden'] = ( ( (bool) $this->hidden() ) or ( (bool) $item->hidden() ) );
|
||||
|
||||
|
||||
if ( \in_array( 'IPS\Content\Lockable', class_implements( $item ) ) )
|
||||
{
|
||||
$filters['locked'] = $item->locked();
|
||||
|
||||
Reference in new issue
Block a user