Version 4.7.6

This commit is contained in:
Neo committed 2025-12-19 16:05:19 -08:00
1 parent 8ba7d43898
commit 7b7404e741
1085 files changed
+30590 -7837

No files matched your search

+90 -21
View File
@@ -343,11 +343,14 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
{
/*
* We prefer fetching post, joining topic, etc. but that is not efficient and causes a temp table and filesort against posts table so we'll lean on the cached last_post value for the topic
* We also need to fetch from the write server in the event that something has just been deleted and the comment hasn't been passed
* We also need to fetch from the write server in the event that something has just been deleted and the comment hasn't been passed.
* We also cannot look for future entries since this code is used in older upgrades, but we can look for the date instead.
*/
$select = \IPS\Db::i()->select( '*', 'forums_topics', array( "forums_topics.forum_id=? AND forums_topics.approved=1 AND forums_topics.state != ?", $this->id, 'link' ), 'forums_topics.last_post DESC', 1, NULL, NULL, \IPS\Db::SELECT_FROM_WRITE_SERVER )->first();
$select = \IPS\Db::i()->select( '*', 'forums_topics', array( "forums_topics.forum_id=? AND forums_topics.approved=1 AND forums_topics.state != ? AND forums_topics.last_post<=?", $this->id, 'link', time() ), 'forums_topics.last_post DESC', 1, NULL, NULL, \IPS\Db::SELECT_FROM_WRITE_SERVER )->first();
$topic = \IPS\forums\Topic::constructFromData( $select );
if ( $topic->last_poster_id and ! $topic->last_poster_name )
{
$member = \IPS\Member::load( $topic->last_poster_id );
@@ -436,7 +439,7 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
{
try
{
$lastPost = \IPS\forums\Topic\Post::constructFromData( \IPS\Db::i()->select( '*', 'forums_posts', array( 'topic_id=? AND queued=0', \IPS\Db::i()->select( 'tid', 'forums_topics', array( 'forum_id=? AND approved=1 AND starter_id=?', $this->_id, \IPS\Member::loggedIn()->member_id ), 'last_post DESC', 1 )->first() ), 'post_date DESC', 1 )->first() );
$lastPost = \IPS\forums\Topic\Post::constructFromData( \IPS\Db::i()->select( '*', 'forums_posts', array( 'topic_id=? AND queued=0', \IPS\Db::i()->select( 'tid', 'forums_topics', array( 'forum_id=? AND approved=1 AND starter_id=? AND is_future_entry=0', $this->_id, \IPS\Member::loggedIn()->member_id ), 'last_post DESC', 1 )->first() ), 'post_date DESC', 1 )->first() );
$result = array(
'author' => $lastPost->author(),
'topic_url' => $lastPost->item()->url(),
@@ -663,11 +666,6 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
}
catch ( \Exception $e ) { }
}
if ( !$this->viglink )
{
\IPS\Settings::i()->viglink_enabled = FALSE;
}
}
/**
@@ -883,7 +881,6 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
'normal' => array( // make sure when adding here that you also add to qa below
'forum_password_on',
'forum_ipseo_priority',
'forum_viglink',
'forum_min_posts_view',
'forum_can_view_others',
'forum_permission_showtopic',
@@ -903,7 +900,6 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
'qa' => array(
'forum_password_on',
'forum_ipseo_priority',
'forum_viglink',
'forum_min_posts_view',
'forum_can_view_others_qa',
'forum_permission_showtopic_qa',
@@ -1010,11 +1006,6 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
)
), NULL, NULL, NULL, 'forum_ipseo_priority' ) );
if ( \IPS\Settings::i()->viglink_enabled )
{
$form->add( new \IPS\Helpers\Form\YesNo( 'forum_viglink', $this->id ? $this->viglink : TRUE, FALSE, array(), NULL, NULL, NULL, 'forum_viglink' ) );
}
$form->addHeader( 'permissions' );
$form->add( new \IPS\Helpers\Form\Number( 'forum_min_posts_view', $this->id ? $this->min_posts_view : 0, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'no_restriction' ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('approved_posts_comments'), 'forum_min_posts_view' ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'forum_can_view_others', $this->id ? $this->can_view_others : TRUE, FALSE, array(), NULL, NULL, NULL, 'forum_can_view_others' ) );
@@ -1074,7 +1065,7 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
$form->add( new \IPS\Helpers\Form\YesNo( 'forum_disable_sharelinks', $this->id ? !$this->disable_sharelinks : TRUE, FALSE, array(), NULL, NULL, NULL, 'forum_disable_sharelinks' ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'bw_enable_answers_moderator', $this->id ? $this->forums_bitoptions['bw_enable_answers_moderator'] : FALSE, FALSE, array( 'togglesOn' => array( 'bw_enable_answers__member' ) ), NULL, NULL, NULL, 'forum_best_answer' ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'bw_enable_answers__member', $this->id ? $this->forums_bitoptions['bw_enable_answers_member'] : FALSE, FALSE, array(), NULL, NULL, NULL, 'bw_enable_answers__member' ) );
$form->addTab( 'posting_settings' );
$form->addHeader('posts');
@@ -1213,8 +1204,18 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
{
if( isset( $values[ $k ] ) )
{
$values['forums_bitoptions'][ $k ] = ( $k == 'bw_enable_answers_member' or $k == 'bw_enable_answers_moderator' or $k == 'bw_fluid_view' ) ? $values[ $k ] : !$values[ $k ];
unset( $values[ $k ] );
/* If were disabling bw_enable_answers_moderator for discussion forums, we need to make sure bw_enable_answers_member is also disabled */
if ( $k == 'bw_enable_answers_moderator' AND !$values[ $k ] )
{
$values['forums_bitoptions']['bw_enable_answers_moderator'] = FALSE;
$values['forums_bitoptions']['bw_enable_answers_member'] = FALSE;
unset( $values['bw_enable_answers_moderator'], $values['bw_enable_answers_member'] );
}
else
{
$values['forums_bitoptions'][ $k ] = ( $k == 'bw_enable_answers_member' or $k == 'bw_enable_answers_moderator' or $k == 'bw_fluid_view' ) ? $values[ $k ] : !$values[ $k ];
unset( $values[ $k ] );
}
}
}
@@ -1281,6 +1282,8 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
$values['preview_posts'] = 0;
}
}
$values['min_posts_post'] = (int) $values['min_posts_post'];
/* Feature color */
if ( isset( $values['use_feature_color'] ) )
@@ -1889,6 +1892,43 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
return $return;
}
/**
* Return the time the first topic was marked as solved in this forum
*
* @return int
*/
public function getFirstSolvedTime(): int
{
if ( ! $this->solved_stats_from )
{
try
{
$post = \IPS\Db::i()->select( '*', 'forums_posts', [
'pid IN (?)', \IPS\Db::i()->select( 'topic_answered_pid', 'forums_topics', ['forum_id=?', $this->_id] )
], 'post_date ASC', 1 )->first();
try
{
$this->solved_stats_from = \IPS\Db::i()->select( 'solved_date', 'core_solved_index', [ 'app=? and comment_id=?', 'forums', $post['pid'] ] )->first();
}
catch( \Exception $e )
{
/* If that goes wrong... */
$this->solved_stats_from = $post['post_date'];
}
}
catch( \UnderflowException $e )
{
/* If all that goes wrong, we have nothing marked so just store now to prevent it rebuilding over and over */
$this->solved_stats_from = time();
}
$this->save();
}
return $this->solved_stats_from;
}
/* !Clubs */
@@ -2016,7 +2056,7 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
$method = ( isset( \IPS\Request::i()->cookie['forum_list_view'] ) ) ? \IPS\Request::i()->cookie['forum_list_view'] : NULL;
$chooseable = \IPS\Settings::i()->forums_view_list_choose;
if ( ! $chooseable )
if ( ! $chooseable or !\IPS\Member::loggedIn()->member_id )
{
return \IPS\Settings::i()->forums_view_list_method;
}
@@ -2049,7 +2089,7 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
$method = ( isset( \IPS\Request::i()->cookie['forum_view'] ) ) ? \IPS\Request::i()->cookie['forum_view'] : NULL;
$chooseable = \IPS\Settings::i()->forums_default_view_choose ? json_decode( \IPS\Settings::i()->forums_default_view_choose , TRUE ) : FALSE;
if ( ! $chooseable )
if ( ! $chooseable or !\IPS\Member::loggedIn()->member_id )
{
return \IPS\Settings::i()->forums_default_view;
}
@@ -2172,4 +2212,33 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
return $type;
}
/**
* Content was held for approval by container
* Allow node classes that can determine if content should be held for approval in individual nodes
*
* @param string $content The type of content we are checking (item, comment, review).
* @param \IPS\Member|NULL $member Member to check or NULL for currently logged in member.
* @return bool
*/
public function contentHeldForApprovalByNode( string $content, ?\IPS\Member $member = NULL ): bool
{
/* If members group bypasses, then no. */
$member = $member ?: \IPS\Member::loggedIn();
if ( $member->group['g_avoid_q'] )
{
return FALSE;
}
switch( $content )
{
case 'item':
return (bool) ( \in_array( $this->preview_posts, array( 1, 2 ) ) );
break;
case 'comment':
return (bool) ( \In_array( $this->preview_posts, array( 1, 3 ) ) );
break;
}
}
}