Version 5.0.0 beta 9

This commit is contained in:
Neo committed 2025-12-19 17:47:00 -08:00
1 parent 214f649f1d
commit 56979f8ee8
202 files changed
+4403 -1123

No files matched your search

+5 -10
View File
@@ -479,7 +479,7 @@ abstract class Comment extends Content
if ( IPS::classUsesTrait( $this, 'IPS\Content\Anonymous' ) and isset( $item::$databaseColumnMap['last_comment_anon'] ) and isset( static::$databaseColumnMap['is_anon'] ) )
{
$lastCommentAnon = $item::$databaseColumnMap['last_comment_anon'];
$item->$lastCommentAnon = $this->mapped('is_anon');
$item->$lastCommentAnon = (int) $this->mapped('is_anon');
}
$item->save();
@@ -1035,11 +1035,6 @@ abstract class Comment extends Content
{
Index::i()->index( $this );
}
if( Content\Search\SearchContent::isSearchable( $item ) )
{
$item->clearCachedStatistics();
}
}
/* Send the content items URL to IndexNow */
@@ -1188,7 +1183,7 @@ abstract class Comment extends Content
if ( $item AND IPS::classUsesTrait( $this->item(), 'IPS\Content\Statistics' ) )
{
$item->clearCachedStatistics();
$item->clearCachedStatistics( TRUE );
}
/* Delete any notifications telling people about this */
@@ -1883,7 +1878,7 @@ abstract class Comment extends Content
}
}
if ( ! Output::i()->reduceLinks() )
if ( ! Output::i()->reduceLinks() and $this->canShare() )
{
if ( $this->mapped( 'first' ) )
{
@@ -1921,7 +1916,7 @@ abstract class Comment extends Content
}
}
if( $this->canEdit($member ) or (IPS::classUsesTrait( $this, "\\IPS\\Content\\Hideable" ) and $this->canHide( $member )) or $this->canSplit( $member ) )
if( $this->canEdit( $member ) or ( IPS::classUsesTrait( $this, "\\IPS\\Content\\Hideable" ) and $this->canHide( $member ) ) or $this->canSplit( $member ) )
{
$menu->addSeparator();
}
@@ -1965,7 +1960,7 @@ abstract class Comment extends Content
if( $this->canUnhide($member) )
{
$menu->add( new ContentMenuLink( url: $this->url( 'unhide' )->csrf(), languageString: 'unhide', dataAttributes: [
$menu->add( new ContentMenuLink( url: $this->url( 'unhide' )->csrf(), languageString: ( $this->hidden() === 1 ? 'approve' : 'unhide' ), dataAttributes: [
'data-ipsDialog-destructOnClose' => 'true'
] ) );
}
+4 -2
View File
@@ -1475,8 +1475,10 @@ class Controller extends CoverPhotoController
{
$options[ $type->id ] = $type->_title;
}
$form->add( new Radio( 'report_type', NULL, FALSE, array( 'options' => $options ) ) );
if ( count( $options ) > 1 )
{
$form->add( new Radio( 'report_type', NULL, FALSE, ['options' => $options] ) );
}
}
$form->add( new Editor( 'report_message', NULL, FALSE, array( 'app' => 'core', 'key' => 'Reports', 'autoSaveKey' => "report-{$class::$application}-{$class::$module}-{$item->$idColumn}", 'minimize' => Request::i()->isAjax() ? 'report_message_placeholder' : NULL ) ) );
+6
View File
@@ -42,6 +42,12 @@ trait Featurable
return false;
}
/* Skip for hidden content */
if( $this->hidden() !== 0 )
{
return false;
}
/* Is this the first comment in an item that requires first comments? */
if ( $this instanceof Comment )
{
+4 -4
View File
@@ -231,7 +231,7 @@ trait Hideable
/* Restoring as hidden? */
if ( $hidden )
{
$column = static::$databaseColumnMap['hidden'] ?? static::$databaseColumnId['approved'];
$column = static::$databaseColumnMap['hidden'] ?? static::$databaseColumnMap['approved'];
$this->$column = -1;
}
else
@@ -461,7 +461,7 @@ trait Hideable
{
try
{
$item->clearCachedStatistics();
$item->clearCachedStatistics( TRUE );
}
catch ( Exception )
{
@@ -1354,7 +1354,7 @@ trait Hideable
return false;
}
if ( $this->hidden() === -1 )
if ( $this->hidden() <> 0 )
{
return FALSE;
}
@@ -1381,7 +1381,7 @@ trait Hideable
return false;
}
if ( !$this->hidden() )
if ( $this->hidden() === 0 )
{
return FALSE;
}
+3 -3
View File
@@ -832,7 +832,7 @@ abstract class Item extends Content
$return['guest_name'] = new Text( 'guest_name', NULL, FALSE, array( 'minLength' => Settings::i()->min_user_name_length, 'maxLength' => Settings::i()->max_user_name_length, 'placeholder' => Member::loggedIn()->language()->addToStack('comment_guest_name'), 'htmlAutocomplete' => "username" ), NULL, NULL, NULL, 'guest_name' );
}
}
if ( Settings::i()->bot_antispam_type !== 'none' and Settings::i()->guest_captcha )
if ( Settings::i()->bot_antispam_type !== 'none' )
{
$return['captcha'] = new Captcha;
}
@@ -4871,7 +4871,7 @@ abstract class Item extends Content
$return['guest_name'] = new Text( 'guest_name', NULL, FALSE, array( 'minLength' => Settings::i()->min_user_name_length, 'maxLength' => Settings::i()->max_user_name_length, 'placeholder' => Member::loggedIn()->language()->addToStack('comment_guest_name') ) );
}
}
if ( Settings::i()->bot_antispam_type !== 'none' and Settings::i()->guest_captcha )
if ( Settings::i()->bot_antispam_type !== 'none' )
{
$return['captcha'] = new Captcha;
}
@@ -5033,7 +5033,7 @@ abstract class Item extends Content
$form->add( new Text( 'guest_name', NULL, FALSE, array( 'minLength' => Settings::i()->min_user_name_length, 'maxLength' => Settings::i()->max_user_name_length, 'placeholder' => Member::loggedIn()->language()->addToStack('comment_guest_name') ) ) );
}
}
if ( Settings::i()->bot_antispam_type !== 'none' and Settings::i()->guest_captcha )
if ( Settings::i()->bot_antispam_type !== 'none' )
{
$form->add( new Captcha );
}
+13
View File
@@ -68,6 +68,13 @@ trait ItemTopic
*/
abstract function getForumId() : int;
/**
* Determine if the topic sync is enabled
*
* @return bool
*/
abstract function isTopicSyncEnabled() : bool;
/**
* Create/Update Topic
*
@@ -75,6 +82,12 @@ trait ItemTopic
*/
public function syncTopic(): void
{
/* If the topic sync is disabled, stop here */
if( !$this->isTopicSyncEnabled() )
{
return;
}
/* If this item is pending deletion, do nothing */
if( $this->hidden() == -2 )
{
+38
View File
@@ -0,0 +1,38 @@
<?php
/**
* @brief Bluesky share link
* @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 19 November 2024
*/
namespace IPS\Content\ShareServices;
use IPS\Content\ShareServices;
use IPS\Theme;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Bluesky share link
*/
class Bluesky extends ShareServices
{
/**
* Return the HTML code to show the share link
*
* @return string
*/
public function __toString(): string
{
return Theme::i()->getTemplate( 'sharelinks', 'core' )->bluesky( urlencode( $this->url ), $this->title ? urlencode( $this->title ) : NULL );
}
}
@@ -36,14 +36,15 @@ abstract class ShareServices
*/
public static function services(): array
{
return array(
return [
'Bluesky' => 'IPS\Content\ShareServices\Bluesky',
'Facebook' => 'IPS\Content\ShareServices\Facebook',
'Linkedin' => 'IPS\Content\ShareServices\Linkedin',
'Pinterest' => 'IPS\Content\ShareServices\Pinterest',
'Reddit' => 'IPS\Content\ShareServices\Reddit',
'Email' => 'IPS\Content\ShareServices\Email',
'X' => 'IPS\Content\ShareServices\X',
);
];
}
/**
+57 -14
View File
@@ -553,13 +553,22 @@ trait Statistics
/**
* Clear any cached stats
*
* @param bool $force Force immediate cache delete
* @return void
* @throws Exception
*/
public function clearCachedStatistics(): void
public function clearCachedStatistics( bool $force=FALSE )
{
$idField = static::$databaseColumnId;
Db::i()->delete( 'core_item_statistics_cache', array( 'cache_class=? and cache_item_id=?', get_class( $this ), $this->$idField ) );
if( $force )
{
Db::i()->delete( 'core_item_statistics_cache', [ 'cache_class=? and cache_item_id=?', \get_class( $this ), $this->$idField ] );
}
else
{
/* Set cache to time out in 10 minutes. */
Db::i()->update( 'core_item_statistics_cache', [ 'cache_added' => ( time() - 172200 ) ], [ 'cache_class=? and cache_item_id=?', \get_class( $this ), $this->$idField ] );
}
}
/**
@@ -728,6 +737,11 @@ trait Statistics
*/
public static array|null $cachedActivity = NULL;
/**
* @var bool|null Process has rebuild lock
*/
protected ?bool $hasRebuildLock = NULL;
/**
* Get the cached data
*
@@ -738,28 +752,57 @@ trait Statistics
protected function _getCached( string $key ): mixed
{
$idField = static::$databaseColumnId;
if( $this->hasRebuildLock === FALSE )
{
return [];
}
$class = get_class( $this );
$arrayKey = $class.'.'.$this->$idField;
if ( !isset( static::$cachedActivity[$arrayKey] ) )
$arrayKey = $class . '.' . $this->$idField;
if ( !isset( static::$cachedActivity[ $arrayKey ] ) )
{
try
{
$cache = Db::i()->select( '*', 'core_item_statistics_cache', array( 'cache_class=? and cache_item_id=?', $class, $this->$idField ) )->first();
if ( $cache['cache_added'] > time() - 86400 )
$cache = Db::i()->select( '*', 'core_item_statistics_cache', [ 'cache_class=? and cache_item_id=?', $class, $this->$idField ] )->first();
if ( $cache['cache_added'] > ( time() - 172800 ) )
{
static::$cachedActivity[ $arrayKey ] = json_decode( $cache['cache_contents'], TRUE );
}
else
{
Db::i()->delete( 'core_item_statistics_cache', array( 'cache_class=? and cache_item_id=?', get_class( $this ), $this->$idField ) );
$this->hasRebuildLock = TRUE;
$affectedRows = Db::i()->delete( 'core_item_statistics_cache', [ 'cache_class=? and cache_item_id=?', \get_class( $this ), $this->$idField ] );
if( $affectedRows == 0 )
{
/* We did not delete the row, allow another process to rebuild the cache */
$this->hasRebuildLock = FALSE;
return [];
}
}
}
catch( \UnderflowException $e )
{
/* Try to get the lock for new cache generation */
try
{
Db::i()->insert( 'core_item_statistics_cache', [
'cache_class' => \get_class( $this ),
'cache_item_id' => $this->$idField,
'cache_contents' => '[]',
'cache_added' => time()
] );
$this->hasRebuildLock = TRUE;
}
/* We didn't get the lock, return empty array and allow other process to build cache */
catch( \IPS\Db\Exception $e )
{
$this->hasRebuildLock = FALSE;
return [];
}
}
catch( UnderflowException $e ) { }
}
if ( isset(static::$cachedActivity[ $arrayKey ] ) and isset( static::$cachedActivity[ $arrayKey ][ $key ] ) )
if ( isset( static::$cachedActivity[ $arrayKey ] ) and isset( static::$cachedActivity[ $arrayKey ][ $key ] ) )
{
return static::$cachedActivity[ $arrayKey ][ $key ];
}
@@ -767,10 +810,10 @@ trait Statistics
{
if( !isset( static::$cachedActivity[ $arrayKey ] ) )
{
static::$cachedActivity[ $arrayKey ] = array();
static::$cachedActivity[ $arrayKey ] = [];
}
static::$cachedActivity[ $arrayKey ][ $key ] = array();
static::$cachedActivity[ $arrayKey ][ $key ] = [];
throw new OutOfRangeException;
}
}
@@ -819,8 +862,8 @@ trait Statistics
{
Db::i()->insert( 'core_item_statistics_cache', array(
'cache_class' => get_class( $this ),
'cache_item_id' => str_replace( get_class($this) . '.', '', $key),
'cache_contents' => json_encode( static::$cachedActivity[$key] ),
'cache_item_id' => str_replace( \get_class( $this ) . '.', '', $key ),
'cache_contents' => json_encode( static::$cachedActivity[ $key ] ) ?? '[]',
'cache_added' => time()
), TRUE );
}