Version 4.7.0
This commit is contained in:
1 parent
517a5e1f70
commit
8ba7d43898
1933 files changed
+65613
-11332
No files matched your search
@@ -42,7 +42,25 @@ class _forums extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->error( 'node_error', '2F176/1', 404, '' );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected $childrenIds = [];
|
||||
|
||||
protected function getChildrenIds( $forum )
|
||||
{
|
||||
$this->childrenIds[] = $forum->_id;
|
||||
|
||||
foreach( $forum->children() as $node )
|
||||
{
|
||||
$this->childrenIds[] = $node->_id;
|
||||
foreach( $node->children() as $child )
|
||||
{
|
||||
$this->getChildrenIds( $child );
|
||||
}
|
||||
}
|
||||
|
||||
return $this->childrenIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show Forum
|
||||
*
|
||||
@@ -88,37 +106,6 @@ class _forums extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
$getReactions = $getFirstComment = $getFollowerCount = (boolean) ( \IPS\forums\Forum::getMemberListView() === 'snippet' );
|
||||
|
||||
/* Init table (it won't show anything until after the password check, but it sets navigation and titles) */
|
||||
$table = new \IPS\Helpers\Table\Content( 'IPS\forums\Topic', $forum->url(), $where, $forum, NULL, 'view', isset( \IPS\Request::i()->rss ) ? FALSE : TRUE, isset( \IPS\Request::i()->rss ) ? FALSE : TRUE, NULL, $getFirstComment, $getFollowerCount, $getReactions );
|
||||
$table->tableTemplate = array( \IPS\Theme::i()->getTemplate( 'forums', 'forums', 'front' ), 'forumTable' );
|
||||
$table->classes = array( 'cTopicList' );
|
||||
$table->limit = \IPS\Settings::i()->forums_topics_per_page;
|
||||
$table->title = \IPS\Member::loggedIn()->language()->addToStack( ( $forum->forums_bitoptions['bw_enable_answers'] ) ? 'count_questions_in_forum' : 'count_topics_in_forum', FALSE, array( 'pluralize' => array( $forum->topics ) ) );
|
||||
if ( $forum->forums_bitoptions['bw_enable_answers'] )
|
||||
{
|
||||
$table->rowsTemplate = array( $this->themeGroup, 'questionRow' );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( \IPS\forums\Forum::getMemberListView() == 'snippet' )
|
||||
{
|
||||
$table->rowsTemplate = array( $this->themeGroup, 'topicRowSnippet' );
|
||||
}
|
||||
else
|
||||
{
|
||||
$table->rowsTemplate = array( $this->themeGroup, 'topicRow' );
|
||||
}
|
||||
}
|
||||
$table->hover = TRUE;
|
||||
$table->sortOptions['num_replies'] = $table->sortOptions['num_comments'];
|
||||
unset( $table->sortOptions['num_comments'] );
|
||||
|
||||
/* If there's only one forum and we're not in a club, we actually don't want the nav */
|
||||
if ( \IPS\forums\Forum::theOnlyForum() AND !$forum->club() )
|
||||
{
|
||||
\IPS\Output::i()->breadcrumb = isset( \IPS\Output::i()->breadcrumb['module'] ) ? array( 'module' => \IPS\Output::i()->breadcrumb['module'] ) : array();
|
||||
}
|
||||
|
||||
/* Redirect? */
|
||||
if ( $forum->redirect_url )
|
||||
@@ -127,142 +114,283 @@ class _forums extends \IPS\Dispatcher\Controller
|
||||
$forum->save();
|
||||
\IPS\Output::i()->redirect( $forum->redirect_url );
|
||||
}
|
||||
|
||||
|
||||
/* Display */
|
||||
if ( $forum->isCombinedView() )
|
||||
{
|
||||
$childrenIds = $this->getChildrenIds( $forum );
|
||||
$where = array();
|
||||
|
||||
if ( \IPS\forums\Forum::customPermissionNodes() )
|
||||
{
|
||||
$where['container'][] = array( 'forums_forums.password IS NULL' );
|
||||
}
|
||||
|
||||
if ( !\IPS\Settings::i()->club_nodes_in_apps OR !\IPS\Member::loggedIn()->canAccessModule( \IPS\Application\Module::get( 'core', 'clubs', 'front' ) ) )
|
||||
{
|
||||
$where['container'][] = array( 'forums_forums.club_id IS NULL' );
|
||||
}
|
||||
|
||||
$forumIds = array();
|
||||
$ids = $childrenIds;
|
||||
$urlParam = 'forumId' . $forum->_id;
|
||||
|
||||
if ( isset( \IPS\Request::i()->$urlParam ) )
|
||||
{
|
||||
$ids = explode( ',', \IPS\Request::i()->$urlParam );
|
||||
}
|
||||
else if ( isset( \IPS\Request::i()->cookie['forums_flowIdsRoots'] ) and $cookie = json_decode( \IPS\Request::i()->cookie['forums_flowIdsRoots'], TRUE ) )
|
||||
{
|
||||
if ( isset( $cookie[ $forum->_id ] ) )
|
||||
{
|
||||
if ( \is_array( $cookie[ $forum->_id ] ) )
|
||||
{
|
||||
$ids = $cookie[$forum->_id];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Inline forum IDs? */
|
||||
if ( ( \is_array( $ids ) and ! \count( $ids ) ) )
|
||||
{
|
||||
/* If we unselect all the filters, then there is nothing to show... */
|
||||
$where[] = [ "1=2" ];
|
||||
}
|
||||
else if ( \count( $ids ) )
|
||||
{
|
||||
foreach( $ids as $id )
|
||||
{
|
||||
if ( ! \in_array( $id, $childrenIds ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
/* Panic not, they are all loaded into memory at this point */
|
||||
$_forum = \IPS\forums\Forum::load( $id );
|
||||
$forumIds[] = $_forum->id;
|
||||
|
||||
}
|
||||
catch( \Exception $ex ) { }
|
||||
}
|
||||
|
||||
if ( \count( $forumIds ) )
|
||||
{
|
||||
$where['container'][] = array( \IPS\Db::i()->in( 'forums_forums.id', array_filter( $forumIds ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* Simplified view */
|
||||
$table = new \IPS\Helpers\Table\Content( 'IPS\forums\Topic', $forum->url(), $where, $forum, NULL, 'read', TRUE, FALSE, NULL, FALSE, FALSE, FALSE, FALSE );
|
||||
$table->tableTemplate = array( \IPS\Theme::i()->getTemplate( 'index' ), 'simplifiedForumTable' );
|
||||
$table->classes = array( 'cTopicList' );
|
||||
$table->limit = \IPS\Settings::i()->forums_topics_per_page;
|
||||
$table->enableRealtime = true;
|
||||
|
||||
if ( \IPS\forums\Forum::getMemberListView() == 'snippet' )
|
||||
{
|
||||
$table->rowsTemplate = array( \IPS\Theme::i()->getTemplate( 'index' ), 'simplifiedTopicRowSnippet' );
|
||||
}
|
||||
else
|
||||
{
|
||||
$table->rowsTemplate = array( \IPS\Theme::i()->getTemplate( 'index' ), 'simplifiedTopicRow' );
|
||||
}
|
||||
|
||||
$table->honorPinned = \IPS\Settings::i()->forums_fluid_pinned;
|
||||
$table->hover = TRUE;
|
||||
$table->sortOptions['num_replies'] = $table->sortOptions['num_comments'];
|
||||
unset( $table->sortOptions['num_comments'] );
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'index' )->simplifiedView( $table );
|
||||
|
||||
if( \IPS\forums\Forum::theOnlyForum() === NULL )
|
||||
{
|
||||
\IPS\Output::i()->sidebar['contextual'] = \IPS\Theme::i()->getTemplate( 'index' )->simplifiedViewForumSidebar( $forum );
|
||||
}
|
||||
|
||||
if ( isset( $where['container'] ) )
|
||||
{
|
||||
$allForumIds = iterator_to_array( \IPS\Db::i()->select( 'id', 'forums_forums', $where['container'] ) );
|
||||
\IPS\Output::i()->contextualSearchOptions[ \IPS\Member::loggedIn()->language()->addToStack('forums_chosen_forums') ] = array( 'type' => 'forums_topic', 'nodes' => implode( ',', $allForumIds ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Init table (it won't show anything until after the password check, but it sets navigation and titles) */
|
||||
$table = new \IPS\Helpers\Table\Content( 'IPS\forums\Topic', $forum->url(), $where, $forum, NULL, 'view', isset( \IPS\Request::i()->rss ) ? FALSE : TRUE, isset( \IPS\Request::i()->rss ) ? FALSE : TRUE, NULL, $getFirstComment, $getFollowerCount, $getReactions );
|
||||
$table->tableTemplate = array(\IPS\Theme::i()->getTemplate( 'forums', 'forums', 'front' ), 'forumTable');
|
||||
$table->classes = array('cTopicList');
|
||||
$table->limit = \IPS\Settings::i()->forums_topics_per_page;
|
||||
$table->title = \IPS\Member::loggedIn()->language()->addToStack( ( $forum->forums_bitoptions['bw_enable_answers'] ) ? 'count_questions_in_forum' : 'count_topics_in_forum', FALSE, array('pluralize' => array($forum->topics)) );
|
||||
if ( $forum->forums_bitoptions['bw_enable_answers'] )
|
||||
{
|
||||
$table->rowsTemplate = array($this->themeGroup, 'questionRow');
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( \IPS\forums\Forum::getMemberListView() == 'snippet' )
|
||||
{
|
||||
$table->rowsTemplate = array($this->themeGroup, 'topicRowSnippet');
|
||||
}
|
||||
else
|
||||
{
|
||||
$table->rowsTemplate = array($this->themeGroup, 'topicRow');
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->contextualSearchOptions[ \IPS\Member::loggedIn()->language()->addToStack( 'search_contextual_item_forums' ) ] = array( 'type' => 'forums_topic', 'nodes' => $forum->_id );
|
||||
}
|
||||
|
||||
/* If there's only one forum and we're not in a club, we actually don't want the nav */
|
||||
if ( \IPS\forums\Forum::theOnlyForum() and !$forum->club() )
|
||||
{
|
||||
\IPS\Output::i()->breadcrumb = isset( \IPS\Output::i()->breadcrumb['module'] ) ? array('module' => \IPS\Output::i()->breadcrumb['module']) : array();
|
||||
}
|
||||
|
||||
$table->hover = TRUE;
|
||||
if ( isset( $table->sortOptions['num_comments'] ) )
|
||||
{
|
||||
$table->sortOptions['num_replies'] = $table->sortOptions['num_comments'];
|
||||
unset( $table->sortOptions['num_comments'] );
|
||||
}
|
||||
|
||||
/* Custom Search */
|
||||
$filterOptions = array(
|
||||
'all' => 'all_topics',
|
||||
'open' => 'open_topics',
|
||||
'popular' => 'popular_now',
|
||||
'poll' => 'poll',
|
||||
'locked' => 'locked_topics',
|
||||
'moved' => 'moved_topics',
|
||||
'all' => 'all_topics',
|
||||
'open' => 'open_topics',
|
||||
'popular' => 'popular_now',
|
||||
'poll' => 'poll',
|
||||
'locked' => 'locked_topics',
|
||||
'moved' => 'moved_topics',
|
||||
);
|
||||
$timeFrameOptions = array(
|
||||
'show_all' => 'show_all',
|
||||
'today' => 'today',
|
||||
'last_5_days' => 'last_5_days',
|
||||
'last_7_days' => 'last_7_days',
|
||||
'last_10_days' => 'last_10_days',
|
||||
'last_15_days' => 'last_15_days',
|
||||
'last_20_days' => 'last_20_days',
|
||||
'last_25_days' => 'last_25_days',
|
||||
'last_30_days' => 'last_30_days',
|
||||
'last_60_days' => 'last_60_days',
|
||||
'last_90_days' => 'last_90_days',
|
||||
'show_all' => 'show_all',
|
||||
'today' => 'today',
|
||||
'last_5_days' => 'last_5_days',
|
||||
'last_7_days' => 'last_7_days',
|
||||
'last_10_days' => 'last_10_days',
|
||||
'last_15_days' => 'last_15_days',
|
||||
'last_20_days' => 'last_20_days',
|
||||
'last_25_days' => 'last_25_days',
|
||||
'last_30_days' => 'last_30_days',
|
||||
'last_60_days' => 'last_60_days',
|
||||
'last_90_days' => 'last_90_days',
|
||||
);
|
||||
|
||||
|
||||
if ( \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
$filterOptions['starter'] = $forum->forums_bitoptions['bw_enable_answers'] ? 'questions_i_asked' : 'topics_i_started';
|
||||
$filterOptions['replied'] = $forum->forums_bitoptions['bw_enable_answers'] ? 'questions_i_posted_in' : 'topics_i_posted_in';
|
||||
|
||||
if ( \IPS\Member::loggedIn()->member_id AND \IPS\Member::loggedIn()->last_visit)
|
||||
if ( \IPS\Member::loggedIn()->member_id and \IPS\Member::loggedIn()->last_visit )
|
||||
{
|
||||
$timeFrameOptions['since_last_visit'] = \IPS\Member::loggedIn()->language()->addToStack('since_last_visit', FALSE, array( 'sprintf' => array( \IPS\DateTime::ts( \IPS\Member::loggedIn()->last_visit ) ) ) );
|
||||
$timeFrameOptions['since_last_visit'] = \IPS\Member::loggedIn()->language()->addToStack( 'since_last_visit', FALSE, array('sprintf' => array(\IPS\DateTime::ts( \IPS\Member::loggedIn()->last_visit ))) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if ( $forum->forums_bitoptions['bw_enable_answers'] )
|
||||
{
|
||||
$table->filters = array(
|
||||
'questions_with_best_answers' => 'topic_answered_pid>0',
|
||||
'questions_without_best_answers' => 'topic_answered_pid=0',
|
||||
'questions_with_best_answers' => 'topic_answered_pid>0',
|
||||
'questions_without_best_answers' => 'topic_answered_pid=0',
|
||||
);
|
||||
|
||||
|
||||
$table->sortOptions['question_rating'] = 'forums_topics.question_rating';
|
||||
}
|
||||
else if ( $forum->forums_bitoptions['bw_enable_answers_moderator'] )
|
||||
else
|
||||
{
|
||||
$table->filters = array(
|
||||
'solved_topics' => 'topic_answered_pid>0',
|
||||
'unsolved_topics' => 'topic_answered_pid=0',
|
||||
);
|
||||
if ( $forum->forums_bitoptions['bw_enable_answers_moderator'] )
|
||||
{
|
||||
$table->filters = array(
|
||||
'solved_topics' => 'topic_answered_pid>0',
|
||||
'unsolved_topics' => 'topic_answered_pid=0',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/* Are we a moderator? */
|
||||
if( \IPS\forums\Topic::modPermission( 'unhide', NULL, $forum ) )
|
||||
if ( \IPS\forums\Topic::modPermission( 'unhide', NULL, $forum ) )
|
||||
{
|
||||
$filterOptions['queued_topics'] = 'queued_topics';
|
||||
$filterOptions['queued_posts'] = 'queued_posts';
|
||||
$filterOptions['queued_topics'] = 'queued_topics';
|
||||
$filterOptions['queued_posts'] = 'queued_posts';
|
||||
|
||||
$table->filters['filter_hidden_topics'] = 'approved=-1';
|
||||
$table->filters['filter_hidden_posts_in_topics'] = 'topic_hiddenposts=1';
|
||||
}
|
||||
|
||||
/* Are we filtering by queued topics or posts? */
|
||||
if( \IPS\Request::i()->filter == 'queued_topics' OR \IPS\Request::i()->filter == 'queued_posts' )
|
||||
if ( \IPS\Request::i()->filter == 'queued_topics' or \IPS\Request::i()->filter == 'queued_posts' )
|
||||
{
|
||||
\IPS\Request::i()->advanced_search_submitted = 1;
|
||||
\IPS\Request::i()->csrfKey = \IPS\Session::i()->csrfKey;
|
||||
\IPS\Request::i()->topic_type = \IPS\Request::i()->filter;
|
||||
}
|
||||
|
||||
|
||||
$table->advancedSearch = array(
|
||||
'topic_type' => array( \IPS\Helpers\Table\SEARCH_SELECT, array( 'options' => $filterOptions ) ),
|
||||
'sort_by' => array( \IPS\Helpers\Table\SEARCH_SELECT, array( 'options' => array(
|
||||
'last_post' => 'last_post',
|
||||
'replies' => 'replies',
|
||||
'views' => 'views',
|
||||
'topic_title' => 'topic_title',
|
||||
'last_poster' => 'last_poster',
|
||||
'topic_started' => 'topic_started',
|
||||
'topic_starter' => $forum->forums_bitoptions['bw_enable_answers'] ? 'question_asker' : 'topic_starter',
|
||||
) )
|
||||
'topic_type' => array(\IPS\Helpers\Table\SEARCH_SELECT, array('options' => $filterOptions)),
|
||||
'sort_by' => array(\IPS\Helpers\Table\SEARCH_SELECT, array('options' => array(
|
||||
'last_post' => 'last_post',
|
||||
'replies' => 'replies',
|
||||
'views' => 'views',
|
||||
'topic_title' => 'topic_title',
|
||||
'last_poster' => 'last_poster',
|
||||
'topic_started' => 'topic_started',
|
||||
'topic_starter' => $forum->forums_bitoptions['bw_enable_answers'] ? 'question_asker' : 'topic_starter',
|
||||
))
|
||||
),
|
||||
'sort_direction'=> array( \IPS\Helpers\Table\SEARCH_SELECT, array( 'options' => array(
|
||||
'asc' => 'asc',
|
||||
'desc' => 'desc',
|
||||
) )
|
||||
'sort_direction' => array(\IPS\Helpers\Table\SEARCH_SELECT, array('options' => array(
|
||||
'asc' => 'asc',
|
||||
'desc' => 'desc',
|
||||
))
|
||||
),
|
||||
'time_frame' => array( \IPS\Helpers\Table\SEARCH_SELECT, array( 'options' => $timeFrameOptions ) ),
|
||||
'time_frame' => array(\IPS\Helpers\Table\SEARCH_SELECT, array('options' => $timeFrameOptions)),
|
||||
);
|
||||
$table->advancedSearchCallback = function( $table, $values )
|
||||
{
|
||||
$table->advancedSearchCallback = function ( $table, $values ) {
|
||||
/* Type */
|
||||
switch ( $values['topic_type'] )
|
||||
{
|
||||
case 'open':
|
||||
$table->where[] = array( 'state=?', 'open' );
|
||||
$table->where[] = array('state=?', 'open');
|
||||
break;
|
||||
case 'popular':
|
||||
$table->where[] = array( 'popular_time IS NOT NULL AND popular_time>?', time() );
|
||||
$table->where[] = array('popular_time IS NOT NULL AND popular_time>?', time());
|
||||
break;
|
||||
case 'poll':
|
||||
$table->where[] = array( 'poll_state<>0' );
|
||||
$table->where[] = array('poll_state<>0');
|
||||
break;
|
||||
case 'locked':
|
||||
$table->where[] = array( 'state=?', 'closed' );
|
||||
$table->where[] = array('state=?', 'closed');
|
||||
break;
|
||||
case 'moved':
|
||||
$table->where[] = array( 'state=?', 'link' );
|
||||
$table->where[] = array('state=?', 'link');
|
||||
break;
|
||||
case 'starter':
|
||||
$table->where[] = array( 'starter_id=?', \IPS\Member::loggedIn()->member_id );
|
||||
$table->where[] = array('starter_id=?', \IPS\Member::loggedIn()->member_id);
|
||||
break;
|
||||
case 'replied':
|
||||
$table->joinComments = TRUE;
|
||||
$table->where[] = array( 'forums_posts.author_id=?', \IPS\Member::loggedIn()->member_id );
|
||||
$table->where[] = array('forums_posts.author_id=?', \IPS\Member::loggedIn()->member_id);
|
||||
break;
|
||||
case 'answered':
|
||||
$table->where[] = array( 'topic_answered_pid<>0' );
|
||||
$table->where[] = array('topic_answered_pid<>0');
|
||||
break;
|
||||
case 'unanswered':
|
||||
$table->where[] = array( 'topic_answered_pid=0' );
|
||||
$table->where[] = array('topic_answered_pid=0');
|
||||
break;
|
||||
case 'queued_topics':
|
||||
$table->where[] = array( 'approved=0' );
|
||||
$table->where[] = array('approved=0');
|
||||
break;
|
||||
case 'queued_posts':
|
||||
$table->where[] = array( 'topic_queuedposts>0' );
|
||||
$table->where[] = array('topic_queuedposts>0');
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ! isset( $values['sort_by'] ) )
|
||||
|
||||
if ( !isset( $values['sort_by'] ) )
|
||||
{
|
||||
$values['sort_by'] = 'forums_topics.last_post';
|
||||
}
|
||||
|
||||
|
||||
/* Sort */
|
||||
switch ( $values['sort_by'] )
|
||||
{
|
||||
@@ -288,10 +416,10 @@ class _forums extends \IPS\Dispatcher\Controller
|
||||
break;
|
||||
}
|
||||
$table->sortDirection = $values['sort_direction'];
|
||||
|
||||
|
||||
/* Cutoff */
|
||||
$days = NULL;
|
||||
|
||||
|
||||
if ( isset( $values['time_frame'] ) )
|
||||
{
|
||||
switch ( $values['time_frame'] )
|
||||
@@ -327,18 +455,18 @@ class _forums extends \IPS\Dispatcher\Controller
|
||||
$days = 90;
|
||||
break;
|
||||
case 'since_last_visit':
|
||||
$table->where[] = array( 'forums_topics.last_post>?', \IPS\Member::loggedIn()->last_visit );
|
||||
$table->where[] = array('forums_topics.last_post>?', \IPS\Member::loggedIn()->last_visit);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $days !== NULL )
|
||||
{
|
||||
$table->where[] = array( 'forums_topics.last_post>?', \IPS\DateTime::create()->sub( new \DateInterval( 'P' . $days . 'D' ) )->getTimestamp() );
|
||||
$table->where[] = array('forums_topics.last_post>?', \IPS\DateTime::create()->sub( new \DateInterval( 'P' . $days . 'D' ) )->getTimestamp());
|
||||
}
|
||||
};
|
||||
\IPS\Request::i()->sort_direction = \IPS\Request::i()->sort_direction ?: mb_strtolower( $table->sortDirection );
|
||||
|
||||
\IPS\Request::i()->sort_direction = \IPS\Request::i()->sort_direction ?: mb_strtolower( $table->sortDirection );
|
||||
|
||||
/* Saved actions */
|
||||
foreach ( \IPS\forums\SavedAction::actions( $forum ) as $action )
|
||||
{
|
||||
@@ -353,7 +481,7 @@ class _forums extends \IPS\Dispatcher\Controller
|
||||
|
||||
if ( \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
$key = md5( ( \IPS\Member::loggedIn()->members_pass_hash ?: \IPS\Member::loggedIn()->email ) . \IPS\Member::loggedIn()->members_pass_salt );
|
||||
$key = \IPS\Member::loggedIn()->getUniqueMemberHash();
|
||||
|
||||
$rssUrl = $rssUrl->setQueryString( array( 'member' => \IPS\Member::loggedIn()->member_id , 'key' => $key ) );
|
||||
}
|
||||
@@ -377,6 +505,23 @@ class _forums extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
\IPS\forums\Forum::populateFollowerCounts( $forum );
|
||||
}
|
||||
|
||||
/* Data Layer Context */
|
||||
if ( !\IPS\Request::i()->isAjax AND \IPS\Settings::i()->core_datalayer_enabled )
|
||||
{
|
||||
foreach ( $forum->getDataLayerProperties() as $key => $value )
|
||||
{
|
||||
\IPS\core\DataLayer::i()->addContextProperty( $key, $value );
|
||||
\IPS\core\DataLayer::i()->addContextProperty( 'sort_direction', \IPS\Request::i()->sort_direction ?: null );
|
||||
$sortby = \IPS\Request::i()->sort_by ?: null;
|
||||
if ( $sortby AND !\in_array( $sortby, ['asc', 'desc'] ) )
|
||||
{
|
||||
$sortby = null;
|
||||
}
|
||||
\IPS\core\DataLayer::i()->addContextProperty( 'sort_by', $sortby );
|
||||
\IPS\core\DataLayer::i()->addContextProperty( 'page_number', 'page' );
|
||||
}
|
||||
}
|
||||
|
||||
/* Show Forum */
|
||||
if ( isset( \IPS\Request::i()->advancedSearchForm ) )
|
||||
@@ -384,11 +529,10 @@ class _forums extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->output = (string) $table;
|
||||
return;
|
||||
}
|
||||
\IPS\Output::i()->contextualSearchOptions[ \IPS\Member::loggedIn()->language()->addToStack( 'search_contextual_item_forums' ) ] = array( 'type' => 'forums_topic', 'nodes' => $forum->_id );
|
||||
|
||||
$forumOutput = '';
|
||||
|
||||
if ( $forum->forums_bitoptions['bw_enable_answers'] )
|
||||
if ( ! $forum->isCombinedView() and $forum->forums_bitoptions['bw_enable_answers'] )
|
||||
{
|
||||
$featuredTopic = NULL;
|
||||
|
||||
@@ -412,14 +556,25 @@ class _forums extends \IPS\Dispatcher\Controller
|
||||
$newQuestions = \IPS\forums\Topic::getItemsWithPermission( $newQuestionsWhere, 'start_date DESC', 5 );
|
||||
$forumOutput = \IPS\Theme::i()->getTemplate( 'forums' )->qaForum( (string) $table, $popularQuestions, $newQuestions, $featuredTopic, $forum );
|
||||
}
|
||||
else if( $forum->sub_can_post )
|
||||
else if( $forum->sub_can_post or $forum->isCombinedView() )
|
||||
{
|
||||
$forumOutput = (string) $table;
|
||||
}
|
||||
|
||||
$table = $this->postProcessTable( $table );
|
||||
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js('front_forum.js', 'forums' ) );
|
||||
\IPS\Output::i()->output = $this->themeGroup->forumDisplay( $forum, $forumOutput );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the forum table
|
||||
*
|
||||
* @return \IPS\Helpers\Table\Content
|
||||
*/
|
||||
protected function postProcessTable( $table ) {
|
||||
return $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show Club Forums
|
||||
@@ -596,10 +751,39 @@ class _forums extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
\IPS\Db::i()->replace( 'forums_view_method', array( 'member_id' => \IPS\Member::loggedIn()->member_id, 'method' => $method, 'type' => 'list' ) );
|
||||
}
|
||||
|
||||
|
||||
if ( ! \IPS\Request::i()->id )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=forums&module=forums&controller=index', 'front', 'forums' ) );
|
||||
}
|
||||
\IPS\Output::i()->redirect( \IPS\forums\Forum::load( \IPS\Request::i()->id )->url() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the combined fluid view start modal form elements
|
||||
* @param $nodes
|
||||
* @param $disabled
|
||||
* @param $node
|
||||
* @param int $depth
|
||||
*/
|
||||
protected function _selectForumPopulate( &$nodes, &$disabled, $node, $depth = 0 )
|
||||
{
|
||||
if ( $node->can('view') )
|
||||
{
|
||||
$nodes[ $node->_id ] = str_repeat( '- ', $depth ) . $node->_title;
|
||||
|
||||
if ( ! $node->can('add') )
|
||||
{
|
||||
$disabled[] = $node->_id;
|
||||
}
|
||||
|
||||
foreach( $node->children() AS $child )
|
||||
{
|
||||
$this->_selectForumPopulate( $nodes, $disabled, $child, $depth + 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the forum selector for creating a topic outside of specific forum
|
||||
*
|
||||
@@ -607,31 +791,59 @@ class _forums extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function _selectForum()
|
||||
{
|
||||
if( !\IPS\forums\Forum::canOnAny( 'add' ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2F176/5', 403, 'no_module_permission_guest' );
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form( 'select_forum', 'continue' );
|
||||
$form->class = 'ipsForm_vertical ipsForm_noLabels';
|
||||
$form->add( new \IPS\Helpers\Form\Node( 'forum', NULL, TRUE, array(
|
||||
'url' => \IPS\Http\Url::internal( 'app=forums&module=forums&controller=forums&do=createMenu' ),
|
||||
'class' => 'IPS\forums\Forum',
|
||||
'permissionCheck' => function( $node )
|
||||
{
|
||||
if ( $node->can( 'view' ) )
|
||||
{
|
||||
if ( $node->can( 'add' ) )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
},
|
||||
'clubs' => \IPS\Settings::i()->club_nodes_in_apps
|
||||
) ) );
|
||||
|
||||
if ( isset( \IPS\Request::i()->root ) )
|
||||
{
|
||||
$root = \IPS\forums\Forum::load( \IPS\Request::i()->root );
|
||||
$options = [];
|
||||
$disabled = [];
|
||||
$this->_selectForumPopulate( $options, $disabled, $root );
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'forum', $root->id, TRUE, [
|
||||
'options' => $options,
|
||||
'disabled' => $disabled
|
||||
] ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Node( 'forum', NULL, TRUE, array(
|
||||
'url' => \IPS\Http\Url::internal( 'app=forums&module=forums&controller=forums&do=createMenu' ),
|
||||
'class' => 'IPS\forums\Forum',
|
||||
'permissionCheck' => function ( $node ) {
|
||||
if ( $node->can( 'view' ) )
|
||||
{
|
||||
if ( $node->can( 'add' ) )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
},
|
||||
'clubs' => \IPS\Settings::i()->club_nodes_in_apps
|
||||
) ) );
|
||||
}
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
\IPS\Output::i()->redirect( $values['forum']->url()->setQueryString( 'do', 'add' ) );
|
||||
if ( \is_numeric( $values['forum'] ) )
|
||||
{
|
||||
$forum = \IPS\forums\Forum::load( $values['forum'] );
|
||||
}
|
||||
else
|
||||
{
|
||||
$forum = $values['forum'];
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( $forum->url()->setQueryString( 'do', 'add' ) );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'select_forum' );
|
||||
|
||||
@@ -117,7 +117,7 @@ class _index extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$where = array();
|
||||
|
||||
if ( \IPS\forums\Forum::hasPasswordForums() )
|
||||
if ( \IPS\forums\Forum::customPermissionNodes() )
|
||||
{
|
||||
$where = array( 'container' => array( array( 'forums_forums.password IS NULL' ) ) );
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ class _topic extends \IPS\Content\Controller
|
||||
/**
|
||||
* View Topic
|
||||
*
|
||||
* @return void
|
||||
* @return \IPS\Content\Item
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function manage()
|
||||
@@ -263,7 +263,7 @@ class _topic extends \IPS\Content\Controller
|
||||
$current = current( $comments );
|
||||
reset( $comments );
|
||||
|
||||
if( !\count( $comments ) AND !$topic->isQuestion() )
|
||||
if( ( !\count( $comments ) AND !$topic->isQuestion() ) OR ( $topic->isQuestion() AND empty( $question ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_posts_returned', '2F173/L', 404, '' );
|
||||
}
|
||||
@@ -296,6 +296,9 @@ class _topic extends \IPS\Content\Controller
|
||||
reset( $comments );
|
||||
}
|
||||
|
||||
/* A convenient hook point to do any further set up */
|
||||
$this->finishManage( $topic );
|
||||
|
||||
$votes = array();
|
||||
$topicVotes = array();
|
||||
|
||||
@@ -357,29 +360,43 @@ class _topic extends \IPS\Content\Controller
|
||||
{
|
||||
try
|
||||
{
|
||||
$answer = \IPS\forums\Topic\Post::load( $topic->topic_answered_pid );
|
||||
|
||||
\IPS\Output::i()->jsonLd['topic']['mainEntity']['acceptedAnswer'] = array(
|
||||
'@type' => 'Answer',
|
||||
'text' => $answer->truncated( TRUE, NULL ),
|
||||
'url' => (string) $answer->url(),
|
||||
'dateCreated' => \IPS\DateTime::ts( $answer->post_date )->format( \IPS\DateTime::ISO8601 ),
|
||||
'upvoteCount' => $answer->reactionCount(),
|
||||
'author' => array(
|
||||
'@type' => 'Person',
|
||||
'name' => $answer->author_name ?: \IPS\Member::load( $answer->author_id )->name,
|
||||
'image' => \IPS\Member::load( $answer->author_id )->get_photo( TRUE, TRUE )
|
||||
),
|
||||
);
|
||||
|
||||
if( $topic->isQuestion() )
|
||||
$postClass = '\IPS\forums\Topic\Post';
|
||||
|
||||
if( $topic->isArchived() )
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['topic']['mainEntity']['acceptedAnswer']['upvoteCount'] = $answer->post_field_int;
|
||||
$postClass = '\IPS\forums\Topic\ArchivedPost';
|
||||
}
|
||||
|
||||
if( $answer->author_id )
|
||||
|
||||
$answer = $postClass::load( $topic->topic_answered_pid );
|
||||
|
||||
/* Set up our column names */
|
||||
$authorIdColumn = $answer::$databaseColumnMap['author'];
|
||||
$dateColumn = $answer::$databaseColumnMap['date'];
|
||||
|
||||
if ( $truncatedAnswer = $answer->truncated( TRUE, NULL ) )
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['topic']['mainEntity']['acceptedAnswer']['author']['url'] = (string) \IPS\Member::load( $answer->author_id )->url();
|
||||
\IPS\Output::i()->jsonLd['topic']['mainEntity']['acceptedAnswer'] = array(
|
||||
'@type' => 'Answer',
|
||||
'text' => $truncatedAnswer,
|
||||
'url' => (string) $answer->url(),
|
||||
'dateCreated' => \IPS\DateTime::ts( $answer->$dateColumn )->format( \IPS\DateTime::ISO8601 ),
|
||||
'upvoteCount' => ( $topic->isArchived() ) ? $answer->field_int : $answer->post_field_int,
|
||||
'author' => array(
|
||||
'@type' => 'Person',
|
||||
'name' => \IPS\Member::load( $answer->$authorIdColumn )->name,
|
||||
'image' => \IPS\Member::load( $answer->$authorIdColumn )->get_photo( TRUE, TRUE )
|
||||
),
|
||||
);
|
||||
|
||||
if( $topic->isQuestion() )
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['topic']['mainEntity']['acceptedAnswer']['upvoteCount'] = ( $topic->isArchived() ) ? $answer->field_int : $answer->post_field_int;
|
||||
}
|
||||
|
||||
if( $answer->author_id )
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['topic']['mainEntity']['acceptedAnswer']['author']['url'] = (string) \IPS\Member::load( $answer->$authorIdColumn )->url();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( \OutOfRangeException $e ){}
|
||||
@@ -424,14 +441,19 @@ class _topic extends \IPS\Content\Controller
|
||||
$commentJson = [];
|
||||
foreach( $comments as $comment )
|
||||
{
|
||||
/* Set up our column names */
|
||||
$idColumn = $comment::$databaseColumnId;
|
||||
$authorIdColumn = $comment::$databaseColumnMap['author'];
|
||||
$dateColumn = $comment::$databaseColumnMap['date'];
|
||||
|
||||
// Don't include the first post as a "comment"
|
||||
if( $comment->pid == $topic->topic_firstpost )
|
||||
if( $comment->$idColumn == $topic->topic_firstpost )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't include the answer as the suggested answer
|
||||
if( $isQuestion and ( $comment->pid === $topic->mapped('solved_comment_id') ) )
|
||||
if( $isQuestion and ( $comment->$idColumn === $topic->mapped('solved_comment_id') ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -442,21 +464,30 @@ class _topic extends \IPS\Content\Controller
|
||||
|
||||
$commentJson[$i] = array(
|
||||
'@type' => $isQuestion ? 'Answer' : 'Comment',
|
||||
'@id' => (string)$url->setFragment( 'comment-' . $comment->pid ),
|
||||
'url' => (string)$url->setFragment( 'comment-' . $comment->pid ),
|
||||
'@id' => (string)$url->setFragment( 'comment-' . $comment->$idColumn ),
|
||||
'url' => (string)$url->setFragment( 'comment-' . $comment->$idColumn ),
|
||||
'author' => array(
|
||||
'@type' => 'Person',
|
||||
'name' => $comment->author_name ?: \IPS\Member::load( $comment->author_id )->name,
|
||||
'image' => \IPS\Member::load( $comment->author_id )->get_photo( TRUE, TRUE )
|
||||
'name' => \IPS\Member::load( $comment->$authorIdColumn )->name,
|
||||
'image' => \IPS\Member::load( $comment->$authorIdColumn )->get_photo( TRUE, TRUE )
|
||||
),
|
||||
'dateCreated' => \IPS\DateTime::ts( $comment->post_date )->format( \IPS\DateTime::ISO8601 ),
|
||||
'upvoteCount' => $comment->reactionCount(),
|
||||
'dateCreated' => \IPS\DateTime::ts( $comment->$dateColumn )->format( \IPS\DateTime::ISO8601 ),
|
||||
|
||||
'text' => $truncatedComment,
|
||||
);
|
||||
|
||||
if ( $comment->author_id )
|
||||
if ( $comment->$authorIdColumn )
|
||||
{
|
||||
$commentJson[$i]['author']['url'] = (string)\IPS\Member::load( $comment->author_id )->url();
|
||||
$commentJson[$i]['author']['url'] = (string)\IPS\Member::load( $comment->$authorIdColumn )->url();
|
||||
}
|
||||
|
||||
if( $isQuestion )
|
||||
{
|
||||
$commentJson[$i]['upvoteCount'] = ( $topic->isArchived() ) ? $comment->field_int : $comment->post_field_int;
|
||||
}
|
||||
else
|
||||
{
|
||||
$commentJson[$i]['upvoteCount'] = $comment->reactionCount();
|
||||
}
|
||||
|
||||
$i++;
|
||||
@@ -491,7 +522,7 @@ class _topic extends \IPS\Content\Controller
|
||||
{
|
||||
/* We do not want to use the \IPS\CACHE_PRIVATE_TIMEOUT constant here, as we explicitly want to cache archived topics for longer times */
|
||||
$httpHeaders = array( 'Expires' => \IPS\DateTime::create()->add( new \DateInterval( 'PT12H' ) )->rfc1123() ,
|
||||
'Cache-Control' => "max-age=" . ( 60 * 60 * 12 ) . ", s-maxage=" . ( 60 * 60 * 12 ) . ", public, stale-if-error, stale-while-revalidate" );
|
||||
'Cache-Control' => 'no-cache="Set-Cookie", max-age=' . ( 60 * 60 * 12 ) . ", s-maxage=" . ( 60 * 60 * 12 ) . ", public, stale-if-error, stale-while-revalidate" );
|
||||
|
||||
\IPS\Output::i()->httpHeaders += $httpHeaders;
|
||||
}
|
||||
@@ -507,7 +538,7 @@ class _topic extends \IPS\Content\Controller
|
||||
'image' => (string) \IPS\Member::load( $topic->starter_id )->get_photo( TRUE, TRUE ),
|
||||
'author' => array(
|
||||
'@type' => 'Person',
|
||||
'name' => $topic->starter_name ?: \IPS\Member::load( $topic->starter_id )->name,
|
||||
'name' => \IPS\Member::load( $topic->starter_id )->name,
|
||||
'image' => \IPS\Member::load( $topic->starter_id )->get_photo( TRUE, TRUE )
|
||||
),
|
||||
'interactionStatistic' => array(
|
||||
@@ -532,6 +563,8 @@ class _topic extends \IPS\Content\Controller
|
||||
/* Show topic */
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'topics.css', 'forums' ) );
|
||||
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'topics' )->topic( $topic, $comments, $question, $votes, $nextUnread, $pagination, $topicVotes );
|
||||
|
||||
return $topic;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user