Version 4.5.0

This commit is contained in:
Neo committed 2025-12-19 05:51:58 -08:00
1 parent 1a0c7fd3c2
commit f79dcf067a
3791 files changed
+248032 -76372

No files matched your search

+201 -211
View File
@@ -11,7 +11,7 @@
namespace IPS\Content;
/* 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;
@@ -41,7 +41,12 @@ abstract class _Comment extends \IPS\Content
* @brief [Content\Item] Sharelink HTML
*/
protected $sharelinks = array();
/**
* @brief [Content\Comment] EditLine Template
*/
public static $editLineTemplate = array( array( 'global', 'core', 'front' ), 'commentEditLine' );
/**
* Create comment
*
@@ -108,7 +113,12 @@ abstract class _Comment extends \IPS\Content
}
elseif ( $hiddenStatus === NULL )
{
if ( in_array( 'IPS\Content\Review', class_parents( get_called_class() ) ) )
$permissionCheckFunction = \in_array( 'IPS\Content\Review', class_parents( \get_called_class() ) ) ? 'canReview' : 'canComment';
if ( !$member->member_id and !$item->$permissionCheckFunction( $member, FALSE ) )
{
$val = -3;
}
elseif ( \in_array( 'IPS\Content\Review', class_parents( \get_called_class() ) ) )
{
$val = $item->moderateNewReviews( $member ) ? 0 : 1;
}
@@ -145,7 +155,12 @@ abstract class _Comment extends \IPS\Content
}
elseif ( $hiddenStatus === NULL )
{
if ( in_array( 'IPS\Content\Review', class_parents( get_called_class() ) ) )
$permissionCheckFunction = \in_array( 'IPS\Content\Review', class_parents( \get_called_class() ) ) ? 'canReview' : 'canComment';
if ( !$member->member_id and !$item->$permissionCheckFunction( $member, FALSE ) )
{
$val = -3;
}
elseif ( \in_array( 'IPS\Content\Review', class_parents( \get_called_class() ) ) )
{
$val = $item->moderateNewReviews( $member ) ? 1 : 0;
}
@@ -161,7 +176,7 @@ abstract class _Comment extends \IPS\Content
break;
}
foreach ( is_array( static::$databaseColumnMap[ $k ] ) ? static::$databaseColumnMap[ $k ] : array( static::$databaseColumnMap[ $k ] ) as $column )
foreach ( \is_array( static::$databaseColumnMap[ $k ] ) ? static::$databaseColumnMap[ $k ] : array( static::$databaseColumnMap[ $k ] ) as $column )
{
$obj->$column = $val;
}
@@ -186,7 +201,7 @@ abstract class _Comment extends \IPS\Content
/* Update member's last post and daily post limits */
if( $obj->author()->member_id )
if( $obj->author()->member_id AND $obj::incrementPostCount() )
{
$obj->author()->member_last_post = time();
@@ -208,7 +223,7 @@ abstract class _Comment extends \IPS\Content
}
/* Send notifications */
if ( !in_array( 'IPS\Content\Review', class_parents( get_called_class() ) ) )
if ( !\in_array( 'IPS\Content\Review', class_parents( \get_called_class() ) ) )
{
if ( !$obj->hidden() and ( !$first or !$item::$firstCommentRequired ) )
{
@@ -220,6 +235,12 @@ abstract class _Comment extends \IPS\Content
}
}
/* Send webhook */
if ( \in_array( $obj->hidden(), array( -1, 0, 1 ) ) ) // i.e. not post before register or pending deletion
{
\IPS\Api\Webhook::fire( str_replace( '\\', '', \substr( \get_called_class(), 3 ) ) . '_create', $obj, $obj->webhookFilters() );
}
/* Update item */
$obj->postCreate();
@@ -232,105 +253,6 @@ abstract class _Comment extends \IPS\Content
/* Return */
return $obj;
}
/**
* Check comment against profanity filters
*
* @note We do not save here, as saving is done in user-land code after
* @param bool $first Is this the first comment?
* @param bool $edit Are we editing or merging (true) or is this a new comment (false)?
* @param string|NULL $content The content to check - useful for if the content needs to be checked first, before it gets saved to the database.
* @return bool Whether to send unapproved notifications
*/
public function checkProfanityFilters( $first=FALSE, $edit=TRUE, $content=NULL )
{
/* Set our content */
$content = $content ?: $this->content();
/* We need our item */
$item = $this->item();
/* And the author */
$member = $this->author();
/* Pass this through our profanity filters to see if it needs to be mod queued */
$sendNotifications = FALSE;
/* Do we need to recount item comments and container comments? */
$recount = FALSE;
try
{
$hiddenByFilter = FALSE;
if ( !$this->hidden() AND ( ! $item::$firstCommentRequired or ( $item::$firstCommentRequired and !$first ) ) AND !$member->group['g_bypass_badwords'] )
{
$hiddenByFilter = \IPS\core\Profanity::hiddenByFilters( $content );
}
/* If the comment is hidden (probably requires moderator approval) and this is the first post in the item that requires a comment (i.e. a post in a topic), then we need to set the item as requiring approval instead. */
elseif ( $item instanceof \IPS\Content\Hideable AND !$member->group['g_bypass_badwords'] AND ( $item::$firstCommentRequired and $first ) )
{
$itemHiddenByFilter = \IPS\core\Profanity::hiddenByFilters( $content );
if ( isset( $item::$databaseColumnMap['approved'] ) and $itemHiddenByFilter )
{
/* 'approved' is easy, clear and concise */
$column = $item::$databaseColumnMap['approved'];
$item->$column = 0;
$item->save();
$recount = TRUE;
}
elseif ( isset( $item::$databaseColumnMap['hidden'] ) and $itemHiddenByFilter )
{
/* 'hidden' is backwards */
$column = $item::$databaseColumnMap['hidden'];
$item->$column = 1;
$item->save();
$recount = TRUE;
}
if( $edit === TRUE )
{
$sendNotifications = TRUE;
}
}
}
catch( \BadMethodCallException $e ) { }
if ( $hiddenByFilter === TRUE )
{
$recount = TRUE;
if ( isset( static::$databaseColumnMap['approved'] ) )
{
/* 'approved' is easy, clear and concise */
$column = static::$databaseColumnMap['approved'];
$this->$column = 0;
}
else if ( isset( static::$databaseColumnMap['hidden'] ) )
{
/* 'hidden' is backwards */
$column = static::$databaseColumnMap['hidden'];
$this->$column = 1;
}
$sendNotifications = TRUE;
}
if ( $recount === TRUE )
{
$item->resyncCommentCounts();
$item->resyncLastComment();
$item->save();
if ( $container = $item->containerWrapper() )
{
$container->resetCommentCounts();
$container->save();
}
}
return $sendNotifications;
}
/**
* Join profile fields when loading comments?
@@ -381,7 +303,7 @@ abstract class _Comment extends \IPS\Content
if( isset( static::$databaseColumnMap['date'] ) )
{
if( is_array( static::$databaseColumnMap['date'] ) )
if( \is_array( static::$databaseColumnMap['date'] ) )
{
$postDateColumn = static::$databaseColumnMap['date'][0];
}
@@ -396,7 +318,7 @@ abstract class _Comment extends \IPS\Content
if ( isset( $item::$databaseColumnMap['last_comment'] ) )
{
$lastCommentField = $item::$databaseColumnMap['last_comment'];
if ( is_array( $lastCommentField ) )
if ( \is_array( $lastCommentField ) )
{
foreach ( $lastCommentField as $column )
{
@@ -441,8 +363,18 @@ abstract class _Comment extends \IPS\Content
/* Are we tracking keywords? */
$this->checkKeywords( $this->content() );
if ( \IPS\IPS::classUsesTrait( $item, 'IPS\Content\Statistics' ) )
{
$item->clearCachedStatistics();
}
}
/**
* @brief Value to set for the 'tab' parameter when redirecting to the comment (via _find())
*/
public static $tabParameter = array( 'tab' => 'comments' );
/**
* Get URL
*
@@ -545,7 +477,7 @@ abstract class _Comment extends \IPS\Content
}
/* Can the member edit their own content? */
if ( $member->member_id == $this->author()->member_id and ( $member->group['g_edit_posts'] == '1' or in_array( get_class( $item ), explode( ',', $member->group['g_edit_posts'] ) ) ) and ( !( $item instanceof \IPS\Content\Lockable ) or !$item->locked() ) )
if ( $member->member_id == $this->author()->member_id and ( $member->group['g_edit_posts'] == '1' or \in_array( \get_class( $item ), explode( ',', $member->group['g_edit_posts'] ) ) ) and ( !( $item instanceof \IPS\Content\Lockable ) or !$item->locked() ) )
{
if ( !$member->group['g_edit_cutoff'] )
{
@@ -574,7 +506,7 @@ abstract class _Comment extends \IPS\Content
{
$member = $member ?: \IPS\Member::loggedIn();
return ( !$this->isFirst() and ( static::modPermission( 'hide', $member, $this->item()->containerWrapper() ) or ( $member->member_id and $member->member_id == $this->author()->member_id and ( $member->group['g_hide_own_posts'] == '1' or in_array( get_class( $this->item() ), explode( ',', $member->group['g_hide_own_posts'] ) ) ) ) ) );
return ( !$this->isFirst() and ( static::modPermission( 'hide', $member, $this->item()->containerWrapper() ) or ( $member->member_id and $member->member_id == $this->author()->member_id and ( $member->group['g_hide_own_posts'] == '1' or \in_array( \get_class( $this->item() ), explode( ',', $member->group['g_hide_own_posts'] ) ) ) ) ) );
}
/**
@@ -607,7 +539,7 @@ abstract class _Comment extends \IPS\Content
{
$member = $member ?: \IPS\Member::loggedIn();
return ( !$this->isFirst() and ( static::modPermission( 'delete', $member, $this->item()->containerWrapper() ) or ( $member->member_id and $member->member_id == $this->author()->member_id and ( $member->group['g_delete_own_posts'] == '1' or in_array( get_class( $this->item() ), explode( ',', $member->group['g_delete_own_posts'] ) ) ) ) ) );
return ( !$this->isFirst() and ( static::modPermission( 'delete', $member, $this->item()->containerWrapper() ) or ( $member->member_id and $member->member_id == $this->author()->member_id and ( $member->group['g_delete_own_posts'] == '1' or \in_array( \get_class( $this->item() ), explode( ',', $member->group['g_delete_own_posts'] ) ) ) ) ) );
}
/**
@@ -716,44 +648,18 @@ abstract class _Comment extends \IPS\Content
}
/* Send notifications */
if ( $sendNotifications AND !in_array( 'IPS\Content\Review', class_parents( get_called_class() ) ) )
if ( $sendNotifications AND !\in_array( 'IPS\Content\Review', class_parents( \get_called_class() ) ) )
{
if( $this->hidden() === 1 )
{
$this->sendUnapprovedNotification();
}
}
}
/**
* Get edit line
*
* @return string|NULL
*/
public function editLine()
{
if ( $this instanceof \IPS\Content\EditHistory and $this->mapped('edit_time') and ( $this->mapped('edit_show') or \IPS\Member::loggedIn()->modPermission('can_view_editlog') ) and \IPS\Settings::i()->edit_log )
if ( \IPS\IPS::classUsesTrait( $this->item(), 'IPS\Content\Statistics' ) )
{
return \IPS\Theme::i()->getTemplate( 'global', 'core' )->commentEditLine( $this, ( isset( static::$databaseColumnMap['edit_reason'] ) and $this->mapped('edit_reason') ) );
$this->item()->clearCachedStatistics();
}
return NULL;
}
/**
* Get edit history
*
* @param bool $staff Set true for moderators who have permission to view the full log which will show edits not made by the author and private edits
* @return \IPS\Db\Select
*/
public function editHistory( $staff=FALSE )
{
$idColumn = static::$databaseColumnId;
$where = array( array( 'class=? AND comment_id=?', get_called_class(), $this->$idColumn ) );
if ( !$staff )
{
$where[] = array( 'member=? AND public=1', $this->author()->member_id );
}
return \IPS\Db::i()->select( '*', 'core_edit_history', $where, 'time DESC' );
}
/**
@@ -764,7 +670,8 @@ abstract class _Comment extends \IPS\Content
public function html()
{
$template = static::$commentTemplate[1];
return call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), static::$commentTemplate[0] )->$template( $this->item(), $this );
return \IPS\Theme::i()->getTemplate( static::$commentTemplate[0][0], static::$commentTemplate[0][1], ( isset( static::$commentTemplate[0][2] ) ) ? static::$commentTemplate[0][2] : NULL )->$template( $this->item(), $this );
}
/**
@@ -777,41 +684,30 @@ abstract class _Comment extends \IPS\Content
*/
public function notificationRecipients( $limit=array( 0, 25 ), $extra=NULL, $countOnly=FALSE )
{
$memberFollowers = $this->author()->followers( 3, array( 'immediate' ), $this->mapped('date'), NULL, NULL, NULL );
/* Do we only want the count? */
if( $countOnly )
{
$count = 0;
$count += $this->author()->followersCount( 3, array( 'immediate' ), $this->mapped('date') );
$count += $this->item()->followersCount( 3, array( 'immediate' ), $this->mapped('date') );
return $count;
}
$memberFollowers = $this->author()->followers( 3, array( 'immediate' ), $this->mapped('date'), NULL );
if( count( $memberFollowers ) )
if( $memberFollowers !== NULL )
{
$unions = array(
$this->item()->followers( static::FOLLOW_PUBLIC + static::FOLLOW_ANONYMOUS, array( 'immediate' ), $this->mapped('date'), NULL, NULL, 0 ),
$this->item()->followers( 3, array( 'immediate' ), $this->mapped('date'), NULL ),
$memberFollowers
);
if ( $countOnly )
{
$return = 0;
foreach ( $unions as $query )
{
$return += $query->count();
}
return $return;
}
else
{
return \IPS\Db::i()->union( $unions, 'follow_added', $limit, NULL, FALSE, \IPS\Db::SELECT_SQL_CALC_FOUND_ROWS );
}
return \IPS\Db::i()->union( $unions, 'follow_added', $limit );
}
else
{
$query = $this->item()->followers( static::FOLLOW_PUBLIC + static::FOLLOW_ANONYMOUS, array( 'immediate' ), $this->mapped('date'), $limit, 'follow_added', \IPS\Db::SELECT_SQL_CALC_FOUND_ROWS );
if ( $countOnly )
{
return $query->count();
}
else
{
return $query;
}
return $this->item()->followers( static::FOLLOW_PUBLIC + static::FOLLOW_ANONYMOUS, array( 'immediate' ), $this->mapped('date'), $limit, 'follow_added' );
}
}
@@ -838,7 +734,7 @@ abstract class _Comment extends \IPS\Content
/* Remove any notifications */
$idColumn = static::$databaseColumnId;
\IPS\Db::i()->delete( 'core_notifications', array( 'item_sub_class=? AND item_sub_id=?', (string) get_called_class(), (int) $this->$idColumn ) );
\IPS\Db::i()->delete( 'core_notifications', array( 'item_sub_class=? AND item_sub_id=?', (string) \get_called_class(), (int) $this->$idColumn ) );
$item->resyncCommentCounts();
$item->resyncLastComment();
@@ -854,6 +750,11 @@ abstract class _Comment extends \IPS\Content
$item->container()->save();
}
} catch ( \BadMethodCallException $e ) {}
if ( \IPS\IPS::classUsesTrait( $item, 'IPS\Content\Statistics' ) )
{
$item->clearCachedStatistics();
}
}
/**
@@ -899,6 +800,11 @@ abstract class _Comment extends \IPS\Content
$item->container()->save();
}
} catch ( \BadMethodCallException $e ) {}
if ( \IPS\IPS::classUsesTrait( $item, 'IPS\Content\Statistics' ) )
{
$item->clearCachedStatistics();
}
}
/**
@@ -922,24 +828,35 @@ abstract class _Comment extends \IPS\Content
\IPS\Db::i()->update( 'core_attachments_map', array( 'id1' => $item->$idColumn ), array( "location_key=? AND id1=? AND id2=?", $oldItem::$application . '_' . mb_ucfirst( $oldItem::$module ), $oldItem->$idColumn, $this->$commentIdColumn ) );
/* Update notifications */
\IPS\Db::i()->update( 'core_notifications', array( 'item_id' => $item->$idColumn ), array( 'item_class=? and item_id=? and item_sub_class=? and item_sub_id=?', (string) get_class( $item ), $oldItem->$idColumn, (string) get_called_class(), $this->$commentIdColumn ) );
\IPS\Db::i()->update( 'core_notifications', array( 'item_id' => $item->$idColumn ), array( 'item_class=? and item_id=? and item_sub_class=? and item_sub_id=?', (string) \get_class( $item ), $oldItem->$idColumn, (string) \get_called_class(), $this->$commentIdColumn ) );
/* Update reputation */
if ( \IPS\IPS::classUsesTrait( $this, 'IPS\Content\Reactable' ) )
{
\IPS\Db::i()->update( 'core_reputation_index', array( 'item_id' => $item->$idColumn ), array( 'class_type_id_hash=?', md5( get_class( $this ) . ':' . $oldItem->$idColumn ) ) );
\IPS\Db::i()->update( 'core_reputation_index', array( 'item_id' => $item->$idColumn ), array( 'class_type_id_hash=?', md5( \get_class( $this ) . ':' . $oldItem->$idColumn ) ) );
}
/* Update solved */
if ( \IPS\IPS::classUsesTrait( $this, 'IPS\Content\Solvable' ) )
{
\IPS\Db::i()->update( 'core_solved_index', array( 'item_id' => $item->$idColumn ), array( 'comment_class=? and comment_id=?', \get_class( $this ), $oldItem->$idColumn ) );
}
if( $skip === FALSE )
{
$oldItem->rebuildFirstAndLastCommentData();
$item->rebuildFirstAndLastCommentData();
}
/* Add to search index */
if ( $this instanceof \IPS\Content\Searchable )
{
\IPS\Content\Search\Index::i()->index( $this );
/* Add to search index */
if ( $this instanceof \IPS\Content\Searchable )
{
\IPS\Content\Search\Index::i()->index( $this );
}
if ( \IPS\IPS::classUsesTrait( $item, 'IPS\Content\Statistics' ) )
{
$item->clearCachedStatistics();
}
}
}
@@ -1005,10 +922,10 @@ abstract class _Comment extends \IPS\Content
/* Reduce the number of comment/reviews count on the item but only if the item is unapproved or visible
* - hidden as opposed to unapproved items do not get included in either of the unapproved_comments/num_comments columns */
if( $this->hidden() !== -1 AND $this->hidden() !== -2 )
if( $this->hidden() !== -1 AND $this->hidden() !== -2 AND $this->hidden() !== -3 )
{
$columnName = ( $this->hidden() === 1 ) ? 'unapproved_comments' : 'num_comments';
if ( in_array( 'IPS\Content\Review', class_parents( get_called_class() ) ) )
if ( \in_array( 'IPS\Content\Review', class_parents( \get_called_class() ) ) )
{
$columnName = ( $this->hidden() === 1 ) ? 'unapproved_reviews' : 'num_reviews';
}
@@ -1023,9 +940,9 @@ abstract class _Comment extends \IPS\Content
}
}
}
else
else if ( $this->hidden() === -1 )
{
if ( in_array( 'IPS\Content\Review', class_parents( get_called_class() ) ) )
if ( \in_array( 'IPS\Content\Review', class_parents( \get_called_class() ) ) )
{
if( isset( $itemClass::$databaseColumnMap['hidden_reviews'] ) AND $item !== NULL )
{
@@ -1052,16 +969,32 @@ abstract class _Comment extends \IPS\Content
}
}
}
if ( \IPS\IPS::classUsesTrait( $this->item(), 'IPS\Content\Solvable' ) and isset( $itemClass::$databaseColumnMap['solved_comment_id'] ) )
{
/* Reset item */
if ( $item->mapped('solved_comment_id') and $item->mapped('solved_comment_id') == $this->$idColumn )
{
\IPS\Db::i()->update( $itemClass::$databaseTable, array( $itemClass::$databaseColumnMap['solved_comment_id'] => 0 ), array( $itemIdColumn . '=?', $itemId ) );
\IPS\Db::i()->delete( 'core_solved_index', array( 'app=? and comment_class=? and item_id=? and comment_id=?', static::$application, \get_called_class(), $itemId, $this->$idColumn ) );
}
}
if ( \IPS\IPS::classUsesTrait( $this->item(), 'IPS\Content\Statistics' ) )
{
$item->clearCachedStatistics();
}
/* Delete any notifications telling people about this */
$memberIds = array();
foreach( \IPS\Db::i()->select( 'member', 'core_notifications', array( 'item_sub_class=? AND item_sub_id=?', (string) get_called_class(), (int) $this->$idColumn ) ) as $member )
foreach( \IPS\Db::i()->select( '`member`', 'core_notifications', array( 'item_sub_class=? AND item_sub_id=?', (string) \get_called_class(), (int) $this->$idColumn ) ) as $member )
{
$memberIds[ $member ] = $member;
}
\IPS\Db::i()->delete( 'core_notifications', array( 'item_sub_class=? AND item_sub_id=?', (string) get_called_class(), (int) $this->$idColumn ) );
\IPS\Db::i()->delete( 'core_notifications', array( 'item_sub_class=? AND item_sub_id=?', (string) \get_called_class(), (int) $this->$idColumn ) );
foreach( $memberIds as $member )
{
@@ -1074,7 +1007,7 @@ abstract class _Comment extends \IPS\Content
/* Update last comment/review data for container and item */
try
{
if ( $item !== NULL AND in_array( 'IPS\Content\Review', class_parents( get_called_class() ) ) )
if ( $item !== NULL AND \in_array( 'IPS\Content\Review', class_parents( \get_called_class() ) ) )
{
if ( $item->container()->_reviews !== NULL )
{
@@ -1116,9 +1049,10 @@ abstract class _Comment extends \IPS\Content
* Change Author
*
* @param \IPS\Member $newAuthor The new author
* @param bool $log If TRUE, action will be logged to moderator log
* @return void
*/
public function changeAuthor( \IPS\Member $newAuthor )
public function changeAuthor( \IPS\Member $newAuthor, $log=TRUE )
{
$oldAuthor = $this->author();
@@ -1130,10 +1064,10 @@ abstract class _Comment extends \IPS\Content
}
/* Update the row */
parent::changeAuthor( $newAuthor );
parent::changeAuthor( $newAuthor, $log );
/* Adjust post counts */
if ( static::incrementPostCount( $this->item()->containerWrapper() ) )
if ( static::incrementPostCount( $this->item()->containerWrapper() ) AND ( $oldAuthor->member_id OR ( $this->hidden() === 0 AND $this->item()->hidden === 0 ) ) )
{
if( $oldAuthor->member_id )
{
@@ -1217,7 +1151,7 @@ abstract class _Comment extends \IPS\Content
$containerWhere = array();
/* Queries are always more efficient when the WHERE clause is added to the ON */
if ( is_array( $where ) )
if ( \is_array( $where ) )
{
foreach( $where as $key => $value )
{
@@ -1252,7 +1186,7 @@ abstract class _Comment extends \IPS\Content
}
}
if ( in_array( 'IPS\Content\Hideable', class_implements( get_called_class() ) ) and $includeHiddenComments === \IPS\Content\Hideable::FILTER_ONLY_HIDDEN )
if ( \in_array( 'IPS\Content\Hideable', class_implements( \get_called_class() ) ) and $includeHiddenComments === \IPS\Content\Hideable::FILTER_ONLY_HIDDEN )
{
/* If we can't view hidden stuff, just return an empty array now */
if( !static::modPermission( 'view_hidden', $member ) )
@@ -1269,7 +1203,7 @@ abstract class _Comment extends \IPS\Content
$where[] = array( static::$databasePrefix . static::$databaseColumnMap['hidden'] . '=?', 1 );
}
}
elseif ( in_array( 'IPS\Content\Hideable', class_implements( get_called_class() ) ) and ( $includeHiddenComments === \IPS\Content\Hideable::FILTER_OWN_HIDDEN OR $includeHiddenComments === \IPS\Content\Hideable::FILTER_PUBLIC_ONLY ) )
elseif ( \in_array( 'IPS\Content\Hideable', class_implements( \get_called_class() ) ) and ( $includeHiddenComments === \IPS\Content\Hideable::FILTER_OWN_HIDDEN OR $includeHiddenComments === \IPS\Content\Hideable::FILTER_PUBLIC_ONLY ) )
{
if ( isset( static::$databaseColumnMap['approved'] ) )
{
@@ -1282,7 +1216,7 @@ abstract class _Comment extends \IPS\Content
}
/* Exclude hidden items. We don't check FILTER_ONLY_HIDDEN because we should return hidden comments in both approved and unapproved topics. */
if ( in_array( 'IPS\Content\Hideable', class_implements( $itemClass ) ) and ( $includeHiddenComments === \IPS\Content\Hideable::FILTER_OWN_HIDDEN OR $includeHiddenComments === \IPS\Content\Hideable::FILTER_PUBLIC_ONLY ) )
if ( \in_array( 'IPS\Content\Hideable', class_implements( $itemClass ) ) and ( $includeHiddenComments === \IPS\Content\Hideable::FILTER_OWN_HIDDEN OR $includeHiddenComments === \IPS\Content\Hideable::FILTER_PUBLIC_ONLY ) )
{
$member = $member ?: \IPS\Member::loggedIn();
$authorCol = $itemClass::$databaseTable . '.' . $itemClass::$databasePrefix . $itemClass::$databaseColumnMap['author'];
@@ -1331,18 +1265,34 @@ abstract class _Comment extends \IPS\Content
}
}
/* No matter if we can or cannot view hidden items, we do not want these to show as they are queued for deletion */
/* No matter if we can or cannot view hidden items, we do not want these to show: -2 is queued for deletion and -3 is posted before register */
if ( isset( static::$databaseColumnMap['hidden'] ) )
{
$col = static::$databaseTable . '.' . static::$databasePrefix . static::$databaseColumnMap['hidden'];
$where[] = array( "{$col}!=-2" );
$where[] = array( "{$col}!=-2 AND {$col} !=-3" );
}
else if ( isset( static::$databaseColumnMap['approved'] ) )
{
$col = static::$databaseTable . '.' . static::$databasePrefix . static::$databaseColumnMap['approved'];
$where[] = array( "{$col}!=-2" );
$where[] = array( "{$col}!=-2 AND {$col} !=-3" );
}
/* We also need to check the item for soft delete and post before register */
if( \in_array( 'IPS\Content\Hideable', class_implements( $itemClass ) ) )
{
/* No matter if we can or cannot view hidden items, we do not want these to show: -2 is queued for deletion and -3 is posted before register */
if ( isset( $itemClass::$databaseColumnMap['hidden'] ) )
{
$col = $itemClass::$databaseTable . '.' . $itemClass::$databasePrefix . $itemClass::$databaseColumnMap['hidden'];
$itemWhere[] = array( "{$col}!=-2 AND {$col} !=-3" );
}
else if ( isset( $itemClass::$databaseColumnMap['approved'] ) )
{
$col = $itemClass::$databaseTable . '.' . $itemClass::$databasePrefix . $itemClass::$databaseColumnMap['approved'];
$itemWhere[] = array( "{$col}!=-2 AND {$col} !=-3" );
}
}
if ( $joinContainer AND isset( $itemClass::$containerNodeClass ) )
{
$containerClass = $itemClass::$containerNodeClass;
@@ -1367,7 +1317,7 @@ abstract class _Comment extends \IPS\Content
/* Build the select clause */
if( $countOnly )
{
if ( in_array( 'IPS\Content\Permissions', class_implements( $itemClass ) ) AND $permissionKey !== NULL )
if ( \in_array( 'IPS\Content\Permissions', class_implements( $itemClass ) ) AND $permissionKey !== NULL )
{
$member = $member ?: \IPS\Member::loggedIn();
@@ -1383,7 +1333,7 @@ abstract class _Comment extends \IPS\Content
->join( $itemClass::$databaseTable, array_merge( array( array( static::$databaseTable . "." . static::$databasePrefix . static::$databaseColumnMap['item'] . "=" . $itemClass::$databaseTable . "." . $itemClass::$databasePrefix . $itemClass::$databaseColumnId ) ), $itemWhere ), 'STRAIGHT_JOIN' );
}
if ( $joins !== NULL AND count( $joins ) )
if ( $joins !== NULL AND \count( $joins ) )
{
foreach( $joins as $join )
{
@@ -1394,7 +1344,7 @@ abstract class _Comment extends \IPS\Content
}
$selectClause = static::$databaseTable . '.*';
if ( $joins !== NULL AND count( $joins ) )
if ( $joins !== NULL AND \count( $joins ) )
{
foreach( $joins as $join )
{
@@ -1405,7 +1355,7 @@ abstract class _Comment extends \IPS\Content
}
}
if ( in_array( 'IPS\Content\Permissions', class_implements( $itemClass ) ) AND $permissionKey !== NULL )
if ( \in_array( 'IPS\Content\Permissions', class_implements( $itemClass ) ) AND $permissionKey !== NULL )
{
$containerClass = $itemClass::$containerNodeClass;
@@ -1418,7 +1368,7 @@ abstract class _Comment extends \IPS\Content
static::$permissionSelect[ $lookupKey ] = array();
$permQuery = \IPS\Db::i()->select( 'perm_type_id', 'core_permission_index', array( "core_permission_index.app='" . $containerClass::$permApp . "' AND core_permission_index.perm_type='" . $containerClass::$permType . "' AND (" . \IPS\Db::i()->findInSet( 'perm_' . $containerClass::$permissionMap[ $permissionKey ], $member->permissionArray() ) . ' OR ' . 'perm_' . $containerClass::$permissionMap[ $permissionKey ] . "='*' )" ) );
if ( count( $containerWhere ) )
if ( \count( $containerWhere ) )
{
$permQuery->join( $containerClass::$databaseTable, array_merge( $containerWhere, array( 'core_permission_index.perm_type_id=' . $containerClass::$databaseTable . '.' . $containerClass::$databasePrefix . $containerClass::$databaseColumnId ) ), 'STRAIGHT_JOIN' );
}
@@ -1431,7 +1381,7 @@ abstract class _Comment extends \IPS\Content
$categories = static::$permissionSelect[ $lookupKey ];
if( count( $categories ) )
if( \count( $categories ) )
{
$where[] = array( $itemClass::$databaseTable . "." . $itemClass::$databasePrefix . $itemClass::$databaseColumnMap['container'] . ' IN(' . implode( ',', $categories ) . ')' );
}
@@ -1451,7 +1401,7 @@ abstract class _Comment extends \IPS\Content
->join( $itemClass::$databaseTable, array_merge( array( array( static::$databaseTable . "." . static::$databasePrefix . static::$databaseColumnMap['item'] . "=" . $itemClass::$databaseTable . "." . $itemClass::$databasePrefix . $itemClass::$databaseColumnId ) ), $itemWhere ), 'STRAIGHT_JOIN' );
}
if ( $joins !== NULL AND count( $joins ) )
if ( $joins !== NULL AND \count( $joins ) )
{
foreach( $joins as $join )
{
@@ -1460,7 +1410,7 @@ abstract class _Comment extends \IPS\Content
}
/* Return */
return new \IPS\Patterns\ActiveRecordIterator( $select, get_called_class() );
return new \IPS\Patterns\ActiveRecordIterator( $select, \get_called_class(), $itemClass );
}
/**
@@ -1497,12 +1447,12 @@ abstract class _Comment extends \IPS\Content
/**
* Returns the content images
*
* @param int|null $limit Number of attachments to fetch, or NULL for all
*
* @param int|null $limit Number of attachments to fetch, or NULL for all
* @param bool $ignorePermissions If set to TRUE, permission to view the images will not be checked
* @return array|NULL
* @throws \BadMethodCallException
*/
public function contentImages( $limit = NULL )
public function contentImages( $limit = NULL, $ignorePermissions = FALSE )
{
$idColumn = static::$databaseColumnId;
$item = $this->item();
@@ -1514,8 +1464,14 @@ abstract class _Comment extends \IPS\Content
{
$attachments[] = array( 'core_Attachment' => $row['attach_location'] );
}
/* IS there a club with a cover photo? */
if ( \IPS\IPS::classUsesTrait( $item->container(), 'IPS\Content\ClubContainer' ) and $club = $item->container()->club() )
{
$attachments[] = array( 'core_Clubs' => $club->cover_photo );
}
return count( $attachments ) ? $attachments : NULL;
return \count( $attachments ) ? $attachments : NULL;
}
/**
@@ -1530,7 +1486,7 @@ abstract class _Comment extends \IPS\Content
*/
public function canShare()
{
return ( $this->canView( \IPS\Member::load( 0 ) ) and in_array( 'IPS\Content\Shareable', class_implements( get_called_class() ) ) );
return ( $this->canView( \IPS\Member::load( 0 ) ) and \in_array( 'IPS\Content\Shareable', class_implements( \get_called_class() ) ) );
}
/**
@@ -1540,7 +1496,7 @@ abstract class _Comment extends \IPS\Content
*/
public function sharelinks()
{
if( !count( $this->sharelinks ) )
if( !\count( $this->sharelinks ) )
{
if ( $this instanceof Shareable and $this->canShare() )
{
@@ -1575,6 +1531,8 @@ abstract class _Comment extends \IPS\Content
return \IPS\Application::load('core')->extensions( 'core', 'MetaData' )['FeaturedComments']->isFeatured( $this );
}
/* !API */
/**
* Get output for API
*
@@ -1597,12 +1555,44 @@ abstract class _Comment extends \IPS\Content
'item_id' => $this->$itemColumn,
'author' => $this->author()->apiOutput( $authorizedMember ),
'date' => \IPS\DateTime::ts( $this->mapped('date') )->rfc3339(),
'content' => $this->content(),
'content' => \IPS\Text\Parser::removeLazyLoad( $this->content() ),
'hidden' => (bool) $this->hidden(),
'url' => (string) $this->url()
);
}
/**
* Webhook filters
*
* @return array
*/
public function webhookFilters()
{
$filters = parent::webhookFilters();
$item = $this->item();
$filters['hidden'] = ( ( (bool) $this->hidden() ) or ( (bool) $item->hidden() ) );
if ( \in_array( 'IPS\Content\Lockable', class_implements( $item ) ) )
{
$filters['locked'] = $item->locked();
}
if ( \in_array( 'IPS\Content\Pinnable', class_implements( $item ) ) )
{
$filters['pinned'] = (bool) $item->mapped('pinned');
}
if ( \in_array( 'IPS\Content\Featurable', class_implements( $item ) ) )
{
$filters['featured'] = (bool) $item->mapped('featured');
}
if ( \in_array( 'IPS\Content\Polls', class_implements( $item ) ) )
{
$filters['hasPoll'] = (bool) $item->mapped('poll');
}
return $filters;
}
/* !Embeddable */
/**