Version 5.0.13
This commit is contained in:
1 parent
b89858b2ff
commit
5efe744c5f
1407 files changed
+69690
-30177
No files matched your search
@@ -24,6 +24,7 @@ use IPS\Content\Comment;
|
||||
use IPS\Content\Item;
|
||||
use IPS\Content\Search\Index;
|
||||
use IPS\Content\Search\SearchContent;
|
||||
use IPS\Content\Taggable;
|
||||
use IPS\Content\ViewUpdates;
|
||||
use IPS\Data\Store;
|
||||
use IPS\DateTime;
|
||||
@@ -57,6 +58,7 @@ use IPS\Member\Club;
|
||||
use IPS\Member\Group;
|
||||
use IPS\Node\Colorize;
|
||||
use IPS\Node\DelayedCount;
|
||||
use IPS\Node\Grouping;
|
||||
use IPS\Node\Icon;
|
||||
use IPS\Node\Model;
|
||||
use IPS\Node\Permissions;
|
||||
@@ -107,6 +109,7 @@ class Forum extends Model implements Permissions
|
||||
use ClubContainer;
|
||||
use Colorize;
|
||||
use DelayedCount;
|
||||
use Grouping;
|
||||
use Statistics;
|
||||
use ViewUpdates;
|
||||
use Icon;
|
||||
@@ -284,7 +287,7 @@ class Forum extends Model implements Permissions
|
||||
*/
|
||||
public function __set( mixed $key, mixed $value ) : void
|
||||
{
|
||||
if( mb_strpos( $key, "forum_" ) === 0 AND $key !== 'forum_allow_rating' )
|
||||
if( mb_strpos( $key, "forum_" ) === 0 )
|
||||
{
|
||||
$key = preg_replace( "/^forum_(.+?)$/", "$1", $key );
|
||||
$this->$key = $value;
|
||||
@@ -705,6 +708,8 @@ class Forum extends Model implements Permissions
|
||||
*/
|
||||
public function lastPost( int $count=1, bool $isChild=false ): ?array
|
||||
{
|
||||
$results = [];
|
||||
|
||||
if ( $count > 5 )
|
||||
{
|
||||
throw new OverflowException( 'Too many posts to return, maximum is 5' );
|
||||
@@ -718,13 +723,15 @@ class Forum extends Model implements Permissions
|
||||
{
|
||||
try
|
||||
{
|
||||
$results = [];
|
||||
|
||||
foreach(
|
||||
new ActiveRecordIterator(
|
||||
Db::i()->select( '*', 'forums_posts', array( 'topic_id=? AND queued=0', Db::i()->select( 'tid', 'forums_topics', array( 'forum_id=? AND approved=1 AND starter_id=? AND is_future_entry=0', $this->_id, Member::loggedIn()->member_id ), 'last_post DESC', 1 )->first() ), 'post_date DESC', $count ),
|
||||
Post::class ) as $post )
|
||||
{
|
||||
/* @var Post $post */
|
||||
$results[ $post->post_date ] = [
|
||||
'_author' => $post->author()->member_id,
|
||||
'author' => $post->author(),
|
||||
'topic_url' => $post->item()->url(),
|
||||
'topic_title' => $post->item()->title,
|
||||
@@ -743,33 +750,24 @@ class Forum extends Model implements Permissions
|
||||
foreach( $this->children() as $child )
|
||||
{
|
||||
/* We need to merge all children and pick the top 5 */
|
||||
if ( $childLastPost = $child->lastPost( $count ) )
|
||||
if ( $childLastPost = $child->lastPost( $count, true ) )
|
||||
{
|
||||
$results = $results + $childLastPost;
|
||||
if ( is_array( $childLastPost ) )
|
||||
{
|
||||
if ( isset( $childLastPost['date'] ) )
|
||||
{
|
||||
$results[$childLastPost['date']] = $childLastPost;
|
||||
}
|
||||
else
|
||||
{
|
||||
$results = $results + $childLastPost;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( count( $results ) )
|
||||
{
|
||||
krsort( $results );
|
||||
if ( $count === 1 )
|
||||
{
|
||||
/* return the first from the array */
|
||||
return array_shift( $results );
|
||||
}
|
||||
|
||||
/* array_slice re-indexes, and we'd lose the krsort timestamp key */
|
||||
return array_intersect_key( $results, array_flip( array_slice( array_keys( $results ), 0, $count ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
elseif ( !$this->permission_showtopic and !$this->can('view') )
|
||||
{
|
||||
$results = [];
|
||||
|
||||
if( !$this->sub_can_post )
|
||||
{
|
||||
foreach( $this->children() as $child )
|
||||
@@ -777,47 +775,38 @@ class Forum extends Model implements Permissions
|
||||
/* We need to merge all children and pick the top 5 */
|
||||
if ( $childLastPost = $child->lastPost( $count, true ) )
|
||||
{
|
||||
$results = $results + $childLastPost;
|
||||
if ( is_array( $childLastPost ) )
|
||||
{
|
||||
if ( isset( $childLastPost['date'] ) )
|
||||
{
|
||||
$results[$childLastPost['date']] = $childLastPost;
|
||||
}
|
||||
else
|
||||
{
|
||||
$results = $results + $childLastPost;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( count( $results ) )
|
||||
{
|
||||
krsort( $results );
|
||||
if ( $count === 1 )
|
||||
{
|
||||
/* return the first from the array */
|
||||
return array_shift( $results );
|
||||
}
|
||||
|
||||
/* array_slice re-indexes, and we'd lose the krsort timestamp key */
|
||||
return array_intersect_key( $results, array_flip( array_slice( array_keys( $results ), 0, $count ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$results = [];
|
||||
|
||||
/* Do we have any data, or do we need to update? The default or cleared state is NULL, forums without topics should have [] */
|
||||
if ( $this->sub_can_post and $this->posts and ! $this->_data['last_post_data'] )
|
||||
if ( $this->sub_can_post and $this->posts and !$this->_data['last_post_data'] )
|
||||
{
|
||||
$this->setLastComment();
|
||||
|
||||
/* We can't use save as dynamic variables have now been assigned which confuses save() */
|
||||
Db::i()->update( 'forums_forums', [ 'last_post_data' => $this->_data['last_post_data'] ], [ 'id=?', $this->_id ] );
|
||||
Db::i()->update( 'forums_forums', ['last_post_data' => $this->_data['last_post_data']], ['id=?', $this->_id] );
|
||||
}
|
||||
|
||||
$lastPostData = $this->_last_post_data;
|
||||
if ( count( $lastPostData ) )
|
||||
{
|
||||
foreach( $lastPostData as $lastPostTime => $lastPost )
|
||||
foreach ( $lastPostData as $lastPostTime => $lastPost )
|
||||
{
|
||||
if ( $this->sub_can_post and !$this->permission_showtopic and ! $this->can('read') )
|
||||
if ( $this->sub_can_post and !$this->permission_showtopic and !$this->can( 'read' ) )
|
||||
{
|
||||
$lastPost['last_title'] = null;
|
||||
}
|
||||
@@ -829,31 +818,31 @@ class Forum extends Model implements Permissions
|
||||
}
|
||||
else
|
||||
{
|
||||
$author = ! empty( $lastPost['last_poster_id'] ) ? $lastPost['last_poster_id'] : ( $lastPost['last_poster_name'] ?? Member::loggedIn()->language()->addToStack( "guest" ) );
|
||||
$author = !empty( $lastPost['last_poster_id'] ) ? $lastPost['last_poster_id'] : ( $lastPost['last_poster_name'] ?? Member::loggedIn()->language()->addToStack( "guest" ) );
|
||||
}
|
||||
|
||||
$results[ $lastPostTime ] = array(
|
||||
'author' => null,
|
||||
'_author' => $author,
|
||||
'topic_url' => Url::internal( "app=forums&module=forums&controller=topic&id={$lastPost['last_id']}", 'front', 'forums_topic', array( $lastPost['seo_last_title'] ) ),
|
||||
'topic_title' => $lastPost['last_title'],
|
||||
'date' => ( $lastPost['last_post'] ?? (int) ( substr( $lastPostTime, 0, strpos( $lastPostTime, '.' ) ) ) ),
|
||||
'last_poster_anon' => $lastPost['last_poster_anon'],
|
||||
$results[$lastPostTime] = [
|
||||
'author' => null,
|
||||
'_author' => $author,
|
||||
'topic_url' => Url::internal( "app=forums&module=forums&controller=topic&id={$lastPost['last_id']}", 'front', 'forums_topic', [$lastPost['seo_last_title']] ),
|
||||
'topic_title' => $lastPost['last_title'],
|
||||
'date' => ( $lastPost['last_post'] ?? (int)( substr( $lastPostTime, 0, strpos( $lastPostTime, '.' ) ) ) ),
|
||||
'last_poster_anon' => $lastPost['last_poster_anon'],
|
||||
'last_post_snippet' => $lastPost['last_post_snippet'] ?? null,
|
||||
'posts' => $lastPost['posts'] ?? 0
|
||||
);
|
||||
'posts' => $lastPost['posts'] ?? 0
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
foreach( $this->children() as $child )
|
||||
foreach ( $this->children() as $child )
|
||||
{
|
||||
/* @var Forum $child */
|
||||
/* We need to merge all children and pick the top 5 */
|
||||
if ( $childLastPost = $child->lastPost( $count, true ) )
|
||||
{
|
||||
if( is_array( $childLastPost ) )
|
||||
if ( is_array( $childLastPost ) )
|
||||
{
|
||||
if( isset( $childLastPost['date'] ) )
|
||||
if ( isset( $childLastPost['date'] ) )
|
||||
{
|
||||
$results[$childLastPost['date']] = $childLastPost;
|
||||
}
|
||||
@@ -864,75 +853,76 @@ class Forum extends Model implements Permissions
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( count( $results ) )
|
||||
if ( count( $results ) )
|
||||
{
|
||||
/* Don't process the author details if we're not going to use them */
|
||||
if ( ! $isChild )
|
||||
{
|
||||
/* Don't process the author details if we're not going to use them */
|
||||
if ( ! $isChild )
|
||||
{
|
||||
$membersToLoad = [];
|
||||
$membersToLoad = [];
|
||||
|
||||
/* Let's get the author details */
|
||||
foreach ( $results as $timestamp => $data )
|
||||
/* Let's get the author details */
|
||||
foreach ( $results as $timestamp => $data )
|
||||
{
|
||||
if ( $data['_author'] and is_int( $data['_author'] ) )
|
||||
{
|
||||
if ( $data['_author'] and is_int( $data['_author'] ) )
|
||||
$membersToLoad[ $timestamp ] = $data['_author'];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Default to a guest account so we can be sure the author is never null */
|
||||
$results[ $timestamp ]['author'] = new Member;
|
||||
if ( $data['_author'] and is_string( $data['_author'] ) )
|
||||
{
|
||||
$membersToLoad[ $timestamp ] = $data['_author'];
|
||||
$results[ $timestamp ]['author']->name = $data['_author'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$idsToLoad = array_unique( array_values( $membersToLoad ) );
|
||||
|
||||
/* Load the members not in static::$lastPostLoadedMembers */
|
||||
$idsToLoad = array_diff( $idsToLoad, array_keys( static::$lastPostLoadedMembers ) );
|
||||
|
||||
if ( count( $idsToLoad ) )
|
||||
{
|
||||
foreach( Db::i()->select( '*', 'core_members', [ Db::i()->in( 'member_id', $idsToLoad ) ] ) as $lastPostMember )
|
||||
{
|
||||
static::$lastPostLoadedMembers[ $lastPostMember['member_id'] ] = Member::constructFromData( $lastPostMember );
|
||||
}
|
||||
}
|
||||
|
||||
if ( count( $membersToLoad ) )
|
||||
{
|
||||
foreach ( $membersToLoad as $timestamp => $memberId )
|
||||
{
|
||||
if ( isset( static::$lastPostLoadedMembers[ $memberId ] ) )
|
||||
{
|
||||
$results[$timestamp]['author'] = static::$lastPostLoadedMembers[ $memberId ];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Default to a guest account so we can be sure the author is never null */
|
||||
$results[ $timestamp ]['author'] = new Member;
|
||||
if ( $data['_author'] and is_string( $data['_author'] ) )
|
||||
{
|
||||
$results[ $timestamp ]['author']->name = $data['_author'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$idsToLoad = array_unique( array_values( $membersToLoad ) );
|
||||
|
||||
/* Load the members not in static::$lastPostLoadedMembers */
|
||||
$idsToLoad = array_diff( $idsToLoad, array_keys( static::$lastPostLoadedMembers ) );
|
||||
|
||||
if ( count( $idsToLoad ) )
|
||||
{
|
||||
foreach( Db::i()->select( '*', 'core_members', [ Db::i()->in( 'member_id', $idsToLoad ) ] ) as $lastPostMember )
|
||||
{
|
||||
static::$lastPostLoadedMembers[ $lastPostMember['member_id'] ] = Member::constructFromData( $lastPostMember );
|
||||
}
|
||||
}
|
||||
|
||||
if ( count( $membersToLoad ) )
|
||||
{
|
||||
foreach ( $membersToLoad as $timestamp => $memberId )
|
||||
{
|
||||
if ( isset( static::$lastPostLoadedMembers[ $memberId ] ) )
|
||||
{
|
||||
$results[$timestamp]['author'] = static::$lastPostLoadedMembers[ $memberId ];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Technically we shouldn't ever get here, but let's not throw an exception */
|
||||
$results[$timestamp]['author'] = Member::load( $memberId );
|
||||
}
|
||||
/* Technically we shouldn't ever get here, but let's not throw an exception */
|
||||
$results[$timestamp]['author'] = Member::load( $memberId );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
krsort( $results );
|
||||
if ( $count === 1 )
|
||||
{
|
||||
/* return the first from the array */
|
||||
return array_shift( $results );
|
||||
}
|
||||
/* array_slice re-indexes, and we'd lose the krsort timestamp key */
|
||||
return array_intersect_key( $results, array_flip( array_slice( array_keys( $results ), 0, $count ) ) );
|
||||
}
|
||||
else
|
||||
|
||||
krsort( $results );
|
||||
if ( $count === 1 )
|
||||
{
|
||||
return null;
|
||||
/* return the first from the array */
|
||||
return array_shift( $results );
|
||||
}
|
||||
|
||||
/* array_slice re-indexes, and we'd lose the krsort timestamp key */
|
||||
return array_intersect_key( $results, array_flip( array_slice( array_keys( $results ), 0, $count ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2091,10 +2081,8 @@ class Forum extends Model implements Permissions
|
||||
|
||||
/* Do the move */
|
||||
Db::i()->update( 'forums_topics', array( 'forum_id' => $node->_id ), array( 'forum_id=?', $this->_id ) );
|
||||
Db::i()->update( 'forums_question_ratings', array( 'forum' => $node->_id ), array( 'forum=?', $this->_id ) );
|
||||
|
||||
/* Rebuild tags */
|
||||
if ( in_array( 'IPS\Content\Taggable', class_implements( $contentItemClass ) ) )
|
||||
if( IPS::classUsesTrait( $contentItemClass, Taggable::class ) )
|
||||
{
|
||||
Db::i()->update( 'core_tags', array(
|
||||
'tag_aap_lookup' => md5( static::$permApp . ';' . static::$permType . ';' . $node->_id ),
|
||||
@@ -2214,11 +2202,14 @@ class Forum extends Model implements Permissions
|
||||
* @return array
|
||||
* @apiresponse int id ID number
|
||||
* @apiresponse string name Forum name
|
||||
* @apiresponse string description Forum description
|
||||
* @apiresponse string cardImage Forum card image
|
||||
* @apiresponse string path Forum name including parents (e.g. "Example Category > Example Forum")
|
||||
* @apiresponse string type The type of forum: "discussions", "questions", "category", or "redirect"
|
||||
* @apiresponse int topics Number of topics in forum
|
||||
* @apiresponse string url URL
|
||||
* @apiresponse int|null parentId Parent Node ID
|
||||
* @apiresponse int followerCount Total members following this forum
|
||||
* @clientapiresponse object|null permissions Node permissions
|
||||
*/
|
||||
public function apiOutput( Member $authorizedMember = NULL ): array
|
||||
@@ -2246,11 +2237,14 @@ class Forum extends Model implements Permissions
|
||||
$return = array(
|
||||
'id' => $this->id,
|
||||
'name' => $this->_title,
|
||||
'description' => $this->description,
|
||||
'cardImage' => null,
|
||||
'path' => implode( ' > ', $path ),
|
||||
'type' => $type,
|
||||
'topics' => $this->topics,
|
||||
'url' => (string) $this->url(),
|
||||
'parentId' => static::$databaseColumnParent ? $this->{static::$databaseColumnParent} : NULL
|
||||
'parentId' => static::$databaseColumnParent ? $this->{static::$databaseColumnParent} : NULL,
|
||||
'followerCount' => Topic::containerFollowerCount( $this )
|
||||
);
|
||||
|
||||
if( $authorizedMember === NULL )
|
||||
@@ -2271,6 +2265,12 @@ class Forum extends Model implements Permissions
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->card_image )
|
||||
{
|
||||
$file = File::get( 'forums_Cards', $this->card_image );
|
||||
$return['card_image'] = $file->fullyQualifiedUrl( $this->card_image );
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user