Version 4.7.13

This commit is contained in:
Neo committed 2025-12-19 16:14:56 -08:00
1 parent fd22d99e69
commit 7124a02564
954 files changed
+29277 -59308

No files matched your search

+110 -52
View File
@@ -41,6 +41,13 @@ abstract class _Item extends \IPS\Content
* @brief [Content\Item] Follower count
*/
public $followerCount = NULL;
/**
* Should IndexNow be skipped for this item? Can be used to prevent that Private Messages,
* Reports and other content which is never going to be visible to guests is triggering the requests.
* @var bool
*/
public static bool $skipIndexNow = FALSE;
/**
* @brief [Content\Item] If $firstCommentRequired is TRUE, when comments are split from an item or items are merged, the author
@@ -521,7 +528,7 @@ abstract class _Item extends \IPS\Content
}
/* Dish out points */
if ( !$obj->isFutureDate() and !$obj->hidden() )
if ( !$obj->isFutureDate() and !$obj->hidden() and !$obj instanceof \IPS\core\Messenger\Conversation )
{
$member->achievementAction( 'core', 'NewContentItem', $obj );
}
@@ -619,6 +626,12 @@ abstract class _Item extends \IPS\Content
{
$column = static::$databaseColumnMap['future_date'];
$this->$column = $time->getTimestamp();
if( isset( static::$databaseColumnMap['is_future_entry'] ) )
{
$column = static::$databaseColumnMap['is_future_entry'];
$this->$column = $time->getTimestamp() > time();
}
}
}
@@ -718,7 +731,12 @@ abstract class _Item extends \IPS\Content
/* Title */
if ( isset( static::$databaseColumnMap['title'] ) )
{
$return['title'] = new \IPS\Helpers\Form\Text( static::$formLangPrefix . 'title', isset( \IPS\Request::i()->title ) ? \IPS\Request::i()->title : $item?->mapped( 'title' ), TRUE, array( 'maxLength' => \IPS\Settings::i()->max_title_length ?: 255, 'bypassProfanity' => \IPS\Helpers\Form\Text::BYPASS_PROFANITY_SWAP ) );
$return['title'] = new \IPS\Helpers\Form\Text( static::$formLangPrefix . 'title', isset( \IPS\Request::i()->title ) ? \IPS\Request::i()->title : $item?->mapped( 'title' ), TRUE, array( 'maxLength' => \IPS\Settings::i()->max_title_length ?: 255, 'bypassProfanity' => \IPS\Helpers\Form\Text::BYPASS_PROFANITY_SWAP ), function( $val ) {
if ( !\IPS\Member::loggedIn()->group['g_bypass_badwords'] AND $word = \IPS\core\Profanity::checkProfanityBlocks( $val ) )
{
throw new \DomainException( \IPS\Member::loggedIn()->language()->addToStack( "form_err_word_blocked", FALSE, array( "sprintf" => array( $word ) ) ) );
}
} );
$return['title']->rowClasses[] = 'ipsFieldRow_primary';
$return['title']->rowClasses[] = 'ipsFieldRow_fullWidth';
}
@@ -1015,6 +1033,10 @@ abstract class _Item extends \IPS\Content
{
$options['autocomplete']['filterProfanity'] = TRUE;
}
if ( \IPS\Settings::i()->tags_alphabetical )
{
$options['autocomplete']['alphabetical'] = TRUE;
}
$options['autocomplete']['prefix'] = static::canPrefix( NULL, $container );
$options['autocomplete']['disallowedCharacters'] = array( '#' ); // @todo Pending \IPS\Http\Url rework, hashes cannot be used in URLs
@@ -1149,7 +1171,7 @@ abstract class _Item extends \IPS\Content
}
/* Send this URL to IndexNow if the guest can view it */
if ( $this->canView( new \IPS\Member ) )
if ( $this->canView( new \IPS\Member ) AND !static::$skipIndexNow )
{
\IPS\core\IndexNow::addUrlToQueue( $this->url() );
}
@@ -1330,6 +1352,14 @@ abstract class _Item extends \IPS\Content
$this->publish();
}
}
else if ( $container and ! $this->$column )
{
if ( $values[ static::$formLangPrefix . 'date' ] instanceof \IPS\DateTime AND $values[ static::$formLangPrefix . 'date' ]->getTimestamp() > time() )
{
/* Was not future, now is */
$this->unpublish();
}
}
}
/* Post anonymously */
@@ -1903,7 +1933,7 @@ abstract class _Item extends \IPS\Content
}
}
if ( $this instanceof \IPS\Content\Views )
if ( \IPS\IPS::classUsesTrait( $this, 'IPS\Content\ViewUpdates' ) )
{
$return['num_views'] = (int) $this->mapped('views');
}
@@ -2129,6 +2159,9 @@ abstract class _Item extends \IPS\Content
{
$link->markRead();
}
/* Remove from Hive */
\IPS\core\Hive::i()->removeContent( $this );
}
/**
@@ -2275,7 +2308,7 @@ abstract class _Item extends \IPS\Content
}
/* Merge view counts */
if ( $this instanceof \IPS\Content\Views )
if ( \IPS\IPS::classUsesTrait( $this, 'IPS\Content\ViewUpdates' ) )
{
$views += $item->mapped('views');
\IPS\Db::i()->update( 'core_view_updates', array( 'id' => $this->$idColumn ), array( 'classname=? and id=?', (string) \get_class( $item ), $item->$idColumn ) );
@@ -2725,7 +2758,7 @@ abstract class _Item extends \IPS\Content
}
$idColumn = static::$databaseColumnId;
/* Don't do anything for shadow items */
if ( isset( static::$databaseColumnMap['moved_to'] ) )
{
@@ -2740,19 +2773,19 @@ abstract class _Item extends \IPS\Content
}
\IPS\Db::i()->delete( 'core_item_member_map', array( 'map_class=? and map_item_id=?', (string) \get_class( $this ), (int) $this->$idColumn ) );
/* Remove any meta data */
if ( ( $this instanceof \IPS\Content\MetaData ) AND isset( static::$databaseColumnMap['meta_data'] ) )
{
$this->deleteAllMeta();
}
/* Unclaim attachments */
$this->unclaimAttachments();
/* Delete it from the database */
parent::delete();
/* Update count */
try
{
@@ -2772,7 +2805,7 @@ abstract class _Item extends \IPS\Content
}
}
} catch ( \BadMethodCallException $e ) {}
/* Delete comments */
if ( isset( static::$commentClass ) )
{
@@ -2783,7 +2816,7 @@ abstract class _Item extends \IPS\Content
{
$where = $commentClass::deleteWhereSql( $this->$idColumn );
}
/* Remove any deletion logs for comments */
$commentIds = array();
$commentIdColumn = $commentClass::$databasePrefix . $commentClass::$databaseColumnId;
@@ -2791,14 +2824,14 @@ abstract class _Item extends \IPS\Content
{
$commentIds[] = $commentId;
}
$this->deleteCommentOrReviewData( $commentIds, $commentClass );
if ( \is_array( $where ) and \count( $where ) )
{
\IPS\Db::i()->delete( $commentClass::$databaseTable, $where );
}
if( !$this->skipContainerRebuild )
{
try
@@ -2810,7 +2843,7 @@ abstract class _Item extends \IPS\Content
{
$this->container()->_comments = ( $this->container()->_comments - $this->mapped('num_comments') );
}
$this->container()->setLastComment();
}
if ( $this->container()->_unapprovedComments !== NULL )
@@ -2821,7 +2854,7 @@ abstract class _Item extends \IPS\Content
} catch ( \BadMethodCallException $e ) {}
}
}
/* Delete reviews */
if ( isset( static::$reviewClass ) )
{
@@ -2832,7 +2865,7 @@ abstract class _Item extends \IPS\Content
{
$where = $reviewClass::deleteWhereSql( $this->$idColumn );
}
/* Remove any deletion logs for reviews */
$reviewIds = array();
$reviewIdColumn = $reviewClass::$databasePrefix . $reviewClass::$databaseColumnMap['item'];
@@ -2844,7 +2877,7 @@ abstract class _Item extends \IPS\Content
$this->deleteCommentOrReviewData( $reviewIds, $reviewClass );
\IPS\Db::i()->delete( $reviewClass::$databaseTable, $where );
if( !$this->skipContainerRebuild )
{
try
@@ -2856,7 +2889,7 @@ abstract class _Item extends \IPS\Content
{
$this->container()->_reviews = ( $this->container()->_reviews - $this->mapped('num_reviews') );
}
$this->container()->setLastReview();
}
if ( $this->container()->_unapprovedReviews !== NULL )
@@ -2867,7 +2900,7 @@ abstract class _Item extends \IPS\Content
} catch ( \BadMethodCallException $e ) {}
}
}
/* Delete tags */
if ( $this instanceof \IPS\Content\Tags )
{
@@ -2876,7 +2909,7 @@ abstract class _Item extends \IPS\Content
\IPS\Db::i()->delete( 'core_tags_cache', array( 'tag_cache_key=?', $aaiLookup ) );
\IPS\Db::i()->delete( 'core_tags_perms', array( 'tag_perm_aai_lookup=?', $aaiLookup ) );
}
/* Delete follows */
if ( $this instanceof \IPS\Content\Followable )
{
@@ -2884,7 +2917,7 @@ abstract class _Item extends \IPS\Content
\IPS\Db::i()->delete( 'core_follow', array( 'follow_app=? AND follow_area=? AND follow_rel_id=?', static::$application, $followArea, (int) $this->$idColumn ) );
\IPS\Db::i()->delete( 'core_follow_count_cache', array( 'class=? AND id=?', \get_called_class(), (int) $this->$idColumn ) );
}
/* Remove Notifications */
$memberIds = array();
@@ -2894,13 +2927,13 @@ abstract class _Item extends \IPS\Content
}
\IPS\Db::i()->delete( 'core_notifications', array( 'item_class=? AND item_id=?', (string) \get_class( $this ), (int) $this->$idColumn ) );
/* Delete from Our Picks */
\IPS\Db::i()->delete( 'core_social_promote', array( 'promote_class=? AND promote_class_id=?', (string) \get_class( $this ), (int) $this->$idColumn ) );
/* Delete from redirect links */
\IPS\Db::i()->delete( 'core_item_redirect', array( 'redirect_class=? AND redirect_new_item_id=?', (string) \get_class( $this ), (int) $this->$idColumn ) );
/* Delete Polls */
if ( $this instanceof \IPS\Content\Polls and $this->getPoll() )
{
@@ -2912,19 +2945,21 @@ abstract class _Item extends \IPS\Content
{
\IPS\Db::i()->delete( 'core_ratings', array( 'class=? AND item_id=?', \get_called_class(), $this->$idColumn ) );
}
foreach( $memberIds as $member )
{
\IPS\Member::load( $member )->recountNotifications();
}
/** Item::url() can throw a LogicException exception in specific cases like when a Pages Record has no valid page */
try
if( !static::$skipIndexNow )
{
\IPS\core\IndexNow::addUrlToQueue( $this->url() );
try
{
\IPS\core\IndexNow::addUrlToQueue( $this->url() );
}
catch( \LogicException $e ) {}
}
catch( \LogicException $e ) {}
}
/**
@@ -3174,7 +3209,7 @@ abstract class _Item extends \IPS\Content
if ( isset( static::$databaseColumnMap['approved'] ) )
{
$col = static::$databaseTable . '.' . static::$databasePrefix . static::$databaseColumnMap['approved'];
if ( $member->member_id and $includeHiddenItems !== \IPS\Content\Hideable::FILTER_PUBLIC_ONLY )
if ( $member->member_id and $includeHiddenItems !== \IPS\Content\Hideable::FILTER_PUBLIC_ONLY and isset( static::$databaseColumnMap['author'] ) )
{
/* Only fetching a count, for a single container with a item cache count, no future publishing, and there is only one where clause (the container limitation) */
if( $countOnly === TRUE AND $skipPermission instanceof \IPS\Node\Model AND $skipPermission->_items !== NULL AND !\in_array( 'IPS\Content\FuturePublishing', class_implements( \get_called_class() ) ) AND \count( $where ) === 1 )
@@ -8069,7 +8104,13 @@ abstract class _Item extends \IPS\Content
*/
public static function definedTags( \IPS\Node\Model $container = NULL )
{
return \IPS\Settings::i()->tags_predefined ? explode( ',', \IPS\Settings::i()->tags_predefined ) : array();
$return = \IPS\Settings::i()->tags_predefined ? explode( ',', \IPS\Settings::i()->tags_predefined ) : array();
if ( \IPS\Settings::i()->tags_alphabetical )
{
natcasesort( $return );
}
return $return;
}
/**
@@ -8125,8 +8166,20 @@ abstract class _Item extends \IPS\Content
}
}
}
return ( isset ( $this->tags['tags'] ) ? $this->tags['tags'] : [] );
if ( isset( $this->tags['tags'] ) )
{
if ( \IPS\Settings::i()->tags_alphabetical )
{
natcasesort( $this->tags['tags'] );
}
return $this->tags['tags'];
}
else
{
return [];
}
}
else
{
@@ -8617,8 +8670,29 @@ abstract class _Item extends \IPS\Content
$this->$future = 0;
}
if ( isset( static::$databaseColumnMap['last_comment'] ) or isset( static::$databaseColumnMap['last_review'] ) )
{
$lastCommentField = static::$databaseColumnMap['last_comment'];
if ( \is_array( $lastCommentField ) )
{
foreach ( $lastCommentField as $column )
{
$this->$column = time();
}
}
else
{
$this->$lastCommentField = time();
}
if ( isset( static::$databaseColumnMap['last_review'] ) )
{
$lastReviewField = static::$databaseColumnMap['last_review'];
$this->$lastReviewField = time();
}
}
$this->save();
$this->onPublish( $member );
/* And update the tags perm cache */
if ( $this instanceof \IPS\Content\Tags )
@@ -8634,26 +8708,10 @@ abstract class _Item extends \IPS\Content
$comment->$date = time();
$comment->save();
if ( isset( static::$databaseColumnMap['last_comment'] ) )
{
$lastCommentField = static::$databaseColumnMap['last_comment'];
if ( \is_array( $lastCommentField ) )
{
foreach ( $lastCommentField as $column )
{
$this->$column = time();
}
}
else
{
$this->$lastCommentField = time();
}
$this->save();
}
}
$this->onPublish( $member );
/* Mark this item as read for the author */
$this->markRead( $this->author() );