Version 4.7.23
This commit is contained in:
1 parent
7124a02564
commit
25ddeb65d6
1791 files changed
+76990
-44452
No files matched your search
@@ -11,6 +11,10 @@
|
||||
|
||||
namespace IPS\forums;
|
||||
|
||||
use IPS\Content\Comment;
|
||||
use IPS\Db;
|
||||
use IPS\Settings;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
@@ -27,6 +31,7 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
use \IPS\Node\Colorize;
|
||||
use \IPS\Node\Statistics;
|
||||
use \IPS\Content\ViewUpdates;
|
||||
use \IPS\Node\DelayedCount;
|
||||
|
||||
/**
|
||||
* @brief [ActiveRecord] Multiton Store
|
||||
@@ -329,55 +334,40 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
* Last Poster ID Column
|
||||
*/
|
||||
protected static $lastPosterIdColumn = 'last_poster_id';
|
||||
|
||||
|
||||
/**
|
||||
* Set last comment
|
||||
*
|
||||
* @param \IPS\Content\Comment $comment The latest comment or NULL to work it out
|
||||
* @return void
|
||||
* @param Comment|null $comment The latest comment or NULL to work it out
|
||||
* @param Item|null $updatedItem We sometimes run setLastComment() when an item has been edited, if so, that item will be here
|
||||
* @return void
|
||||
*/
|
||||
public function setLastComment( \IPS\Content\Comment $comment=NULL )
|
||||
public function _setLastComment( \IPS\Content\Comment $comment=NULL, \IPS\Content\Item $updatedItem=NULL )
|
||||
{
|
||||
if ( $comment === NULL )
|
||||
/* If we were given an item, but it's older than the current last post, clear it */
|
||||
if( $updatedItem !== NULL AND $updatedItem->mapped('last_comment') < $this->last_post )
|
||||
{
|
||||
$updatedItem = null;
|
||||
}
|
||||
|
||||
/* If we still have no item, load the latest topic */
|
||||
if( $updatedItem === null )
|
||||
{
|
||||
try
|
||||
{
|
||||
/*
|
||||
/*
|
||||
* 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 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 != ? AND forums_topics.last_post<=? AND forums_topics.publish_date <=?", $this->id, 'link', time(), time() ), '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<=? AND forums_topics.publish_date <=?", $this->id, 'link', time(), time() ), 'forums_topics.last_post DESC', 1 )->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 );
|
||||
if ( $member->member_id )
|
||||
{
|
||||
$topic->last_poster_name = $member->name;
|
||||
}
|
||||
else
|
||||
{
|
||||
$topic->last_poster_name = '';
|
||||
$topic->last_poster_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
$this->last_post = $topic->last_post;
|
||||
$this->last_poster_id = (int) $topic->last_poster_id;
|
||||
$this->last_poster_name = $topic->last_poster_name;
|
||||
$this->seo_last_name = \IPS\Http\Url\Friendly::seoTitle( $this->last_poster_name );
|
||||
$this->last_title = $topic->title;
|
||||
$this->seo_last_title = \IPS\Http\Url\Friendly::seoTitle( $this->last_title );
|
||||
$this->last_id = $topic->tid;
|
||||
$this->last_poster_anon = $topic->last_poster_anon;
|
||||
return;
|
||||
$updatedItem = \IPS\forums\Topic::constructFromData( $select );
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
/* At this point we have nothing, so clear the last post data */
|
||||
$this->last_post = NULL;
|
||||
$this->last_poster_id = 0;
|
||||
$this->last_poster_name = '';
|
||||
@@ -387,15 +377,29 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$this->last_post = $comment->mapped('date');
|
||||
$this->last_poster_id = (int) $comment->author()->member_id;
|
||||
$this->last_poster_name = $comment->author()->member_id ? $comment->author()->name : $comment->mapped('author_name');
|
||||
|
||||
if ( $updatedItem->last_poster_id and ! $updatedItem->last_poster_name )
|
||||
{
|
||||
$member = \IPS\Member::load( $updatedItem->last_poster_id );
|
||||
if ( $member->member_id )
|
||||
{
|
||||
$updatedItem->last_poster_name = $member->name;
|
||||
}
|
||||
else
|
||||
{
|
||||
$updatedItem->last_poster_name = '';
|
||||
$updatedItem->last_poster_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
$this->last_post = $updatedItem->last_post;
|
||||
$this->last_poster_id = (int) $updatedItem->last_poster_id;
|
||||
$this->last_poster_name = $updatedItem->last_poster_name;
|
||||
$this->seo_last_name = \IPS\Http\Url\Friendly::seoTitle( $this->last_poster_name );
|
||||
$this->last_title = $comment->item()->title;
|
||||
$this->last_title = $updatedItem->title;
|
||||
$this->seo_last_title = \IPS\Http\Url\Friendly::seoTitle( $this->last_title );
|
||||
$this->last_id = $comment->item()->tid;
|
||||
$this->last_poster_anon = $comment->isAnonymous();
|
||||
$this->last_id = $updatedItem->tid;
|
||||
$this->last_poster_anon = $updatedItem->last_poster_anon;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1064,8 +1068,9 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
$form->add( new \IPS\Helpers\Form\CheckboxSet( 'forum_qa_rate_answers', $this->id ? ( ( $this->qa_rate_answers == '*' or $this->qa_rate_answers === NULL ) ? '*' : explode( ',', $this->qa_rate_answers ) ) : '*', FALSE, array( 'options' => $groupsNoGuests, 'unlimited' => '*', 'multiple' => TRUE, 'impliedUnlimited' => TRUE ), NULL, NULL, NULL, 'forum_qa_rate_answers' ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'forum_forum_allow_rating', $this->id ? $this->forum_allow_rating : FALSE, FALSE, array(), NULL, NULL, NULL, 'forum_allow_rating' ) );
|
||||
$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_moderator', $this->id ? $this->forums_bitoptions['bw_enable_answers_moderator'] : FALSE, FALSE, array( 'togglesOn' => array( 'bw_enable_answers__member', 'solved_stats_from_cutoff' ) ), 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->add( new \IPS\Helpers\Form\Interval( 'solved_stats_from_cutoff', $this->id ? $this->solved_stats_from_cutoff : 0, FALSE, array( 'valueAs' => \IPS\Helpers\Form\Interval::DAYS, 'unlimited' => 0, 'unlimitedLang' => 'alltime' ), NULL, NULL, NULL, 'solved_stats_from_cutoff' ) );
|
||||
|
||||
$form->addTab( 'posting_settings' );
|
||||
$form->addHeader('posts');
|
||||
@@ -1220,6 +1225,20 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $values['solved_stats_from_cutoff'] ) )
|
||||
{
|
||||
/* If answers is disabled, set this to no. */
|
||||
if ( !$values['forums_bitoptions']['bw_enable_answers_moderator'] )
|
||||
{
|
||||
$values['solved_stats_from_cutoff'] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise we need to reset the current time so it rebuilds */
|
||||
$values['solved_stats_from'] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove forum_ prefix */
|
||||
$_values = $values;
|
||||
$values = array();
|
||||
@@ -1633,7 +1652,7 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
/* If this is not a true mass move of contents of one container to another, then let parent handle it normally */
|
||||
if( isset( $data['additional'] ) AND
|
||||
( isset( $data['additional']['author'] ) OR ( isset( $data['additional']['no_comments'] ) AND $data['additional']['no_comments'] > 0 ) OR
|
||||
( isset( $data['additional']['num_comments'] ) AND $data['additional']['num_comments'] > 0 ) OR isset( $data['additional']['state'] ) OR
|
||||
( isset( $data['additional']['num_comments'] ) AND $data['additional']['num_comments'] >= 0 ) OR isset( $data['additional']['state'] ) OR
|
||||
( isset( $data['additional']['pinned'] ) AND $data['additional']['pinned'] === TRUE ) OR ( isset( $data['additional']['featured'] ) AND $data['additional']['featured'] === TRUE ) OR ( isset( $data['additional']['last_post'] ) AND $data['additional']['last_post'] > 0 ) OR ( isset( $data['additional']['date'] ) AND $data['additional']['date'] > 0 ) )
|
||||
)
|
||||
{
|
||||
@@ -1913,8 +1932,15 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
{
|
||||
try
|
||||
{
|
||||
$where = [['forum_id=?', $this->_id]];
|
||||
if ( $this->solved_stats_from_cutoff )
|
||||
{
|
||||
$cutoff = \IPS\DateTime::create()->sub( new \DateInterval( 'P' . $this->solved_stats_from_cutoff . 'D' ) )->getTimestamp();
|
||||
$where[] = ['start_date>?', $cutoff];
|
||||
}
|
||||
|
||||
$post = \IPS\Db::i()->select( '*', 'forums_posts', [
|
||||
'pid IN (?)', \IPS\Db::i()->select( 'topic_answered_pid', 'forums_topics', ['forum_id=?', $this->_id] )
|
||||
'pid IN (?)', \IPS\Db::i()->select( 'topic_answered_pid', 'forums_topics', $where )
|
||||
], 'post_date ASC', 1 )->first();
|
||||
|
||||
try
|
||||
@@ -2266,8 +2292,36 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
break;
|
||||
|
||||
case 'comment':
|
||||
return (bool) ( \In_array( $this->preview_posts, array( 1, 3 ) ) );
|
||||
return (bool) ( \in_array( $this->preview_posts, array( 1, 3 ) ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Count all comments, items, etc
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function recount()
|
||||
{
|
||||
$this->_items = (int) Db::i()->select( 'count(*)', 'forums_topics', [ 'forum_id=? and approved=? and state != ?', $this->_id, 1, 'link' ] )->first();
|
||||
$this->_unapprovedItems = (int) Db::i()->select( 'count(*)', 'forums_topics', [ 'forum_id=? and approved = ? and state !=?', $this->_id, 0, 'link' ] )->first();
|
||||
$this->_comments = (int) Db::i()->select( 'count(*)', 'forums_posts', [ 'queued=? and forum_id=? and approved=? and state != ?', 0, $this->_id, 1, 'link' ] )
|
||||
->join( 'forums_topics', 'forums_posts.topic_id=forums_topics.tid' )
|
||||
->first();
|
||||
$this->_unapprovedComments = (int) Db::i()->select( 'count(*)', 'forums_posts', [ 'queued =? and forum_id=? and approved=? and state != ?', 1, $this->_id, 1, 'link' ] )
|
||||
->join( 'forums_topics', 'forums_posts.topic_id=forums_topics.tid' )
|
||||
->first();
|
||||
|
||||
/* Count archived posts */
|
||||
if( Settings::i()->archive_on )
|
||||
{
|
||||
/* Here we use the sum from the topics table because once the topic is archived, these won't change */
|
||||
$archiveStats = Db::i()->select( 'IFNULL( sum(posts), 0 ) as approved, IFNULL( sum(topic_queuedposts), 0 ) as unapproved', 'forums_topics', [ 'forum_id=? and approved=? and state != ? and topic_archive_status=?', $this->_id, 1, 'link', Topic::ARCHIVE_DONE ] )->first();
|
||||
$this->_comments += $archiveStats['approved'];
|
||||
$this->_unapprovedComments += $archiveStats['unapproved'];
|
||||
}
|
||||
|
||||
$this->save();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user