Version 4.6.0
This commit is contained in:
1 parent
f79dcf067a
commit
517a5e1f70
2036 files changed
+110041
-26162
No files matched your search
@@ -90,13 +90,6 @@ class _MarkTopicSolved extends \IPS\Node\Api\GraphQL\NodeMutator
|
||||
if( $args['solved'] )
|
||||
{
|
||||
$topic->toggleSolveComment( $post->pid, TRUE );
|
||||
|
||||
if( $post->author()->member_id != \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
$notification = new \IPS\Notification( \IPS\Application::load( 'core' ), 'best_answer', $topic, array( $post ), array( $post->author()->member_id ) );
|
||||
$notification->recipients->attach( $post->author() );
|
||||
$notification->send();
|
||||
}
|
||||
}
|
||||
else if ( $topic->mapped('solved_comment_id') )
|
||||
{
|
||||
|
||||
@@ -128,7 +128,7 @@ class _Topics
|
||||
$orderBy = 'last_post';
|
||||
}
|
||||
|
||||
$sortBy = "{$orderBy} {$args['orderDir']}";
|
||||
$sortBy = \IPS\forums\Topic::$databaseTable . '.' . \IPS\forums\Topic::$databasePrefix . "{$orderBy} {$args['orderDir']}";
|
||||
$offset = max( $args['offset'], 0 );
|
||||
$limit = min( $args['limit'], 50 );
|
||||
|
||||
|
||||
@@ -229,6 +229,10 @@ class _forums extends \IPS\Node\Api\NodeController
|
||||
$forum->can_view_others = \IPS\Request::i()->can_see_others;
|
||||
}
|
||||
|
||||
return parent::_createOrUpdate( $forum );
|
||||
$forum = parent::_createOrUpdate( $forum );
|
||||
|
||||
unset( \IPS\Data\Store::i()->forumsHavePasswords );
|
||||
|
||||
return $forum;
|
||||
}
|
||||
}
|
||||
@@ -195,6 +195,10 @@ class _topics extends \IPS\Content\Api\ItemController
|
||||
{
|
||||
throw new \IPS\Api\Exception( 'NO_FORUM', '1F294/2', 400 );
|
||||
}
|
||||
if ( !$forum->sub_can_post )
|
||||
{
|
||||
throw new \IPS\Api\Exception( 'NO_PERMISSION', '2F294/C', 403 );
|
||||
}
|
||||
|
||||
/* Get author */
|
||||
if ( $this->member )
|
||||
|
||||
@@ -8,14 +8,22 @@
|
||||
"forums"
|
||||
]
|
||||
},
|
||||
"app=forums&module=forums&controller=forums&do=form": {
|
||||
"app=forums&module=forums&controller=forums": {
|
||||
"lang_key": "menu__forums_forums_forums",
|
||||
"restriction": "forums_manage",
|
||||
"keywords": [
|
||||
"edit forum"
|
||||
]
|
||||
},
|
||||
"app=forums&module=forums&controller=forums&do=form&searchResult=forum_best_answer": {
|
||||
"app=forums&module=forums&controller=forums&searchResult=form_2_allow_anonymous": {
|
||||
"lang_key": "allow_anonymous",
|
||||
"restriction": "forums_manage",
|
||||
"keywords": [
|
||||
"anonymous",
|
||||
"anonymously"
|
||||
]
|
||||
},
|
||||
"app=forums&module=forums&controller=forums&searchResult=forum_best_answer": {
|
||||
"lang_key": "bw_enable_answers_moderator",
|
||||
"restriction": "forums_manage",
|
||||
"keywords": [
|
||||
@@ -495,7 +503,7 @@
|
||||
"saved actions"
|
||||
]
|
||||
},
|
||||
"app=forums&module=forums&controller=savedActions&do=form": {
|
||||
"app=forums&module=forums&controller=savedActions": {
|
||||
"lang_key": "menu__forums_forums_savedActions",
|
||||
"restriction": "savedActions_manage",
|
||||
"keywords": [
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"app_author": "Invision Power Services, Inc.",
|
||||
"app_directory": "forums",
|
||||
"app_protected": 0,
|
||||
"app_website": null,
|
||||
"app_update_check": null
|
||||
"app_website": "",
|
||||
"app_update_check": "",
|
||||
"app_hide_tab": 0
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
<module key="front/forums"><![CDATA[{"default_controller":"index","protected":0,"default":1}]]></module>
|
||||
<task frequency="P0Y0M0DT0H5M0S">archive</task>
|
||||
<task frequency="P0Y0M0DT0H5M0S">unarchive</task>
|
||||
<setting key="archive_last_post_cloud"><![CDATA[{"key":"archive_last_post_cloud","default":"3","report":"full"}]]></setting>
|
||||
<setting key="archive_last_post_cloud"><![CDATA[{"key":"archive_last_post_cloud","default":"5","report":"full"}]]></setting>
|
||||
<setting key="archive_on"><![CDATA[{"key":"archive_on","default":"0","report":"full"}]]></setting>
|
||||
<setting key="archive_remote_sql_database"><![CDATA[{"key":"archive_remote_sql_database","default":"","report":"none"}]]></setting>
|
||||
<setting key="archive_remote_sql_host"><![CDATA[{"key":"archive_remote_sql_host","default":"","report":"none"}]]></setting>
|
||||
@@ -19,6 +19,7 @@
|
||||
<setting key="forums_default_view"><![CDATA[{"key":"forums_default_view","default":"table","report":"full"}]]></setting>
|
||||
<setting key="forums_default_view_choose"><![CDATA[{"key":"forums_default_view_choose","default":"0","report":"full"}]]></setting>
|
||||
<setting key="forums_fluid_pinned"><![CDATA[{"key":"forums_fluid_pinned","default":"1","report":"full"}]]></setting>
|
||||
<setting key="forums_mod_actions_anon"><![CDATA[{"key":"forums_mod_actions_anon","default":"0","report":"full"}]]></setting>
|
||||
<setting key="forums_new_questions"><![CDATA[{"key":"forums_new_questions","default":"0","report":"full"}]]></setting>
|
||||
<setting key="forums_popular_now"><![CDATA[{"key":"forums_popular_now","default":"{\"posts\":\"10\",\"minutes\":\"60\"}","report":"bool"}]]></setting>
|
||||
<setting key="forums_posts_per_page"><![CDATA[{"key":"forums_posts_per_page","default":"25","report":"full"}]]></setting>
|
||||
@@ -37,9 +38,9 @@
|
||||
<widget key="topicFeed"><![CDATA[{"class":"\\IPS\\Widget\\PermissionCache","restrict":[],"default_area":"","allow_reuse":true,"menu_style":"modal","embeddable":true}]]></widget>
|
||||
<widget key="postFeed"><![CDATA[{"class":"\\IPS\\Widget\\PermissionCache","restrict":[],"default_area":"","allow_reuse":true,"menu_style":"modal","embeddable":true}]]></widget>
|
||||
<widget key="poll"><![CDATA[{"class":"\\IPS\\Widget\\PermissionCache","restrict":["sidebar","cms"],"default_area":"","allow_reuse":true,"menu_style":"modal","embeddable":true}]]></widget>
|
||||
<acpsearch key="app=forums&module=forums&controller=forums"><![CDATA[{"lang_key":"menu__forums_forums_forums","restriction":"forums_manage","keywords":["categories","forum","forums"]}]]></acpsearch>
|
||||
<acpsearch key="app=forums&module=forums&controller=forums&do=form"><![CDATA[{"lang_key":"menu__forums_forums_forums","restriction":"forums_manage","keywords":["edit forum"]}]]></acpsearch>
|
||||
<acpsearch key="app=forums&module=forums&controller=forums&do=form&searchResult=forum_best_answer"><![CDATA[{"lang_key":"bw_enable_answers_moderator","restriction":"forums_manage","keywords":["answer","best answer","qa","solved"]}]]></acpsearch>
|
||||
<acpsearch key="app=forums&module=forums&controller=forums"><![CDATA[{"lang_key":"menu__forums_forums_forums","restriction":"forums_manage","keywords":["edit forum"]}]]></acpsearch>
|
||||
<acpsearch key="app=forums&module=forums&controller=forums&searchResult=form_2_allow_anonymous"><![CDATA[{"lang_key":"allow_anonymous","restriction":"forums_manage","keywords":["anonymous","anonymously"]}]]></acpsearch>
|
||||
<acpsearch key="app=forums&module=forums&controller=forums&searchResult=forum_best_answer"><![CDATA[{"lang_key":"bw_enable_answers_moderator","restriction":"forums_manage","keywords":["answer","best answer","qa","solved"]}]]></acpsearch>
|
||||
<acpsearch key="app=forums&module=forums&controller=forums&searchResult=bw_disable_prefixes"><![CDATA[{"lang_key":"bw_disable_prefixes","restriction":"forums_manage","keywords":["can set","can set tag prefixes","tag prefixes"]}]]></acpsearch>
|
||||
<acpsearch key="app=forums&module=forums&controller=forums&searchResult=bw_disable_tagging"><![CDATA[{"lang_key":"bw_disable_tagging","restriction":"forums_manage","keywords":["can use tags","tags","use tags"]}]]></acpsearch>
|
||||
<acpsearch key="app=forums&module=forums&controller=forums&searchResult=form_1_forum_description"><![CDATA[{"lang_key":"forum_description","restriction":"forums_manage","keywords":["category description","forum description"]}]]></acpsearch>
|
||||
@@ -94,8 +95,7 @@
|
||||
<acpsearch key="app=forums&module=forums&controller=forums&subnode=0&parent=2&searchResult=forum_permission_showtopic"><![CDATA[{"lang_key":"forum_permission_showtopic","restriction":"forums_manage","keywords":["read permissions","users without","users without read permissions","without permissions"]}]]></acpsearch>
|
||||
<acpsearch key="app=forums&module=forums&controller=forums&subnode=0&parent=2&searchResult=forum_preview_posts"><![CDATA[{"lang_key":"forum_preview_posts","restriction":"forums_manage","keywords":["must approved","posts approved","posts must approved"]}]]></acpsearch>
|
||||
<acpsearch key="app=forums&module=forums&controller=forums&subnode=0&parent=2&searchResult=forum_sort_key"><![CDATA[{"lang_key":"forum_sort_key","restriction":"forums_manage","keywords":["default sort","default sort order","sort order"]}]]></acpsearch>
|
||||
<acpsearch key="app=forums&module=forums&controller=savedActions"><![CDATA[{"lang_key":"menu__forums_forums_savedActions","restriction":"savedActions_manage","keywords":["multi moderation","multimod","saved actions"]}]]></acpsearch>
|
||||
<acpsearch key="app=forums&module=forums&controller=savedActions&do=form"><![CDATA[{"lang_key":"menu__forums_forums_savedActions","restriction":"savedActions_manage","keywords":["saved actions"]}]]></acpsearch>
|
||||
<acpsearch key="app=forums&module=forums&controller=savedActions"><![CDATA[{"lang_key":"menu__forums_forums_savedActions","restriction":"savedActions_manage","keywords":["saved actions"]}]]></acpsearch>
|
||||
<acpsearch key="app=forums&module=forums&controller=savedActions&searchResult=form_1_mm_forums"><![CDATA[{"lang_key":"mm_forums","restriction":"savedActions_manage","keywords":["multimod forums","settings forums"]}]]></acpsearch>
|
||||
<acpsearch key="app=forums&module=forums&controller=savedActions&searchResult=form_1_mm_title"><![CDATA[{"lang_key":"mm_title","restriction":"savedActions_manage","keywords":["multimod name","name","settings name"]}]]></acpsearch>
|
||||
<acpsearch key="app=forums&module=forums&controller=savedActions&searchResult=form_1_topic_approve"><![CDATA[{"lang_key":"topic_approve","restriction":"savedActions_manage","keywords":["hide","unhide"]}]]></acpsearch>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<a href='{$comment->url()}' style='text-decoration: none;'>{$comment->item()->mapped('title')}</a>
|
||||
</h2>
|
||||
<div style='font-family: "Helvetica Neue", helvetica, sans-serif; line-height: 22px; margin-top: 5px; margin-bottom: 5px; border-left: 3px solid #8c8c8c; padding-left: 15px; font-size: 14px; margin-left: 15px'>
|
||||
{$email->parseTextForEmail( $comment->content(), $email->language )|raw}
|
||||
{$email->parseTextForEmail( $comment->content(), $email->language, ( \IPS\Settings::i()->email_truncate ? 150 : NULL ) )|raw}
|
||||
</div>
|
||||
</td>
|
||||
</tr>]]></template_content_html><template_data>$comment, $email</template_data><template_content_plaintext><![CDATA[{{if $comment->item()->isQuestion()}}{$email->language->addToStack("x_answered_a_question", FALSE, array( 'htmlsprintf' => array( $comment->author()->name ) ) )}{{else}}{$email->language->addToStack("x_replied_to_a_topic", FALSE, array( 'htmlsprintf' => array( $comment->author()->name ) ) )}{{endif}}: {$comment->item()->mapped('title')} ({$comment->url()})
|
||||
@@ -36,7 +36,7 @@
|
||||
{{if $topic->mapped('featured')}} <span style='color: #68a72f; font-weight: bold; font-size: 12px; text-transform: uppercase;'>{$email->language->addToStack("featured", FALSE)}</span>{{endif}}
|
||||
</h2>
|
||||
<div style="font-family: 'Helvetica Neue', helvetica, sans-serif; line-height: 22px; margin-top: 10px; margin-bottom: 10px;">
|
||||
{$email->parseTextForEmail( $topic->content(), $email->language )|raw}
|
||||
{$email->parseTextForEmail( $topic->content(), $email->language, ( \IPS\Settings::i()->email_truncate ? 150 : NULL ) )|raw}
|
||||
</div>
|
||||
<p style="font-family: 'Helvetica Neue', helvetica, sans-serif; margin: 0; font-size: 13px;">
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
"Topics": "IPS\\forums\\extensions\\core\\ContentModeratorPermissions\\Topics"
|
||||
},
|
||||
"FileStorage": {
|
||||
"Icons": "IPS\\forums\\extensions\\core\\FileStorage\\Icons",
|
||||
"Cards": "IPS\\forums\\extensions\\core\\FileStorage\\Cards"
|
||||
"Cards": "IPS\\forums\\extensions\\core\\FileStorage\\Cards",
|
||||
"Icons": "IPS\\forums\\extensions\\core\\FileStorage\\Icons"
|
||||
},
|
||||
"Announcements": {
|
||||
"Forums": "IPS\\forums\\extensions\\core\\Announcements\\Forums"
|
||||
@@ -33,8 +33,15 @@
|
||||
"TopicStarterIds": "IPS\\forums\\extensions\\core\\Queue\\TopicStarterIds",
|
||||
"DeleteLegacyPosts": "IPS\\forums\\extensions\\core\\Queue\\DeleteLegacyPosts",
|
||||
"HiddenFirstPost": "IPS\\forums\\extensions\\core\\Queue\\HiddenFirstPost",
|
||||
"RebuildNewTopicFlag": "IPS\\forums\\extensions\\core\\Queue\\RebuildNewTopicFlag",
|
||||
"RebuildSolvedIndex": "IPS\\forums\\extensions\\core\\Queue\\RebuildSolvedIndex"
|
||||
"RebuildSolvedIndex": "IPS\\forums\\extensions\\core\\Queue\\RebuildSolvedIndex",
|
||||
"RebuildNewTopicFlag": "IPS\\forums\\extensions\\core\\Queue\\RebuildNewTopicFlag"
|
||||
},
|
||||
"MobileNavigation": {
|
||||
"Topics": "IPS\\forums\\extensions\\core\\MobileNavigation\\Topics",
|
||||
"Forums": "IPS\\forums\\extensions\\core\\MobileNavigation\\Forums"
|
||||
},
|
||||
"OverviewStatistics": {
|
||||
"Solved": "IPS\\forums\\extensions\\core\\OverviewStatistics\\Solved"
|
||||
},
|
||||
"FrontNavigation": {
|
||||
"Forums": "IPS\\forums\\extensions\\core\\FrontNavigation\\Forums"
|
||||
@@ -42,10 +49,6 @@
|
||||
"MemberSync": {
|
||||
"Forums": "IPS\\forums\\extensions\\core\\MemberSync\\Forums"
|
||||
},
|
||||
"MobileNavigation": {
|
||||
"Topics": "IPS\\forums\\extensions\\core\\MobileNavigation\\Topics",
|
||||
"Forums": "IPS\\forums\\extensions\\core\\MobileNavigation\\Forums"
|
||||
},
|
||||
"BBCode": {
|
||||
"post": "IPS\\forums\\extensions\\core\\BBCode\\post",
|
||||
"topic": "IPS\\forums\\extensions\\core\\BBCode\\topic",
|
||||
@@ -55,6 +58,9 @@
|
||||
"IndexView": "IPS\\forums\\extensions\\core\\AdvertisementLocations\\IndexView",
|
||||
"TopicView": "IPS\\forums\\extensions\\core\\AdvertisementLocations\\TopicView",
|
||||
"ForumListing": "IPS\\forums\\extensions\\core\\AdvertisementLocations\\ForumListing"
|
||||
},
|
||||
"AchievementAction": {
|
||||
"AnswerMarkedBest": "IPS\\forums\\extensions\\core\\AchievementAction\\AnswerMarkedBest"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<javascript app="forums">
|
||||
<file javascript_app="forums" javascript_location="front" javascript_path="controllers/forum" javascript_name="ips.forum.flow.js" javascript_type="controller" javascript_version="105100" javascript_position="1000100"><![CDATA[/**
|
||||
<file javascript_app="forums" javascript_location="front" javascript_path="controllers/forum" javascript_name="ips.forum.flow.js" javascript_type="controller" javascript_version="106107" javascript_position="1000100"><![CDATA[/**
|
||||
* Invision Community
|
||||
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
||||
*
|
||||
@@ -220,7 +220,7 @@
|
||||
}
|
||||
});
|
||||
}(jQuery, _));]]></file>
|
||||
<file javascript_app="forums" javascript_location="front" javascript_path="controllers/forum" javascript_name="ips.forum.forumList.js" javascript_type="controller" javascript_version="105100" javascript_position="1000100"><![CDATA[/**
|
||||
<file javascript_app="forums" javascript_location="front" javascript_path="controllers/forum" javascript_name="ips.forum.forumList.js" javascript_type="controller" javascript_version="106107" javascript_position="1000100"><![CDATA[/**
|
||||
* Invision Community
|
||||
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
||||
*
|
||||
@@ -234,6 +234,7 @@
|
||||
ips.controller.register('forums.front.forum.forumList', {
|
||||
initialize: function () {
|
||||
this.on( 'click', '[data-action="toggleCategory"]', this.toggleCategory );
|
||||
this.on( 'markedAsRead', this.forumMarkedRead );
|
||||
this.setup();
|
||||
},
|
||||
|
||||
@@ -284,10 +285,21 @@
|
||||
.removeClass('cForumRow_hidden')
|
||||
.removeAttr( 'data-hidden' );
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Event handler for a forum being marked as read
|
||||
* We need to do some extra work for grid-style forums
|
||||
*
|
||||
* @param {event} e Event object
|
||||
* @returns {void}
|
||||
*/
|
||||
forumMarkedRead: function(e) {
|
||||
$( e.target ).closest( '.cForumGrid' ).removeClass('cForumGrid--unread').removeClass('ipsDataItem_unread').addClass('cForumGrid--read');
|
||||
}
|
||||
});
|
||||
}(jQuery, _));]]></file>
|
||||
<file javascript_app="forums" javascript_location="front" javascript_path="controllers/forum" javascript_name="ips.forum.forumPage.js" javascript_type="controller" javascript_version="105100" javascript_position="1000100">/**
|
||||
<file javascript_app="forums" javascript_location="front" javascript_path="controllers/forum" javascript_name="ips.forum.forumPage.js" javascript_type="controller" javascript_version="106107" javascript_position="1000100">/**
|
||||
* Invision Community
|
||||
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
||||
*
|
||||
@@ -346,7 +358,7 @@
|
||||
}
|
||||
});
|
||||
}(jQuery, _));</file>
|
||||
<file javascript_app="forums" javascript_location="front" javascript_path="controllers/forum" javascript_name="ips.forum.hovercard.js" javascript_type="controller" javascript_version="105100" javascript_position="1000100">/**
|
||||
<file javascript_app="forums" javascript_location="front" javascript_path="controllers/forum" javascript_name="ips.forum.hovercard.js" javascript_type="controller" javascript_version="106107" javascript_position="1000100">/**
|
||||
* Invision Community
|
||||
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
||||
*
|
||||
@@ -396,7 +408,7 @@
|
||||
}
|
||||
});
|
||||
}(jQuery, _));</file>
|
||||
<file javascript_app="forums" javascript_location="admin" javascript_path="controllers/settings" javascript_name="ips.settings.archiveRules.js" javascript_type="controller" javascript_version="105100" javascript_position="1000050"><![CDATA[/**
|
||||
<file javascript_app="forums" javascript_location="admin" javascript_path="controllers/settings" javascript_name="ips.settings.archiveRules.js" javascript_type="controller" javascript_version="106107" javascript_position="1000050"><![CDATA[/**
|
||||
* Invision Community
|
||||
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
||||
*
|
||||
@@ -461,7 +473,7 @@
|
||||
});
|
||||
}(jQuery, _));
|
||||
]]></file>
|
||||
<file javascript_app="forums" javascript_location="front" javascript_path="controllers/topic" javascript_name="ips.topic.activity.js" javascript_type="controller" javascript_version="105100" javascript_position="1000050">/**
|
||||
<file javascript_app="forums" javascript_location="front" javascript_path="controllers/topic" javascript_name="ips.topic.activity.js" javascript_type="controller" javascript_version="106107" javascript_position="1000050">/**
|
||||
* Invision Community
|
||||
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
||||
*
|
||||
@@ -493,7 +505,7 @@
|
||||
}
|
||||
});
|
||||
}(jQuery, _));</file>
|
||||
<file javascript_app="forums" javascript_location="front" javascript_path="controllers/topic" javascript_name="ips.topic.answers.js" javascript_type="controller" javascript_version="105100" javascript_position="1000050"><![CDATA[/**
|
||||
<file javascript_app="forums" javascript_location="front" javascript_path="controllers/topic" javascript_name="ips.topic.answers.js" javascript_type="controller" javascript_version="106107" javascript_position="1000050"><![CDATA[/**
|
||||
* Invision Community
|
||||
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
||||
*
|
||||
@@ -633,7 +645,7 @@
|
||||
}
|
||||
});
|
||||
}(jQuery, _));]]></file>
|
||||
<file javascript_app="forums" javascript_location="front" javascript_path="controllers/topic" javascript_name="ips.topic.reply.js" javascript_type="controller" javascript_version="105100" javascript_position="1000050">/**
|
||||
<file javascript_app="forums" javascript_location="front" javascript_path="controllers/topic" javascript_name="ips.topic.reply.js" javascript_type="controller" javascript_version="106107" javascript_position="1000050">/**
|
||||
* Invision Community
|
||||
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
||||
*
|
||||
@@ -661,7 +673,7 @@
|
||||
}
|
||||
});
|
||||
}(jQuery, _));</file>
|
||||
<file javascript_app="forums" javascript_location="front" javascript_path="controllers/topic" javascript_name="ips.topic.view.js" javascript_type="controller" javascript_version="105100" javascript_position="1000050">/**
|
||||
<file javascript_app="forums" javascript_location="front" javascript_path="controllers/topic" javascript_name="ips.topic.view.js" javascript_type="controller" javascript_version="106107" javascript_position="1000050">/**
|
||||
* Invision Community
|
||||
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
||||
*
|
||||
@@ -723,23 +735,4 @@
|
||||
}
|
||||
});
|
||||
}(jQuery, _));</file>
|
||||
<order app="global" path="/dev/js//framework/">templates
|
||||
common/ips.loader.js
|
||||
common/ui
|
||||
common/utils
|
||||
common
|
||||
controllers</order>
|
||||
<order app="global" path="/dev/js//library/">underscore
|
||||
jquery
|
||||
mustache
|
||||
jstz
|
||||
IntersectionObserver
|
||||
Debug.js
|
||||
app.js</order>
|
||||
<order app="global" path="/dev/js//library//jquery">jquery.js
|
||||
jquery-migrate.js
|
||||
jquery.history.js
|
||||
jquery.transform.js</order>
|
||||
<order app="global" path="/dev/js//library//linkify">linkify.min.js
|
||||
linkify-jquery.min.js</order>
|
||||
</javascript>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<language>
|
||||
<app key="forums" version="105100">
|
||||
<app key="forums" version="106107">
|
||||
<word key="__app_forums" js="0">Forums</word>
|
||||
<word key="frontnavigation_forums" js="0">Forums</word>
|
||||
<word key="__indefart_post" js="0">a post in a topic</word>
|
||||
@@ -8,9 +8,13 @@
|
||||
<word key="__indefart_answer" js="0">an answer to a question</word>
|
||||
<word key="__indefart_question" js="0">a question</word>
|
||||
<word key="__defart_post" js="0">post in a topic</word>
|
||||
<word key="__defart_post_plural" js="0">{!#[1:post][?:posts]} in a topic</word>
|
||||
<word key="__defart_topic" js="0">topic</word>
|
||||
<word key="__defart_topic_plural" js="0">{!#[1:topic][?:topics]}</word>
|
||||
<word key="__defart_answer" js="0">answer to a question</word>
|
||||
<word key="__defart_answer_plural" js="0">{!#[1:answer][?:answers]} to a question</word>
|
||||
<word key="__defart_question" js="0">question</word>
|
||||
<word key="__defart_question_plural" js="0">{!#[1:question][?:questions]}</word>
|
||||
<word key="topic_container" js="0">Forum</word>
|
||||
<word key="search_contextual_item_forums" js="0">This Forum</word>
|
||||
<word key="search_contextual_item_topic" js="0">This Topic</word>
|
||||
@@ -81,6 +85,7 @@
|
||||
<word key="can_toggle_item_moderation_topic" js="0">Can enable/disable moderation on topics?</word>
|
||||
<word key="forums" js="0">Forums</word>
|
||||
<word key="forums_sg" js="0">Forum</word>
|
||||
<word key="forums_sg_lc" js="0">forum</word>
|
||||
<word key="forums_add_child" js="0">Create Subforum</word>
|
||||
<word key="forums_add_child_cat" js="0">Create Forum</word>
|
||||
<word key="all_public" js="0">All public</word>
|
||||
@@ -113,7 +118,7 @@
|
||||
<word key="forum_rules_text" js="0">Rules</word>
|
||||
<word key="forum_settings" js="0">Forum Settings</word>
|
||||
<word key="posting_settings" js="0">Posting Settings</word>
|
||||
<word key="forum_allow_poll" js="0">Allow Polls?</word>
|
||||
<word key="forum_allow_poll" js="0">Allow polls?</word>
|
||||
<word key="posts" js="0">Posts</word>
|
||||
<word key="forum_preview_posts" js="0">Posts must be approved?</word>
|
||||
<word key="forum_preview_posts_qa" js="0">Posts must be approved?</word>
|
||||
@@ -121,7 +126,7 @@
|
||||
<word key="forum_preview_posts_questions" js="0">New Questions</word>
|
||||
<word key="forum_preview_posts_posts" js="0">Replies</word>
|
||||
<word key="forum_preview_posts_answers" js="0">Answers</word>
|
||||
<word key="forum_inc_postcount" js="0">Increase Content Counts?</word>
|
||||
<word key="forum_inc_postcount" js="0">Increase content counts?</word>
|
||||
<word key="forum_inc_postcount_desc" js="0">If disabled, the user's total number of content items will not increase when a user posts in this forum. You may want to disable this for forums for posting test messages, etc.</word>
|
||||
<word key="forum_redirect_url" js="0">Redirect URL</word>
|
||||
<word key="forum_redirect_hits" js="0">Redirect Count</word>
|
||||
@@ -173,7 +178,7 @@
|
||||
<word key="edit_forum" js="0">Edit Forum</word>
|
||||
<word key="node_no_parentf" js="0">No Parent</word>
|
||||
<word key="forum_use_feature_color" js="0">Use a Feature Color?</word>
|
||||
<word key="forum_use_feature_color_desc" js="0">A feature color will show the forum title as a badge when used in a description.</word>
|
||||
<word key="forum_use_feature_color_desc" js="0">A feature color will be used in various places such as the forum/category title, forum badges and the forum index.</word>
|
||||
<word key="forum_feature_color" js="0">Feature color</word>
|
||||
<word key="forum_card_image" js="0">Grid Card Image</word>
|
||||
<word key="forum_card_image_desc" js="0">When viewing forums as a grid, your chosen image will appear as the background.</word>
|
||||
@@ -182,6 +187,7 @@
|
||||
<word key="bw_enable_answers__member" js="0">Allow the topic starter to mark solved?</word>
|
||||
<word key="bw_enable_answers__member_desc" js="0">Optionally allow the topic starter to also mark posts as the solution.</word>
|
||||
<word key="rebuilding_starter_ids" js="0">Rebuilding topic starter IDs</word>
|
||||
<word key="chart_forums" js="0">Filter by forums</word>
|
||||
<word key="forums_topic_post" js="0">Forum Posts</word>
|
||||
<word key="forums_topic" js="0">Forum Topics</word>
|
||||
<word key="forums_topic_pl" js="0">Topics</word>
|
||||
@@ -216,6 +222,8 @@
|
||||
<word key="archiving" js="0">Archiving</word>
|
||||
<word key="archiving_blurb" js="0">If you have a very large site, it can be beneficial to reduce the size of the database table storing posts. Archiving topics is an alternative to deleting which allows them to still exist and be viewed as normal, but moves them to a separate database table. Archived topics cannot be posted in or edited, and will not show in search results. You can unarchive topics after they've been archived if you change your mind.</word>
|
||||
<word key="archiving_blurb_cloud" js="0"><![CDATA[Archiving older <strong>non-pinned</strong> and <strong>non-featured</strong> topics keeps your community running smoothly. Archived topics cannot be posted in or edited, and will not show in search results. You can unarchive topics after they've been archived if you change your mind.]]></word>
|
||||
<word key="archiving_blurb_cloud_notforced" js="0"><![CDATA[Archiving older <strong>non-pinned</strong> and <strong>non-featured</strong> topics on larger sites helps keep your community running smoothly. Archived topics cannot be posted in or edited, and will not show in search results. When your community reaches a certain size, archiving of older topics will be required.]]></word>
|
||||
<word key="disable_cloud_archiving" js="0">Disable archiving</word>
|
||||
<word key="archive_topics_where" js="0"><![CDATA[Archive topics when <em>all</em> of the following conditions are true...]]></word>
|
||||
<word key="archive_topic_forums" js="0">In forums</word>
|
||||
<word key="archive_topic_not_forums" js="0">In forums</word>
|
||||
@@ -458,8 +466,6 @@
|
||||
<word key="go_to_forum" js="0">Go to %s</word>
|
||||
<word key="go_back_to_forum" js="0">Go to topic listing</word>
|
||||
<word key="go_back_to_qa_forum" js="0">Go to question listing</word>
|
||||
<word key="first_unread_post" js="0">Go to first unread post</word>
|
||||
<word key="get_last_post" js="0">Go to last post</word>
|
||||
<word key="topic_is_archived" js="0">Archived</word>
|
||||
<word key="topic_archived_desc" js="0">This topic is now archived and is closed to further replies.</word>
|
||||
<word key="count_topics_in_forum" js="0">{# [1:topic][?:topics] in this forum}</word>
|
||||
@@ -519,6 +525,9 @@
|
||||
<word key="forums_topic_list_snippet" js="0">Expanded View: Show topics with a preview of the post</word>
|
||||
<word key="forums_topic_list_list" js="0">Condensed View: Show topics as a list</word>
|
||||
<word key="topic_snippet_last_reply" js="0"><![CDATA[Last reply by %s, <a href='%s' title='Go to last post'>%s</a>]]></word>
|
||||
<word key="topic_posted_in_groups" js="0">Posts by %s</word>
|
||||
<word key="filter_hidden_topics" js="0">Hidden Topics</word>
|
||||
<word key="filter_hidden_posts_in_topics" js="0">Topics With Hidden Posts</word>
|
||||
<word key="saved_actions" js="0">Saved Actions</word>
|
||||
<word key="saved_actions_sg" js="0">Saved Action</word>
|
||||
<word key="mm_title" js="0">Name</word>
|
||||
@@ -592,6 +601,12 @@
|
||||
<word key="stats_posts_tab_byforum" js="0">New Posts By Forum</word>
|
||||
<word key="stats_posts_title" js="0">New posts by time period</word>
|
||||
<word key="stats_posts_title_byforum" js="0">New posts by forum</word>
|
||||
<word key="stats_percentagesolved" js="0">Percentage Solved</word>
|
||||
<word key="stats_percentagesolved_desc" js="0">The percent of topics solved compared to the total number of topics posted</word>
|
||||
<word key="stats_solved_tooltip" js="0">%s topics were marked solved out of %s total topics</word>
|
||||
<word key="stats_solved_tooltip_prev" js="0">%s topics were marked solved out of %s total topics for a solution rate of %s%%</word>
|
||||
<word key="stats_averagetimesolved" js="0">Average Time To Solution</word>
|
||||
<word key="stats_averagetimesolved_desc" js="0">The average amount of time that passed between the time the topic was started and the time a solution was marked</word>
|
||||
<word key="widget_feed_container_topic" js="0">Forums</word>
|
||||
<word key="block_topicFeed_title" js="0">Topics</word>
|
||||
<word key="block_postFeed_title" js="0">Posts</word>
|
||||
@@ -664,6 +679,11 @@
|
||||
<word key="forums_topics_show_meta" js="0">Show</word>
|
||||
<word key="forums_topic_show_meta_time" js="0">Large time gaps between posts</word>
|
||||
<word key="forums_topic_show_meta_moderation" js="0">Moderation events between posts</word>
|
||||
<word key="forums_topic_show_meta_moderation_desc" js="0"><![CDATA[You can specify which groups can see moderation events in the <a href='{internal.app=core&module=members&controller=groups}'>Group Settings</a>]]></word>
|
||||
<word key="forums_mod_actions_anon" js="0">Show moderator name alongside moderation events</word>
|
||||
<word key="forums_mod_actions_anon_desc" js="0">If disabled, the name of the moderator who performed the action will be hidden from other users who do not have permission to moderate within the forum.</word>
|
||||
<word key="404_forums_topic" js="0">We could not find that topic.</word>
|
||||
<word key="403_forums_topic" js="0">You do not have permission to view this topic.</word>
|
||||
<word key="mobilenavigation_Topics" js="0">All Topics</word>
|
||||
<word key="mobilenavigation_Forums" js="0">Forums</word>
|
||||
<word key="app_forums" js="0">Forums</word>
|
||||
@@ -702,6 +722,17 @@
|
||||
<word key="app_topic_restricted_cannot_comment" js="0">Your account is currently restricted from posting.</word>
|
||||
<word key="app_topic_unacknowledged_warning_cannot_post" js="0">You have received a warning that you must acknowledge before being able to post.</word>
|
||||
<word key="app_topic_member_exceeded_posts_per_day" js="0">You have reached the maximum number posts you can make per day.</word>
|
||||
<word key="AchievementAction__AnswerMarkedBest" js="0">Post is marked as the best answer</word>
|
||||
<word key="achievement_filter_AnswerMarkedBest_forum" js="0">Add a location condition</word>
|
||||
<word key="achievement_filter_AnswerMarkedBest_forum_prefix" js="0">The question is in the forum</word>
|
||||
<word key="achievement_filter_AnswerMarkedBest_poster" js="0">To the user who posted the answer</word>
|
||||
<word key="achievement_filter_AnswerMarkedBest_asker" js="0">To the user who posted the original question</word>
|
||||
<word key="achievement_filter_AnswerMarkedBest_nth" js="0">Add a milestone condition</word>
|
||||
<word key="achievement_filter_AnswerMarkedBest_nth_suffix" js="0">th time having a post in that forum marked as the best answer</word>
|
||||
<word key="AchievementAction__AnswerMarkedBest_log_subject" js="0">Answer given to %s marked as the best answer</word>
|
||||
<word key="AchievementAction__AnswerMarkedBest_log_other" js="0">Question %s had an answer marked as the best answer</word>
|
||||
<word key="AchievementAction__AnswerMarkedBest_log_deleted" js="0">a deleted question</word>
|
||||
<word key="AchievementAction__AnswerMarkedBest_title" js="0">Best answer</word>
|
||||
<word key="forumMarkedRead" js="1">Forum marked as read</word>
|
||||
<word key="topicMarkedRead" js="1">Topic marked as read</word>
|
||||
<word key="js_num_topic_posts" js="1">{# [1:post][?:posts]} in this topic</word>
|
||||
|
||||
@@ -645,6 +645,30 @@
|
||||
"unsigned": false,
|
||||
"values": [],
|
||||
"zerofill": false
|
||||
},
|
||||
"allow_anonymous": {
|
||||
"name": "allow_anonymous",
|
||||
"type": "TINYINT",
|
||||
"length": null,
|
||||
"decimals": null,
|
||||
"values": null,
|
||||
"allow_null": false,
|
||||
"default": "0",
|
||||
"comment": "",
|
||||
"unsigned": true,
|
||||
"auto_increment": false
|
||||
},
|
||||
"last_poster_anon": {
|
||||
"name": "last_poster_anon",
|
||||
"type": "TINYINT",
|
||||
"length": null,
|
||||
"decimals": null,
|
||||
"values": null,
|
||||
"allow_null": true,
|
||||
"default": "0",
|
||||
"comment": "",
|
||||
"unsigned": true,
|
||||
"auto_increment": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
@@ -1290,6 +1314,30 @@
|
||||
"comment": "",
|
||||
"unsigned": true,
|
||||
"auto_increment": false
|
||||
},
|
||||
"is_anon": {
|
||||
"name": "is_anon",
|
||||
"type": "TINYINT",
|
||||
"length": null,
|
||||
"decimals": null,
|
||||
"values": null,
|
||||
"allow_null": false,
|
||||
"default": "0",
|
||||
"comment": "",
|
||||
"unsigned": true,
|
||||
"auto_increment": false
|
||||
},
|
||||
"last_poster_anon": {
|
||||
"name": "last_poster_anon",
|
||||
"type": "TINYINT",
|
||||
"length": null,
|
||||
"decimals": null,
|
||||
"values": null,
|
||||
"allow_null": true,
|
||||
"default": "0",
|
||||
"comment": "",
|
||||
"unsigned": true,
|
||||
"auto_increment": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[
|
||||
{
|
||||
"key": "archive_last_post_cloud",
|
||||
"default": "3",
|
||||
"default": "5",
|
||||
"report": "full"
|
||||
},
|
||||
{
|
||||
@@ -69,6 +69,11 @@
|
||||
"default": "1",
|
||||
"report": "full"
|
||||
},
|
||||
{
|
||||
"key": "forums_mod_actions_anon",
|
||||
"default": "0",
|
||||
"report": "full"
|
||||
},
|
||||
{
|
||||
"key": "forums_new_questions",
|
||||
"default": "0",
|
||||
|
||||
+568
-310
File diff suppressed because it is too large.
Load diff
@@ -315,6 +315,7 @@
|
||||
"104067": "4.4.10",
|
||||
"104068": "4.4.10",
|
||||
"104069": "4.4.10",
|
||||
"104070": "4.4.11",
|
||||
"105013": "4.5.0 Beta 1",
|
||||
"105014": "4.5.0 Beta 1",
|
||||
"105015": "4.5.0 Beta 2",
|
||||
@@ -335,5 +336,42 @@
|
||||
"105030": "4.5.0 Beta 11",
|
||||
"105031": "4.5.0 Beta 11",
|
||||
"105032": "4.5.0 Beta 12",
|
||||
"105100": "4.5.0"
|
||||
"105100": "4.5.0",
|
||||
"105101": "4.5.0",
|
||||
"105102": "4.5.1 Beta 1",
|
||||
"105103": "4.5.1 Beta 1",
|
||||
"105104": "4.5.1 Beta 2",
|
||||
"105105": "4.5.1 Beta 3",
|
||||
"105106": "4.5.1",
|
||||
"105107": "4.5.2",
|
||||
"105108": "4.5.2",
|
||||
"105109": "4.5.2",
|
||||
"105110": "4.5.2",
|
||||
"105111": "4.5.2",
|
||||
"105112": "4.5.3",
|
||||
"105113": "4.5.3",
|
||||
"105114": "4.5.3",
|
||||
"105115": "4.5.3",
|
||||
"105116": "4.5.4",
|
||||
"105117": "4.5.4",
|
||||
"105118": "4.5.4",
|
||||
"105119": "4.5.4",
|
||||
"105120": "4.5.4",
|
||||
"105121": "4.5.4",
|
||||
"105122": "4.5.4",
|
||||
"105123": "4.5.4",
|
||||
"105124": "4.5.4.1",
|
||||
"105125": "4.5.4.2",
|
||||
"105126": "4.5.4.2",
|
||||
"105127": "4.5.4.2",
|
||||
"105128": "4.5.4.2",
|
||||
"105129": "4.5.4.2",
|
||||
"105130": "4.5.4.2",
|
||||
"106100": "4.6.0 Beta 1",
|
||||
"106101": "4.6.0 Beta 1.1",
|
||||
"106103": "4.6.0 Beta 2",
|
||||
"106104": "4.6.0 Beta 3",
|
||||
"106105": "4.6.0 Beta 3.1",
|
||||
"106106": "4.6.0 Beta 4",
|
||||
"106107": "4.6.0"
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Achievement Action Extension: Answer a member in a Q&A Forum is marked as the best answer
|
||||
* @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/
|
||||
* @subpackage Forums
|
||||
* @since 18 Feb 2021
|
||||
*/
|
||||
|
||||
namespace IPS\forums\extensions\core\AchievementAction;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Achievement Action Extension: Answer a member in a Q&A Forum is marked as the best answer
|
||||
*/
|
||||
class _AnswerMarkedBest extends \IPS\core\Achievements\Actions\AbstractAchievementAction
|
||||
{
|
||||
/**
|
||||
* Get filter form elements
|
||||
*
|
||||
* @param array|NULL $filters Current filter values (if editing)
|
||||
* @param \IPS\Http\Url $url The URL the form is being shown on
|
||||
* @return array
|
||||
*/
|
||||
public function filters( ?array $filters, \IPS\Http\Url $url ): array
|
||||
{
|
||||
return [
|
||||
'nodes' => new \IPS\Helpers\Form\Node( 'achievement_filter_AnswerMarkedBest_forum', ( $filters and isset( $filters['nodes'] ) and $filters['nodes'] ) ? $filters['nodes'] : NULL, FALSE, [
|
||||
'url' => $url,
|
||||
'class' => 'IPS\forums\Forum',
|
||||
'showAllNodes' => TRUE,
|
||||
'multiple' => TRUE,
|
||||
'permissionCheck' => function( $forum ) {
|
||||
return $forum->forums_bitoptions['bw_enable_answers'];
|
||||
}
|
||||
], NULL, \IPS\Member::loggedIn()->language()->addToStack('achievement_filter_AnswerMarkedBest_forum_prefix') ),
|
||||
'milestone' => new \IPS\Helpers\Form\Number( 'achievement_filter_AnswerMarkedBest_nth', ( $filters and isset( $filters['milestone'] ) and $filters['milestone'] ) ? $filters['milestone'] : 0, FALSE, [], NULL, \IPS\Member::loggedIn()->language()->addToStack('achievement_filter_nth_their'), \IPS\Member::loggedIn()->language()->addToStack('achievement_filter_AnswerMarkedBest_nth_suffix') )
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Format filter form values
|
||||
*
|
||||
* @param array $values The values from the form
|
||||
* @return array
|
||||
*/
|
||||
public function formatFilterValues( array $values ): array
|
||||
{
|
||||
$return = [];
|
||||
if ( isset( $values['achievement_filter_AnswerMarkedBest_forum'] ) )
|
||||
{
|
||||
$return['nodes'] = array_keys( $values['achievement_filter_AnswerMarkedBest_forum'] );
|
||||
}
|
||||
if ( isset( $values['achievement_filter_AnswerMarkedBest_nth'] ) )
|
||||
{
|
||||
$return['milestone'] = $values['achievement_filter_AnswerMarkedBest_nth'];
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Work out if the filters applies for a given action
|
||||
*
|
||||
* Important note for milestones: consider the context. This method is called by \IPS\Member::achievementAction(). If your code
|
||||
* calls that BEFORE making its change in the database (or there is read/write separation), you will need to add
|
||||
* 1 to the value being considered for milestones
|
||||
*
|
||||
* @param \IPS\Member $subject The subject member
|
||||
* @param array $filters The value returned by formatFilterValues()
|
||||
* @param mixed $extra Any additional information about what is happening (e.g. if a post is being made: the post object)
|
||||
* @return bool
|
||||
*/
|
||||
public function filtersMatch( \IPS\Member $subject, array $filters, $extra = NULL ): bool
|
||||
{
|
||||
if ( isset( $filters['nodes'] ) and !\in_array( $extra->container()->_id, $filters['nodes'] ) )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( isset( $filters['milestone'] ) )
|
||||
{
|
||||
$where = [
|
||||
[ 'member_id=? AND app=?', $extra->author()->member_id, 'forums' ],
|
||||
];
|
||||
if ( isset( $filters['nodes'] ) )
|
||||
{
|
||||
$where[] = [ \IPS\Db::i()->in( 'forum_id', $filters['nodes'] ) ];
|
||||
}
|
||||
$query = \IPS\Db::i()->select( 'COUNT(*)', 'core_solved_index', $where );
|
||||
if ( isset( $filters['nodes'] ) )
|
||||
{
|
||||
$query->join( 'forums_topics', 'core_solved_index.item_id=forums_topics.tid' );
|
||||
}
|
||||
if ( ( $query->first() + 1 ) < $filters['milestone'] )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the labels for the people this action might give awards to
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function awardOptions(): array
|
||||
{
|
||||
return [
|
||||
'subject' => 'achievement_filter_AnswerMarkedBest_poster',
|
||||
'other' => 'achievement_filter_AnswerMarkedBest_asker'
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "other" people we need to award =stuff to
|
||||
*
|
||||
* @param mixed $extra Any additional information about what is happening (e.g. if a post is being made: the post object)
|
||||
* @return array
|
||||
*/
|
||||
public function awardOther( $extra = NULL ): array
|
||||
{
|
||||
return [ $extra->item()->author() ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get identifier to prevent the member being awarded points for the same action twice
|
||||
* Must be unique within within of this domain, must not exceed 32 chars.
|
||||
*
|
||||
* @param \IPS\Member $subject The subject member
|
||||
* @param mixed $extra Any additional information about what is happening (e.g. if a post is being made: the post object)
|
||||
* @return string
|
||||
*/
|
||||
public function identifier( \IPS\Member $subject, $extra = NULL ): string
|
||||
{
|
||||
return (string) $extra->pid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a description for this action to show in the log
|
||||
*
|
||||
* @param string $identifier The identifier as returned by identifier()
|
||||
* @param array $actor If the member was the "subject", "other", or both
|
||||
* @return string
|
||||
*/
|
||||
public function logRow( string $identifier, array $actor ): string
|
||||
{
|
||||
$sprintf = [];
|
||||
try
|
||||
{
|
||||
$post = \IPS\forums\Topic\Post::load( $identifier );
|
||||
$sprintf = [ 'htmlsprintf' => [
|
||||
\IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->basicUrl( $post->url(), TRUE, $post->item()->title, FALSE )
|
||||
] ];
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
$sprintf = [ 'sprintf' => [ \IPS\Member::loggedIn()->language()->addToStack('AchievementAction__AnswerMarkedBest_log_deleted') ] ];
|
||||
}
|
||||
|
||||
if ( \in_array( 'subject', $actor ) )
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack( 'AchievementAction__AnswerMarkedBest_log_subject', FALSE, $sprintf );
|
||||
}
|
||||
else
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack( 'AchievementAction__AnswerMarkedBest_log_other', FALSE, $sprintf );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get "description" for rule
|
||||
*
|
||||
* @param \IPS\core\Achievements\Rule $rule The rule
|
||||
* @return string|null
|
||||
*/
|
||||
public function ruleDescription( \IPS\core\Achievements\Rule $rule ): ?string
|
||||
{
|
||||
$conditions = [];
|
||||
if ( isset( $rule->filters['milestone'] ) )
|
||||
{
|
||||
$conditions[] = \IPS\Member::loggedIn()->language()->addToStack( 'achievements_title_filter_milestone', FALSE, [
|
||||
'htmlsprintf' => [
|
||||
\IPS\Theme::i()->getTemplate( 'achievements' )->ruleDescriptionBadge( 'milestone', \IPS\Member::loggedIn()->language()->addToStack( 'achievements_title_filter_milestone_nth', FALSE, [ 'pluralize' => [ $rule->filters['milestone'] ] ] ) )
|
||||
],
|
||||
'sprintf' => \IPS\Member::loggedIn()->language()->addToStack( 'best_answer_post', FALSE, [ 'strtolower' => TRUE ] )
|
||||
] );
|
||||
}
|
||||
if ( isset( $rule->filters['nodes'] ) )
|
||||
{
|
||||
$forumNames = [];
|
||||
foreach ( $rule->filters['nodes'] as $id )
|
||||
{
|
||||
try
|
||||
{
|
||||
$forumNames[] = \IPS\forums\Forum::load( $id )->_title;
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) {}
|
||||
}
|
||||
if ( $forumNames )
|
||||
{
|
||||
$conditions[] = \IPS\Member::loggedIn()->language()->addToStack( 'achievements_title_filter_location', FALSE, [
|
||||
'htmlsprintf' => [
|
||||
\IPS\Theme::i()->getTemplate( 'achievements' )->ruleDescriptionBadge( 'location',
|
||||
\count( $forumNames ) === 1 ? $forumNames[0] : \IPS\Member::loggedIn()->language()->addToStack( 'achievements_title_filter_location_val', FALSE, [ 'sprintf' => [
|
||||
\count( $forumNames ),
|
||||
\IPS\Member::loggedIn()->language()->addToStack( \IPS\forum\Forum::$nodeTitle, FALSE, [ 'strtolower' => TRUE ] )
|
||||
] ] ),
|
||||
\count( $forumNames ) === 1 ? NULL : $forumNames
|
||||
)
|
||||
],
|
||||
] );
|
||||
}
|
||||
}
|
||||
|
||||
return \IPS\Theme::i()->getTemplate( 'achievements' )->ruleDescription(
|
||||
\IPS\Member::loggedIn()->language()->addToStack( 'AchievementAction__AnswerMarkedBest_title' ),
|
||||
$conditions
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get rebuild data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static public function rebuildData()
|
||||
{
|
||||
return [ [
|
||||
'table' => 'core_solved_index',
|
||||
'pkey' => 'id',
|
||||
'date' => 'solved_date',
|
||||
'where' => [ [ 'app=?', 'forums' ] ],
|
||||
] ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the rebuild row
|
||||
*
|
||||
* @param array $row Row from database
|
||||
* @param array $data Data collected when starting rebuild [table, pkey...]
|
||||
* @return void
|
||||
*/
|
||||
public static function rebuildRow( $row, $data )
|
||||
{
|
||||
$post = \IPS\forums\Topic\Post::load( $row['comment_id'] );
|
||||
$post->author()->achievementAction( 'forums', 'AnswerMarkedBest', $post, \IPS\DateTime::ts( $row[ $data['date'] ] ) );
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,8 @@ class _Topics
|
||||
{
|
||||
$return['can_read_all_topics'] = 'YesNo';
|
||||
}
|
||||
if ( \IPS\Db::i()->select( 'COUNT(*)', 'forums_forums', \IPS\Db::i()->bitwiseWhere( \IPS\forums\Forum::$bitOptions['forums_bitoptions'], 'bw_enable_answers' ) )->first() )
|
||||
|
||||
if ( \IPS\Db::i()->select( 'COUNT(*)', 'forums_forums', '(' . \IPS\Db::i()->bitwiseWhere( \IPS\forums\Forum::$bitOptions['forums_bitoptions'], 'bw_enable_answers' ) . ') OR ( ' . \IPS\Db::i()->bitwiseWhere( \IPS\forums\Forum::$bitOptions['forums_bitoptions'], 'bw_enable_answers_moderator' ) . ' )' )->first() )
|
||||
{
|
||||
$return['can_set_best_answer'] = 'YesNo';
|
||||
}
|
||||
@@ -70,10 +71,10 @@ class _Topics
|
||||
*/
|
||||
public function onChange( $moderator, $changed )
|
||||
{
|
||||
if ( $changed === '*' or array_key_exists( 'can_read_all_topics', $changed ) )
|
||||
if ( $changed === '*' or array_key_exists( 'can_read_all_topics', $changed ) OR array_key_exists( 'forums', $changed ) )
|
||||
{
|
||||
$deleteFirst = TRUE;
|
||||
if ( $changed === '*' or $changed['can_read_all_topics'] == true )
|
||||
if ( $changed === '*' or !empty( $changed['can_read_all_topics'] ) )
|
||||
{
|
||||
$deleteFirst = FALSE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,249 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Overview statistics extension: Solved
|
||||
* @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
|
||||
* @subpackage Forums
|
||||
* @since 01 Dec 2020
|
||||
*/
|
||||
|
||||
namespace IPS\forums\extensions\core\OverviewStatistics;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Overview statistics extension: Solved
|
||||
*/
|
||||
class _Solved
|
||||
{
|
||||
/**
|
||||
* @brief Which statistics page (activity or user)
|
||||
*/
|
||||
public $page = 'activity';
|
||||
|
||||
/**
|
||||
* Return the sub-block keys
|
||||
*
|
||||
* @note This is designed to allow one class to support multiple blocks, for instance using the ContentRouter to generate blocks.
|
||||
* @return array
|
||||
*/
|
||||
public function getBlocks()
|
||||
{
|
||||
return array( 'percentagesolved', 'averagetimesolved' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return block details (title and description)
|
||||
*
|
||||
* @param string|NULL $subBlock The subblock we are loading as returned by getBlocks()
|
||||
* @return array
|
||||
*/
|
||||
public function getBlockDetails( $subBlock = NULL )
|
||||
{
|
||||
switch( $subBlock )
|
||||
{
|
||||
case 'percentagesolved':
|
||||
return array( 'app' => 'forums', 'title' => 'stats_percentagesolved', 'description' => 'stats_percentagesolved_desc', 'refresh' => 60, 'form' => true );
|
||||
break;
|
||||
|
||||
case 'averagetimesolved':
|
||||
return array( 'app' => 'forums', 'title' => 'stats_averagetimesolved', 'description' => 'stats_averagetimesolved_desc', 'refresh' => 60, 'form' => true );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the block HTML to show
|
||||
*
|
||||
* @param array|NULL $dateRange NULL for all time, or an array with 'start' and 'end' \IPS\DateTime objects to restrict to
|
||||
* @param string|NULL $subBlock The subblock we are loading as returned by getBlocks()
|
||||
* @return string
|
||||
*/
|
||||
public function getBlock( $dateRange = NULL, $subBlock = NULL )
|
||||
{
|
||||
/* Make sure someone isn't trying to manipulate the request or do something weird */
|
||||
if( !\in_array( $subBlock, $this->getBlocks() ) )
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
$value = 0;
|
||||
$previousValue = 0;
|
||||
$nodeNames = array();
|
||||
|
||||
/* Build where clause in the event we are filtering */
|
||||
$where = array();
|
||||
$previousWhere = NULL;
|
||||
|
||||
if( $dateRange !== NULL )
|
||||
{
|
||||
if( \is_array( $dateRange ) )
|
||||
{
|
||||
$where = array(
|
||||
array( 'start_date > ?', $dateRange['start']->getTimestamp() ),
|
||||
array( 'start_date < ?', $dateRange['end']->getTimestamp() ),
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$currentDate = new \IPS\DateTime;
|
||||
$interval = NULL;
|
||||
|
||||
switch( $dateRange )
|
||||
{
|
||||
case '7':
|
||||
$interval = new \DateInterval( 'P7D' );
|
||||
break;
|
||||
|
||||
case '30':
|
||||
$interval = new \DateInterval( 'P1M' );
|
||||
break;
|
||||
|
||||
case '90':
|
||||
$interval = new \DateInterval( 'P3M' );
|
||||
break;
|
||||
|
||||
case '180':
|
||||
$interval = new \DateInterval( 'P6M' );
|
||||
break;
|
||||
|
||||
case '365':
|
||||
$interval = new \DateInterval( 'P1Y' );
|
||||
break;
|
||||
}
|
||||
|
||||
$initialTimestamp = $currentDate->sub( $interval )->getTimestamp();
|
||||
$where = array( array( 'start_date > ?', $initialTimestamp ) );
|
||||
$previousWhere = array( array( 'start_date BETWEEN ? AND ?', $currentDate->sub( $interval )->getTimestamp(), $initialTimestamp ) );
|
||||
}
|
||||
}
|
||||
else if ( $dateRange === NULL and isset( \IPS\Request::i()->nodes ) and \IPS\Request::i()->nodes )
|
||||
{
|
||||
$where = array( array( \IPS\Db::i()->in( 'forum_id', explode( ',', \IPS\Request::i()->nodes ) ) ) );
|
||||
}
|
||||
|
||||
$where[] = array( \IPS\Db::i()->in( 'forum_id', iterator_to_array( \IPS\Db::i()->select( 'id', 'forums_forums', '(' . \IPS\Db::i()->bitwiseWhere( \IPS\forums\Forum::$bitOptions['forums_bitoptions'], 'bw_enable_answers' ) . ') OR ( ' . \IPS\Db::i()->bitwiseWhere( \IPS\forums\Forum::$bitOptions['forums_bitoptions'], 'bw_enable_answers_moderator' ) . ' )' ) ) ) );
|
||||
|
||||
if( \IPS\Request::i()->nodes )
|
||||
{
|
||||
foreach( explode( ',', \IPS\Request::i()->nodes ) as $nodeId )
|
||||
{
|
||||
$nodeNames[] = \IPS\forums\Forum::load( $nodeId )->_title;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the current and previous values */
|
||||
switch( $subBlock )
|
||||
{
|
||||
case 'percentagesolved':
|
||||
$total = \IPS\Db::i()->select( 'COUNT(*)', 'forums_topics', $this->_modifyWhereClause( $where ) )->first();
|
||||
$solved = \IPS\Db::i()->select( 'COUNT(*)', 'forums_topics', array_merge( $this->_modifyWhereClause( $where ), array( array( 'core_solved_index.id IS NOT NULL' ) ) ) )->join( 'core_solved_index', "core_solved_index.app='forums' AND core_solved_index.item_id=forums_topics.tid")->first();
|
||||
|
||||
$value = $total ? round( $solved / $total * 100, 2 ) : 0;
|
||||
|
||||
$previousTotal = $previousSolved = NULL;
|
||||
|
||||
if( $previousWhere !== NULL )
|
||||
{
|
||||
$previousTotal = \IPS\Db::i()->select( 'COUNT(*)', 'forums_topics', $this->_modifyWhereClause( $previousWhere ) )->first();
|
||||
$previousSolved = \IPS\Db::i()->select( 'COUNT(*)', 'forums_topics', array_merge( $this->_modifyWhereClause( $previousWhere ), array( array( 'core_solved_index.id IS NOT NULL' ) ) ) )->join( 'core_solved_index', "core_solved_index.app='forums' AND core_solved_index.item_id=forums_topics.tid")->first();
|
||||
|
||||
$previousValue = $previousTotal ? round( $previousSolved / $previousTotal * 100, 2 ) : 0;
|
||||
}
|
||||
|
||||
return \IPS\Theme::i()->getTemplate( 'stats', 'forums' )->solvedPercentage( $value, $total, $solved, $previousValue, $previousTotal, $previousSolved, $nodeNames );
|
||||
break;
|
||||
|
||||
case 'averagetimesolved':
|
||||
$value = \IPS\Db::i()->select( 'AVG(core_solved_index.solved_date-forums_topics.start_date)', 'forums_topics', array_merge( $this->_modifyWhereClause( $where ), array( array( 'core_solved_index.id IS NOT NULL' ) ) ) )->join( 'core_solved_index', "core_solved_index.app='forums' AND core_solved_index.item_id=forums_topics.tid")->first();
|
||||
|
||||
if( $previousWhere !== NULL )
|
||||
{
|
||||
$previousValue = \IPS\Db::i()->select( 'AVG(core_solved_index.solved_date-forums_topics.start_date)', 'forums_topics', array_merge( $this->_modifyWhereClause( $previousWhere ), array( array( 'core_solved_index.id IS NOT NULL' ) ) ) )->join( 'core_solved_index', "core_solved_index.app='forums' AND core_solved_index.item_id=forums_topics.tid")->first();
|
||||
}
|
||||
|
||||
return \IPS\Theme::i()->getTemplate( 'stats', 'forums' )->timeToSolved( $value, $previousValue, $nodeNames );
|
||||
break;
|
||||
}
|
||||
|
||||
return \IPS\Theme::i()->getTemplate( 'stats', 'forums' )->solvedPercentage( $values, $previousValues, $nodeNames );
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the where clause to apply other filters
|
||||
*
|
||||
* @param array $where Current where clause
|
||||
* @return array
|
||||
*/
|
||||
protected function _modifyWhereClause( $where )
|
||||
{
|
||||
$where[] = array( \IPS\Db::i()->in( 'approved', array( -2, -3 ), TRUE ) );
|
||||
|
||||
$where = array_merge( $where, \IPS\forums\Topic::overviewStatisticsWhere() );
|
||||
|
||||
if( \IPS\Request::i()->nodes )
|
||||
{
|
||||
$where[] = array( \IPS\Db::i()->in( 'forum_id', explode( ',', \IPS\Request::i()->nodes ) ) );
|
||||
}
|
||||
|
||||
return $where;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return block filter form, or the updated block result upon submit
|
||||
*
|
||||
* @param string|NULL $subBlock The subblock we are loading as returned by getBlocks()
|
||||
* @return array
|
||||
*/
|
||||
public function getBlockForm( $subBlock = NULL )
|
||||
{
|
||||
/* Make sure someone isn't trying to manipulate the request or do something weird */
|
||||
if( !\in_array( $subBlock, $this->getBlocks() ) )
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->attributes['data-controller'] = 'core.admin.stats.nodeFilters';
|
||||
$form->attributes['data-block'] = \IPS\Request::i()->blockKey;
|
||||
$form->attributes['data-subblock'] = $subBlock;
|
||||
$form->add( new \IPS\Helpers\Form\Node( \IPS\forums\Forum::$nodeTitle, NULL, TRUE, array( 'class' => '\IPS\forums\Forum', 'multiple' => TRUE, 'clubs' => FALSE ) ) );
|
||||
|
||||
if( $values = $form->values() )
|
||||
{
|
||||
$dateFilters = NULL;
|
||||
|
||||
if( \IPS\Request::i()->range )
|
||||
{
|
||||
$dateFilters = \IPS\Request::i()->range;
|
||||
}
|
||||
elseif( \IPS\Request::i()->start )
|
||||
{
|
||||
try
|
||||
{
|
||||
$timezone = \IPS\Member::loggedIn()->timezone ? new \DateTimeZone( \IPS\Member::loggedIn()->timezone ) : NULL;
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
$timezone = NULL;
|
||||
}
|
||||
|
||||
$dateFilters = array(
|
||||
'start' => new \IPS\DateTime( \IPS\Helpers\Form\Date::_convertDateFormat( \IPS\Request::i()->start ), $timezone ),
|
||||
'end' => new \IPS\DateTime( \IPS\Helpers\Form\Date::_convertDateFormat( \IPS\Request::i()->end ), $timezone )
|
||||
);
|
||||
}
|
||||
|
||||
return $this->getBlock( $dateFilters, $subblock );
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
}
|
||||
@@ -664,8 +664,13 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
'options' => array(
|
||||
'time' => 'forums_topic_show_meta_time',
|
||||
'moderation' => 'forums_topic_show_meta_moderation'
|
||||
),
|
||||
'toggles' => array(
|
||||
'moderation' => array( 'forums_mod_actions_anon' )
|
||||
) ) ) );
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'forums_mod_actions_anon', !\IPS\Settings::i()->forums_mod_actions_anon, FALSE, array(), NULL, NULL, NULL, 'forums_mod_actions_anon' ) );
|
||||
|
||||
$form->addHeader('topic_summary_settings');
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\CheckboxSet( 'forums_topic_activity', \IPS\Settings::i()->forums_topic_activity ? json_decode( \IPS\Settings::i()->forums_topic_activity, TRUE ) : NULL, FALSE, array(
|
||||
@@ -685,6 +690,9 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
/* This setting needs to be reversed */
|
||||
$values['forums_mod_actions_anon'] = !$values['forums_mod_actions_anon'];
|
||||
|
||||
if ( isset( $values['forums_popular_now']['never'] ) )
|
||||
{
|
||||
$values['forums_popular_now'] = json_encode( array( 'posts' => 0, 'minutes' => 0 ) );
|
||||
|
||||
@@ -27,7 +27,12 @@ class _posts extends \IPS\Dispatcher\Controller
|
||||
* @brief Has been CSRF-protected
|
||||
*/
|
||||
public static $csrfProtected = TRUE;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Allow MySQL RW separation for efficiency
|
||||
*/
|
||||
public static $allowRWSeparation = TRUE;
|
||||
|
||||
/**
|
||||
* Manage
|
||||
*
|
||||
@@ -42,7 +47,7 @@ class _posts extends \IPS\Dispatcher\Controller
|
||||
|
||||
if ( $activeTab === 'total' )
|
||||
{
|
||||
$chart = new \IPS\Helpers\Chart\Database( \IPS\Http\Url::internal( "app=forums&module=stats&controller=posts" ), 'forums_posts', 'post_date', '', array(
|
||||
$chart = new \IPS\Helpers\Chart\Database( \IPS\Http\Url::internal( "app=forums&module=stats&controller=posts" ), 'forums_posts', 'post_date', '', array(
|
||||
'isStacked' => FALSE,
|
||||
'backgroundColor' => '#ffffff',
|
||||
'colors' => array( '#10967e' ),
|
||||
@@ -50,6 +55,8 @@ class _posts extends \IPS\Dispatcher\Controller
|
||||
'lineWidth' => 1,
|
||||
'areaOpacity' => 0.4
|
||||
) );
|
||||
|
||||
$chart->where = array( array( \IPS\Db::i()->in( 'queued', array( -2, -3 ), TRUE ) ) );
|
||||
$chart->addSeries( \IPS\Member::loggedIn()->language()->addToStack( 'stats_new_posts' ), 'number', 'COUNT(*)', FALSE );
|
||||
$chart->title = \IPS\Member::loggedIn()->language()->addToStack( 'stats_posts_title' );
|
||||
$chart->availableTypes = array( 'AreaChart', 'ColumnChart', 'BarChart' );
|
||||
@@ -74,14 +81,45 @@ class _posts extends \IPS\Dispatcher\Controller
|
||||
|
||||
$chart->title = \IPS\Member::loggedIn()->language()->addToStack( 'stats_posts_title_byforum' );
|
||||
$chart->availableTypes = array( 'ColumnChart' );
|
||||
|
||||
$chart->where = array( array( \IPS\Db::i()->in( 'queued', array( -2, -3 ), TRUE ) ) );
|
||||
$chart->groupBy = 'forum_id';
|
||||
$chart->joins = array( array( 'forums_topics', 'forums_topics.tid=forums_posts.topic_id' ) );
|
||||
|
||||
foreach( \IPS\Db::i()->select( '*', 'forums_forums', array( 'posts>?', 0 ) ) as $forum )
|
||||
{
|
||||
$chart->addSeries( \IPS\Member::loggedIn()->language()->addToStack( 'forums_forum_' . $forum['id'] ), 'number', 'COUNT(*)', TRUE, $forum['id'] );
|
||||
}
|
||||
|
||||
$customValues = ( isset( $chart->savedCustomFilters['chart_forums'] ) ? array_values( explode( ',', $chart->savedCustomFilters['chart_forums'] ) ) : 0 );
|
||||
|
||||
$chart->customFiltersForm = array(
|
||||
'form' => array(
|
||||
new \IPS\Helpers\Form\Node( 'chart_forums', $customValues, FALSE, array( 'class' => 'IPS\forums\Forum', 'zeroVal' => 'any', 'multiple' => TRUE, 'permissionCheck' => function ( $forum )
|
||||
{
|
||||
return $forum->sub_can_post and !$forum->redirect_url;
|
||||
} ), NULL, NULL, NULL, 'chart_forums' )
|
||||
),
|
||||
'where' => function( $values )
|
||||
{
|
||||
$forumIds = \is_array( $values['chart_forums'] ) ? array_keys( $values['chart_forums'] ) : explode( ',', $values['chart_forums'] );
|
||||
return \IPS\Db::i()->in( 'forums_topics.forum_id', $forumIds );
|
||||
},
|
||||
'groupBy' => 'forum_id',
|
||||
'series' => function( $values )
|
||||
{
|
||||
$series = array();
|
||||
$forumIds = \is_array( $values['chart_forums'] ) ? array_keys( $values['chart_forums'] ) : explode( ',', $values['chart_forums'] );
|
||||
foreach( $forumIds as $id )
|
||||
{
|
||||
$series[] = array( \IPS\Member::loggedIn()->language()->addToStack( 'forums_forum_' . $id ), 'number', 'COUNT(*)', FALSE, $id );
|
||||
}
|
||||
return $series;
|
||||
},
|
||||
'defaultSeries' => function()
|
||||
{
|
||||
foreach( \IPS\Db::i()->select( '*', 'forums_forums', array( 'posts>?', 0 ), 'last_post desc', array( 0, 50 ) ) as $forum )
|
||||
{
|
||||
$series[] = array( \IPS\Member::loggedIn()->language()->addToStack( 'forums_forum_' . $forum['id'] ), 'number', 'COUNT(*)', FALSE, $forum['id'] );
|
||||
}
|
||||
|
||||
return $series;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
|
||||
@@ -27,6 +27,11 @@ class _topics extends \IPS\Dispatcher\Controller
|
||||
* @brief Has been CSRF-protected
|
||||
*/
|
||||
public static $csrfProtected = TRUE;
|
||||
|
||||
/**
|
||||
* @brief Allow MySQL RW separation for efficiency
|
||||
*/
|
||||
public static $allowRWSeparation = TRUE;
|
||||
|
||||
/**
|
||||
* Manage
|
||||
@@ -52,7 +57,8 @@ class _topics extends \IPS\Dispatcher\Controller
|
||||
),
|
||||
'AreaChart'
|
||||
);
|
||||
|
||||
|
||||
$chart->where = array( array( \IPS\Db::i()->in( 'state', array( 'link', 'merged' ), TRUE ) ), array( \IPS\Db::i()->in( 'approved', array( -2, -3 ), TRUE ) ) );
|
||||
$chart->addSeries( \IPS\Member::loggedIn()->language()->addToStack( 'stats_new_topics' ), 'number', 'COUNT(*)', FALSE );
|
||||
$chart->title = \IPS\Member::loggedIn()->language()->addToStack( 'stats_topics_title' );
|
||||
$chart->availableTypes = array( 'AreaChart', 'ColumnChart', 'BarChart' );
|
||||
@@ -74,16 +80,47 @@ class _topics extends \IPS\Dispatcher\Controller
|
||||
array(),
|
||||
'byforum'
|
||||
);
|
||||
|
||||
|
||||
$chart->where = array( array( \IPS\Db::i()->in( 'state', array( 'link', 'merged' ), TRUE ) ), array( \IPS\Db::i()->in( 'approved', array( -2, -3 ), TRUE ) ) );
|
||||
$chart->title = \IPS\Member::loggedIn()->language()->addToStack( 'stats_topics_title_byforum' );
|
||||
$chart->availableTypes = array( 'ColumnChart' );
|
||||
|
||||
$chart->groupBy = 'forum_id';
|
||||
|
||||
foreach( \IPS\Db::i()->select( '*', 'forums_forums', array( 'topics>?', 0 ) ) as $forum )
|
||||
{
|
||||
$chart->addSeries( \IPS\Member::loggedIn()->language()->addToStack( 'forums_forum_' . $forum['id'] ), 'number', 'COUNT(*)', TRUE, $forum['id'] );
|
||||
}
|
||||
$customValues = ( isset( $chart->savedCustomFilters['chart_forums'] ) ? array_values( explode( ',', $chart->savedCustomFilters['chart_forums'] ) ) : 0 );
|
||||
|
||||
$chart->customFiltersForm = array(
|
||||
'form' => array(
|
||||
new \IPS\Helpers\Form\Node( 'chart_forums', $customValues, FALSE, array( 'class' => 'IPS\forums\Forum', 'zeroVal' => 'any', 'multiple' => TRUE, 'permissionCheck' => function ( $forum )
|
||||
{
|
||||
return $forum->sub_can_post and !$forum->redirect_url;
|
||||
} ), NULL, NULL, NULL, 'chart_forums' )
|
||||
),
|
||||
'where' => function( $values )
|
||||
{
|
||||
$forumIds = \is_array( $values['chart_forums'] ) ? array_keys( $values['chart_forums'] ) : explode( ',', $values['chart_forums'] );
|
||||
return \IPS\Db::i()->in( 'forum_id', $forumIds );
|
||||
},
|
||||
'groupBy' => 'forum_id',
|
||||
'series' => function( $values )
|
||||
{
|
||||
$series = array();
|
||||
$forumIds = \is_array( $values['chart_forums'] ) ? array_keys( $values['chart_forums'] ) : explode( ',', $values['chart_forums'] );
|
||||
foreach( $forumIds as $id )
|
||||
{
|
||||
$series[] = array( \IPS\Member::loggedIn()->language()->addToStack( 'forums_forum_' . $id ), 'number', 'COUNT(*)', FALSE, $id );
|
||||
}
|
||||
return $series;
|
||||
},
|
||||
'defaultSeries' => function()
|
||||
{
|
||||
foreach( \IPS\Db::i()->select( '*', 'forums_forums', array( 'topics>?', 0 ), 'last_post desc', array( 0, 50 ) ) as $forum )
|
||||
{
|
||||
$series[] = array( \IPS\Member::loggedIn()->language()->addToStack( 'forums_forum_' . $forum['id'] ), 'number', 'COUNT(*)', FALSE, $forum['id'] );
|
||||
}
|
||||
|
||||
return $series;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
|
||||
@@ -51,8 +51,6 @@ class _forums extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
public function _forum( $forum )
|
||||
{
|
||||
$this->themeGroup = \IPS\Theme::i()->getTemplate( 'forums', 'forums', 'front' );
|
||||
|
||||
$forum->clubCheckRules();
|
||||
|
||||
/* Is simple mode on? If so, redirect to the index page */
|
||||
@@ -80,6 +78,7 @@ class _forums extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Theme */
|
||||
$forum->setTheme();
|
||||
$this->themeGroup = \IPS\Theme::i()->getTemplate( 'forums', 'forums', 'front' );
|
||||
|
||||
/* Users can see topics posted by other users? */
|
||||
$where = array();
|
||||
@@ -179,8 +178,6 @@ class _forums extends \IPS\Dispatcher\Controller
|
||||
'solved_topics' => 'topic_answered_pid>0',
|
||||
'unsolved_topics' => 'topic_answered_pid=0',
|
||||
);
|
||||
|
||||
$table->sortOptions['question_rating'] = 'forums_topics.question_rating';
|
||||
}
|
||||
|
||||
/* Are we a moderator? */
|
||||
@@ -188,6 +185,17 @@ class _forums extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$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' )
|
||||
{
|
||||
\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(
|
||||
@@ -389,7 +397,7 @@ class _forums extends \IPS\Dispatcher\Controller
|
||||
break;
|
||||
}
|
||||
|
||||
$popularQuestions = \IPS\forums\Topic::getItemsWithPermission( array( array( 'forum_id=?', $forum->id ), array( 'start_date>?', \IPS\DateTime::ts( time() - ( 86400 * 30 ) )->getTimestamp() ), array( 'question_rating>0' ) ), 'question_rating DESC', 5 );
|
||||
$popularQuestions = \IPS\forums\Topic::getItemsWithPermission( array( array( 'forum_id=?', $forum->id ), array( 'start_date>?', \IPS\DateTime::ts( time() - ( 86400 * 30 ) )->getTimestamp() ), array( 'question_rating>0' ) ), 'question_rating DESC, views DESC', 5 );
|
||||
$newQuestionsWhere = array( array( 'forum_id=?', $forum->id ) );
|
||||
|
||||
if ( !\IPS\Settings::i()->forums_new_questions )
|
||||
@@ -409,7 +417,8 @@ class _forums extends \IPS\Dispatcher\Controller
|
||||
$forumOutput = (string) $table;
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = $this->themeGroup->forumDisplay( $forum, $forumOutput );
|
||||
\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 );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -492,6 +501,7 @@ class _forums extends \IPS\Dispatcher\Controller
|
||||
\IPS\Session::i()->setLocation( $forum->url(), explode( ",", $permissions['perm_view'] ), 'loc_forums_creating_topic', array( "forums_forum_{$forum->id}" => TRUE ) );
|
||||
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->linkTags['canonical'] = (string) $forum->url()->setQueryString( 'do', 'add' );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'submit' )->createTopic( $formTemplate, $forum, $title );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( $title );
|
||||
|
||||
|
||||
@@ -115,7 +115,13 @@ class _index extends \IPS\Dispatcher\Controller
|
||||
/* Display */
|
||||
if ( \IPS\forums\Forum::isSimpleView() )
|
||||
{
|
||||
$where = array( 'container' => array( array( 'forums_forums.password IS NULL' ) ) );
|
||||
$where = array();
|
||||
|
||||
if ( \IPS\forums\Forum::hasPasswordForums() )
|
||||
{
|
||||
$where = array( 'container' => array( 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' );
|
||||
@@ -171,7 +177,16 @@ class _index extends \IPS\Dispatcher\Controller
|
||||
$table->tableTemplate = array( \IPS\Theme::i()->getTemplate( 'index' ), 'simplifiedForumTable' );
|
||||
$table->classes = array( 'cTopicList' );
|
||||
$table->limit = \IPS\Settings::i()->forums_topics_per_page;
|
||||
$table->rowsTemplate = array( \IPS\Theme::i()->getTemplate( 'index' ), 'simplifiedTopicRow' );
|
||||
|
||||
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'];
|
||||
|
||||
@@ -283,6 +283,18 @@ class _topic extends \IPS\Content\Controller
|
||||
$topic->markRead( NULL, $maxTime );
|
||||
}
|
||||
}
|
||||
elseif( $topic->isLastPage() )
|
||||
{
|
||||
/* See if the last comment is hidden or pending approval. If so, force the topic read because it won't be done so automatically. */
|
||||
$lastComment = end( $comments );
|
||||
|
||||
if( $lastComment and $lastComment->hidden() !== 0 )
|
||||
{
|
||||
$topic->markRead( NULL, NULL, NULL, TRUE );
|
||||
}
|
||||
|
||||
reset( $comments );
|
||||
}
|
||||
|
||||
$votes = array();
|
||||
$topicVotes = array();
|
||||
@@ -320,41 +332,26 @@ class _topic extends \IPS\Content\Controller
|
||||
|
||||
/* Add Json-LD */
|
||||
$isQuestion = ( $topic->isQuestion() or $topic->isSolved() );
|
||||
\IPS\Output::i()->jsonLd['topic'] = array(
|
||||
'@context' => "http://schema.org",
|
||||
'@type' => $isQuestion ? 'Question' : 'DiscussionForumPosting',
|
||||
'@id' => (string) $topic->url(),
|
||||
'isPartOf' => array(
|
||||
'@id' => \IPS\Settings::i()->base_url . '#website'
|
||||
),
|
||||
'publisher' => array(
|
||||
'@id' => \IPS\Settings::i()->base_url . '#organization'
|
||||
),
|
||||
'url' => (string) $topic->url(),
|
||||
'discussionUrl' => (string) $topic->url(),
|
||||
'mainEntityOfPage' => array(
|
||||
'@type' => 'WebPage',
|
||||
'@id' => (string) $topic->url()
|
||||
)
|
||||
);
|
||||
|
||||
/* Do we have a real author */
|
||||
if( $topic->starter_id )
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['topic']['author']['url'] = (string) \IPS\Member::load( $topic->starter_id )->url();
|
||||
|
||||
\IPS\Output::i()->jsonLd['topic']['publisher']['member'] = array(
|
||||
'@type' => "Person",
|
||||
'name' => \IPS\Member::load( $topic->starter_id )->name,
|
||||
'image' => (string) \IPS\Member::load( $topic->starter_id )->get_photo(),
|
||||
'url' => (string) \IPS\Member::load( $topic->starter_id )->url(),
|
||||
if ( $isQuestion )
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['topic'] = array(
|
||||
'@context' => "http://schema.org",
|
||||
'@type' => 'QAPage',
|
||||
'@id' => (string) $topic->url(),
|
||||
'url' => (string) $topic->url(),
|
||||
'mainEntity' => [
|
||||
'@type' => "Question",
|
||||
'name' => $topic->title,
|
||||
'text' => $topic->comments( 1, 0 )->truncated( TRUE, NULL ),
|
||||
'answerCount' => $topic->posts ? $topic->posts - 1 : 0,
|
||||
'dateCreated' => \IPS\DateTime::ts( $topic->start_date )->format( \IPS\DateTime::ISO8601 ),
|
||||
'author' => [
|
||||
'@type' => 'Person',
|
||||
'name' => $topic->author()->name
|
||||
]
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
if( $isQuestion )
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['topic']['answerCount'] = $topic->posts ? $topic->posts - 1 : 0;
|
||||
\IPS\Output::i()->jsonLd['topic']['upvoteCount'] = \intval( $topic->question_rating );
|
||||
|
||||
if( $topic->topic_answered_pid )
|
||||
{
|
||||
@@ -362,22 +359,27 @@ class _topic extends \IPS\Content\Controller
|
||||
{
|
||||
$answer = \IPS\forums\Topic\Post::load( $topic->topic_answered_pid );
|
||||
|
||||
\IPS\Output::i()->jsonLd['topic']['acceptedAnswer'] = array(
|
||||
\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->post_field_int,
|
||||
'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()
|
||||
'image' => \IPS\Member::load( $answer->author_id )->get_photo( TRUE, TRUE )
|
||||
),
|
||||
);
|
||||
|
||||
if( $topic->isQuestion() )
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['topic']['mainEntity']['acceptedAnswer']['upvoteCount'] = $answer->post_field_int;
|
||||
}
|
||||
|
||||
if( $answer->author_id )
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['topic']['acceptedAnswer']['author']['url'] = (string) \IPS\Member::load( $answer->author_id )->url();
|
||||
\IPS\Output::i()->jsonLd['topic']['mainEntity']['acceptedAnswer']['author']['url'] = (string) \IPS\Member::load( $answer->author_id )->url();
|
||||
}
|
||||
}
|
||||
catch( \OutOfRangeException $e ){}
|
||||
@@ -385,9 +387,41 @@ class _topic extends \IPS\Content\Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['topic']['comment'] = array();
|
||||
\IPS\Output::i()->jsonLd['topic'] = array(
|
||||
'@context' => "http://schema.org",
|
||||
'@type' => 'DiscussionForumPosting',
|
||||
'@id' => (string) $topic->url(),
|
||||
'isPartOf' => array(
|
||||
'@id' => \IPS\Settings::i()->base_url . '#website'
|
||||
),
|
||||
'publisher' => array(
|
||||
'@id' => \IPS\Settings::i()->base_url . '#organization'
|
||||
),
|
||||
'url' => (string) $topic->url(),
|
||||
'discussionUrl' => (string) $topic->url(),
|
||||
'mainEntityOfPage' => array(
|
||||
'@type' => 'WebPage',
|
||||
'@id' => (string) $topic->url()
|
||||
),
|
||||
'pageStart' => 1,
|
||||
'pageEnd' => $topic->commentPageCount(),
|
||||
);
|
||||
}
|
||||
|
||||
/* Add in comments */
|
||||
if( $topic->posts > 1 )
|
||||
{
|
||||
if ( $isQuestion )
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['topic']['mainEntity']['suggestedAnswer'] = [];
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['topic']['comment'] = [];
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
$commentJson = [];
|
||||
foreach( $comments as $comment )
|
||||
{
|
||||
// Don't include the first post as a "comment"
|
||||
@@ -396,27 +430,70 @@ class _topic extends \IPS\Content\Controller
|
||||
continue;
|
||||
}
|
||||
|
||||
$url = $topic->url()->setPage( 'page', \IPS\Request::i()->page );
|
||||
\IPS\Output::i()->jsonLd['topic']['comment'][ $i ] = array(
|
||||
'@type' => 'Comment',
|
||||
'@id' => (string) $url->setFragment( 'comment-' . $comment->pid ),
|
||||
'url' => (string) $url->setFragment( 'comment-' . $comment->pid ),
|
||||
'author' => array(
|
||||
'@type' => 'Person',
|
||||
'name' => $comment->author_name ?: \IPS\Member::load( $comment->author_id )->name,
|
||||
'image' => \IPS\Member::load( $comment->author_id )->get_photo()
|
||||
),
|
||||
'dateCreated' => \IPS\DateTime::ts( $comment->post_date )->format( \IPS\DateTime::ISO8601 ),
|
||||
'text' => $comment->truncated( TRUE, NULL ),
|
||||
);
|
||||
|
||||
if( $comment->author_id )
|
||||
// Don't include the answer as the suggested answer
|
||||
if( $isQuestion and ( $comment->pid === $topic->mapped('solved_comment_id') ) )
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['topic']['comment'][ $i ]['author']['url'] = (string) \IPS\Member::load( $comment->author_id )->url();
|
||||
continue;
|
||||
}
|
||||
|
||||
$i++;
|
||||
if ( $truncatedComment = $comment->truncated( TRUE, NULL ) )
|
||||
{
|
||||
$url = $topic->url()->setPage( 'page', \IPS\Request::i()->page );
|
||||
|
||||
$commentJson[$i] = array(
|
||||
'@type' => $isQuestion ? 'Answer' : 'Comment',
|
||||
'@id' => (string)$url->setFragment( 'comment-' . $comment->pid ),
|
||||
'url' => (string)$url->setFragment( 'comment-' . $comment->pid ),
|
||||
'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 )
|
||||
),
|
||||
'dateCreated' => \IPS\DateTime::ts( $comment->post_date )->format( \IPS\DateTime::ISO8601 ),
|
||||
'upvoteCount' => $comment->reactionCount(),
|
||||
'text' => $truncatedComment,
|
||||
);
|
||||
|
||||
if ( $comment->author_id )
|
||||
{
|
||||
$commentJson[$i]['author']['url'] = (string)\IPS\Member::load( $comment->author_id )->url();
|
||||
}
|
||||
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $isQuestion )
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['topic']['mainEntity']['suggestedAnswer'] = $commentJson;
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['topic']['comment'] = $commentJson;
|
||||
}
|
||||
}
|
||||
|
||||
/* Do we have a real author */
|
||||
if( $topic->starter_id )
|
||||
{
|
||||
\IPS\Output::i()->jsonLd['topic']['author']['url'] = (string) \IPS\Member::load( $topic->starter_id )->url();
|
||||
|
||||
\IPS\Output::i()->jsonLd['topic']['publisher']['member'] = array(
|
||||
'@type' => "Person",
|
||||
'name' => \IPS\Member::load( $topic->starter_id )->name,
|
||||
'image' => (string) \IPS\Member::load( $topic->starter_id )->get_photo( TRUE, TRUE ),
|
||||
'url' => (string) \IPS\Member::load( $topic->starter_id )->url(),
|
||||
);
|
||||
}
|
||||
|
||||
/* Enable caching for archived topics */
|
||||
if( $topic->isArchived() AND !\IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
/* 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" );
|
||||
|
||||
\IPS\Output::i()->httpHeaders += $httpHeaders;
|
||||
}
|
||||
|
||||
\IPS\Output::i()->jsonLd['topic'] = array_merge_recursive( array(
|
||||
@@ -426,14 +503,12 @@ class _topic extends \IPS\Content\Controller
|
||||
'dateCreated' => \IPS\DateTime::ts( $topic->start_date )->format( \IPS\DateTime::ISO8601 ),
|
||||
'datePublished' => \IPS\DateTime::ts( $topic->start_date )->format( \IPS\DateTime::ISO8601 ),
|
||||
'dateModified' => \IPS\DateTime::ts( $topic->last_post )->format( \IPS\DateTime::ISO8601 ),
|
||||
'pageStart' => 1,
|
||||
'pageEnd' => $topic->commentPageCount(),
|
||||
/* Image is required, but we don't have "topic images", so we'll use topic starter's profile photo for now */
|
||||
'image' => (string) \IPS\Member::load( $topic->starter_id )->get_photo(),
|
||||
'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,
|
||||
'image' => \IPS\Member::load( $topic->starter_id )->get_photo()
|
||||
'image' => \IPS\Member::load( $topic->starter_id )->get_photo( TRUE, TRUE )
|
||||
),
|
||||
'interactionStatistic' => array(
|
||||
array(
|
||||
@@ -625,6 +700,9 @@ class _topic extends \IPS\Content\Controller
|
||||
|
||||
$topic->topic_archive_status = \IPS\forums\Topic::ARCHIVE_RESTORE;
|
||||
$topic->save();
|
||||
|
||||
/* Make sure the task is enabled */
|
||||
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => 1 ), array( '`key`=?', 'unarchive' ) );
|
||||
|
||||
/* Log */
|
||||
\IPS\Session::i()->modLog( 'modlog__unarchived_topic', array( $topic->url()->__toString() => FALSE, $topic->mapped( 'title' ) => FALSE ), $topic );
|
||||
@@ -813,13 +891,6 @@ class _topic extends \IPS\Content\Controller
|
||||
}
|
||||
|
||||
$topic->toggleSolveComment( $post->pid, TRUE );
|
||||
|
||||
if( $post->author()->member_id != \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
$notification = new \IPS\Notification( \IPS\Application::load( 'core' ), 'best_answer', $topic, array( $post ), array( $post->author()->member_id ) );
|
||||
$notification->recipients->attach( $post->author() );
|
||||
$notification->send();
|
||||
}
|
||||
|
||||
/* Log */
|
||||
if ( \IPS\Member::loggedIn()->modPermission('can_set_best_answer') )
|
||||
@@ -859,19 +930,16 @@ class _topic extends \IPS\Content\Controller
|
||||
throw new \OutOfRangeException;
|
||||
}
|
||||
|
||||
if ( $topic->topic_answered_pid )
|
||||
try
|
||||
{
|
||||
try
|
||||
$topic->toggleSolveComment( $post->pid, FALSE );
|
||||
|
||||
if ( \IPS\Member::loggedIn()->modPermission('can_set_best_answer') )
|
||||
{
|
||||
$topic->toggleSolveComment( $post->pid, FALSE );
|
||||
|
||||
if ( \IPS\Member::loggedIn()->modPermission('can_set_best_answer') )
|
||||
{
|
||||
\IPS\Session::i()->modLog( 'modlog__best_answer_unset', array( $topic->topic_answered_pid => FALSE ), $topic );
|
||||
}
|
||||
\IPS\Session::i()->modLog( 'modlog__best_answer_unset', array( $post->pid => FALSE ), $topic );
|
||||
}
|
||||
catch ( \Exception $e ) {}
|
||||
}
|
||||
catch ( \Exception $e ) {}
|
||||
|
||||
\IPS\Output::i()->redirect( $post->url() );
|
||||
}
|
||||
@@ -1026,8 +1094,28 @@ class _topic extends \IPS\Content\Controller
|
||||
$where[] = array( $hiddenWhereClause );
|
||||
}
|
||||
}
|
||||
$answers = \IPS\Db::i()->select( 'archive_id, @rownum := @rownum + 1 AS position', 'forums_archive_posts', $where, 'archive_is_first DESC, archive_bwoptions DESC, archive_field_int DESC, archive_content_date' )->join( array( '(SELECT @rownum := 0)', 'r' ), NULL, 'JOIN' );
|
||||
$commentPosition = \IPS\Db::i()->select( 'position', $answers, array( 'archive_id=?', $comment->id ) )->first() - 1;
|
||||
|
||||
/* Connect to the remote DB if needed */
|
||||
if ( \IPS\CIC2 )
|
||||
{
|
||||
$storage = \IPS\Cicloud\getForumArchiveDb();
|
||||
}
|
||||
else
|
||||
{
|
||||
$storage = !\IPS\Settings::i()->archive_remote_sql_host ? \IPS\Db::i() : \IPS\Db::i( 'archive', array(
|
||||
'sql_host' => \IPS\Settings::i()->archive_remote_sql_host,
|
||||
'sql_user' => \IPS\Settings::i()->archive_remote_sql_user,
|
||||
'sql_pass' => \IPS\Settings::i()->archive_remote_sql_pass,
|
||||
'sql_database' => \IPS\Settings::i()->archive_remote_sql_database,
|
||||
'sql_port' => \IPS\Settings::i()->archive_sql_port,
|
||||
'sql_socket' => \IPS\Settings::i()->archive_sql_socket,
|
||||
'sql_tbl_prefix'=> \IPS\Settings::i()->archive_sql_tbl_prefix,
|
||||
'sql_utf8mb4' => isset( \IPS\Settings::i()->sql_utf8mb4 ) ? \IPS\Settings::i()->sql_utf8mb4 : FALSE
|
||||
) );
|
||||
}
|
||||
|
||||
$answers = $storage->select( 'archive_id, @rownum := @rownum + 1 AS position', 'forums_archive_posts', $where, 'archive_is_first DESC, archive_bwoptions DESC, archive_field_int DESC, archive_content_date' )->join( array( '(SELECT @rownum := 0)', 'r' ), NULL, 'JOIN' );
|
||||
$commentPosition = $storage->select( 'position', $answers, array( 'archive_id=?', $comment->id ) )->first() - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -30,6 +30,12 @@ class _Upgrade
|
||||
*/
|
||||
public function step1()
|
||||
{
|
||||
/* Make sure we have the table first */
|
||||
if( !\IPS\Db::i()->checkForTable('forums_rss_import') )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Move over forums_rss_import to core_rss_import */
|
||||
foreach( \IPS\Db::i()->select( '*', 'forums_rss_import' ) as $rss )
|
||||
{
|
||||
@@ -48,8 +54,8 @@ class _Upgrade
|
||||
'rss_import_topic_pre' => $rss['rss_import_topic_pre'],
|
||||
'rss_import_auto_follow' => $rss['rss_import_auto_follow'],
|
||||
'rss_import_settings' => json_encode( array(
|
||||
'rss_import_topic_open' => $rss['rss_import_topic_open'],
|
||||
'rss_import_topic_hide' => $rss['rss_import_topic_hide']
|
||||
'topic_open' => $rss['rss_import_topic_open'],
|
||||
'topic_hide' => $rss['rss_import_topic_hide']
|
||||
) )
|
||||
) );
|
||||
|
||||
@@ -60,7 +66,7 @@ class _Upgrade
|
||||
|
||||
\IPS\Db::i()->query( "INSERT INTO " . \IPS\Db::i()->prefix . "core_rss_imported
|
||||
(rss_imported_guid, rss_imported_content_id, rss_imported_import_id )
|
||||
( SELECT a.rss_imported_guid, a.rss_imported_tid, {$newImportId} FROM " . \IPS\Db::i()->prefix . "forums_rss_imported a)" );
|
||||
( SELECT a.rss_imported_guid, a.rss_imported_tid, {$newImportId} FROM " . \IPS\Db::i()->prefix . "forums_rss_imported a WHERE a.rss_imported_impid={$rss['rss_import_id']})" );
|
||||
}
|
||||
catch( \Exception $e ) { }
|
||||
}
|
||||
@@ -94,7 +100,10 @@ class _Upgrade
|
||||
) ), 'forums' ) );
|
||||
|
||||
/* Delete old RSS Table */
|
||||
\IPS\Db::i()->dropTable( array( 'forums_rss_import', 'forums_rss_imported' ) );
|
||||
if( \IPS\Db::i()->checkForTable('forums_rss_import') )
|
||||
{
|
||||
\IPS\Db::i()->dropTable( array( 'forums_rss_import', 'forums_rss_imported' ) );
|
||||
}
|
||||
|
||||
/* Kick off solve index build */
|
||||
\IPS\Task::queue( 'forums', 'RebuildSolvedIndex', array(), 4 );
|
||||
|
||||
@@ -24,14 +24,14 @@ if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
class _Upgrade
|
||||
{
|
||||
/**
|
||||
* ...
|
||||
* Auto-enable archiving on CIC2 if appropriate
|
||||
*
|
||||
* @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
|
||||
*/
|
||||
public function step1()
|
||||
{
|
||||
|
||||
if ( \IPS\CIC2 )
|
||||
/* Auto-enable post archiving if the community is CIC2 and has more than 255K posts */
|
||||
if ( \IPS\CIC2 AND \IPS\Cicloud\getForcedArchiving() )
|
||||
{
|
||||
/* Make sure archiving is on */
|
||||
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => 1 ), array( '`key`=?', 'archive' ) );
|
||||
@@ -39,6 +39,16 @@ class _Upgrade
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom title for this step
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function step1CustomTitle()
|
||||
{
|
||||
return "Adjusting archiving options";
|
||||
}
|
||||
|
||||
// You can create as many additional methods (step2, step3, etc.) as is necessary.
|
||||
// Each step will be executed in a new HTTP request
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105101,
|
||||
"name": "4.5.0",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": true,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"files": {
|
||||
"added": [],
|
||||
"edited": [],
|
||||
"removed": []
|
||||
},
|
||||
"orders": {
|
||||
"added": [],
|
||||
"edited": [],
|
||||
"removed": [
|
||||
"global\/\/dev\/js\/\/framework\/",
|
||||
"global\/\/dev\/js\/\/library\/",
|
||||
"global\/\/dev\/js\/\/library\/\/jquery",
|
||||
"global\/\/dev\/js\/\/library\/\/linkify"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105102,
|
||||
"name": "4.5.1 Beta 1",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": true,
|
||||
"themeSettings": false,
|
||||
"javascript": true,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"files": {
|
||||
"added": [],
|
||||
"edited": [
|
||||
"forums\/front\/controllers\/forum\/ips.forum.forumList.js"
|
||||
],
|
||||
"removed": []
|
||||
},
|
||||
"orders": {
|
||||
"added": [],
|
||||
"edited": [],
|
||||
"removed": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"html": {
|
||||
"added": [],
|
||||
"edited": [
|
||||
"front\/global\/viewChange",
|
||||
"front\/index\/forumGridItem",
|
||||
"front\/index\/forumRow",
|
||||
"front\/topics\/activity"
|
||||
],
|
||||
"removed": []
|
||||
},
|
||||
"css": {
|
||||
"added": [],
|
||||
"edited": [
|
||||
"front\/forums_responsive.css",
|
||||
"front\/forums.css",
|
||||
"front\/topics.css"
|
||||
],
|
||||
"removed": []
|
||||
},
|
||||
"resources": {
|
||||
"added": [],
|
||||
"edited": [],
|
||||
"removed": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105103,
|
||||
"name": "4.5.1 Beta 1",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105104,
|
||||
"name": "4.5.1 Beta 2",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": true,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"html": {
|
||||
"added": [],
|
||||
"edited": [
|
||||
"front\/topics\/topic"
|
||||
],
|
||||
"removed": []
|
||||
},
|
||||
"css": {
|
||||
"added": [],
|
||||
"edited": [],
|
||||
"removed": []
|
||||
},
|
||||
"resources": {
|
||||
"added": [],
|
||||
"edited": [],
|
||||
"removed": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105105,
|
||||
"name": "4.5.1 Beta 3",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105106,
|
||||
"name": "4.5.1",
|
||||
"steps": {
|
||||
"queries": true,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"1": {
|
||||
"method": "update",
|
||||
"params": [
|
||||
"core_rss_import",
|
||||
"rss_import_settings=REPLACE( rss_import_settings, 'rss_import_', '' )"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105107,
|
||||
"name": "4.5.2",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105108,
|
||||
"name": "4.5.2",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105109,
|
||||
"name": "4.5.2",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105110,
|
||||
"name": "4.5.2",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105111,
|
||||
"name": "4.5.2",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105112,
|
||||
"name": "4.5.3",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": true,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"html": {
|
||||
"added": [],
|
||||
"edited": [
|
||||
"front\/topics\/topic"
|
||||
],
|
||||
"removed": []
|
||||
},
|
||||
"css": {
|
||||
"added": [],
|
||||
"edited": [],
|
||||
"removed": []
|
||||
},
|
||||
"resources": {
|
||||
"added": [],
|
||||
"edited": [],
|
||||
"removed": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105113,
|
||||
"name": "4.5.3",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105114,
|
||||
"name": "4.5.3",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105115,
|
||||
"name": "4.5.3",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105116,
|
||||
"name": "4.5.4",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": true,
|
||||
"theme": true,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": true,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": true
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"normal": {
|
||||
"added": [
|
||||
"chart_forums",
|
||||
"archiving_blurb_cloud_notforced",
|
||||
"disable_cloud_archiving"
|
||||
],
|
||||
"edited": [],
|
||||
"removed": []
|
||||
},
|
||||
"js": {
|
||||
"added": [],
|
||||
"edited": [],
|
||||
"removed": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"added": [],
|
||||
"edited": [
|
||||
"archive_last_post_cloud"
|
||||
],
|
||||
"removed": []
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"html": {
|
||||
"added": [
|
||||
"admin\/settings\/archiveOffCic"
|
||||
],
|
||||
"edited": [],
|
||||
"removed": []
|
||||
},
|
||||
"css": {
|
||||
"added": [],
|
||||
"edited": [],
|
||||
"removed": []
|
||||
},
|
||||
"resources": {
|
||||
"added": [],
|
||||
"edited": [],
|
||||
"removed": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief 4.5.4 Upgrade Code
|
||||
* @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
|
||||
* @subpackage Forums
|
||||
* @since 29 Sep 2020
|
||||
*/
|
||||
|
||||
namespace IPS\forums\setup\upg_105116;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 4.5.4 Upgrade Code
|
||||
*/
|
||||
class _Upgrade
|
||||
{
|
||||
/**
|
||||
* Tweak archiving for CIC2
|
||||
*
|
||||
* @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
|
||||
*/
|
||||
public function step1()
|
||||
{
|
||||
/* If this is a CIC2 site... */
|
||||
if ( \IPS\CIC2 )
|
||||
{
|
||||
/* Make sure archiving is on if it should be */
|
||||
if( \IPS\Cicloud\getForcedArchiving() )
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => 1 ), array( '`key`=?', 'archive' ) );
|
||||
}
|
||||
/* Otherwise unarchive everything and make sure archiving is not enabled. They can turn back on later if they want. */
|
||||
else
|
||||
{
|
||||
\IPS\Db::i()->update( 'forums_topics', array( 'topic_archive_status' => \IPS\forums\Topic::ARCHIVE_RESTORE ), array( 'topic_archive_status=?', \IPS\forums\Topic::ARCHIVE_DONE ) );
|
||||
|
||||
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => 0 ), array( '`key`=?', 'archive' ) );
|
||||
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => 1 ), array( '`key`=?', 'unarchive' ) );
|
||||
|
||||
/* This disables the archiving setting */
|
||||
\IPS\Settings::i()->changeValues( array( 'archive_last_post_cloud' => 100 ) );
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom title for this step
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function step1CustomTitle()
|
||||
{
|
||||
return "Adjusting archiving options";
|
||||
}
|
||||
|
||||
// You can create as many additional methods (step2, step3, etc.) as is necessary.
|
||||
// Each step will be executed in a new HTTP request
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105117,
|
||||
"name": "4.5.4",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105118,
|
||||
"name": "4.5.4",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105119,
|
||||
"name": "4.5.4",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105120,
|
||||
"name": "4.5.4",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105121,
|
||||
"name": "4.5.4",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105122,
|
||||
"name": "4.5.4",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105123,
|
||||
"name": "4.5.4",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105124,
|
||||
"name": "4.5.4.1",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105125,
|
||||
"name": "4.5.4.2",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105126,
|
||||
"name": "4.5.4.2",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105127,
|
||||
"name": "4.5.4.2",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105128,
|
||||
"name": "4.5.4.2",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105129,
|
||||
"name": "4.5.4.2",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 105130,
|
||||
"name": "4.5.4.2",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"added": [
|
||||
"app=forums&module=forums&controller=forums&do=form&searchResult=form_2_allow_anonymous"
|
||||
],
|
||||
"edited": [],
|
||||
"removed": []
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 106100,
|
||||
"name": "4.6.0 Beta 1",
|
||||
"steps": {
|
||||
"queries": true,
|
||||
"lang": true,
|
||||
"theme": true,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": true,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": true,
|
||||
"settings": true,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"added": [],
|
||||
"edited": [
|
||||
"digests__comment",
|
||||
"digests__item"
|
||||
],
|
||||
"removed": []
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"normal": {
|
||||
"added": [
|
||||
"__defart_post_plural",
|
||||
"__defart_topic_plural",
|
||||
"__defart_answer_plural",
|
||||
"__defart_question_plural",
|
||||
"topic_posted_in_groups",
|
||||
"filter_hidden_topics",
|
||||
"filter_hidden_posts_in_topics",
|
||||
"stats_percentagesolved",
|
||||
"stats_percentagesolved_desc",
|
||||
"stats_solved_tooltip",
|
||||
"stats_solved_tooltip_prev",
|
||||
"stats_averagetimesolved",
|
||||
"stats_averagetimesolved_desc",
|
||||
"forums_topic_show_meta_moderation_desc",
|
||||
"forums_mod_actions_anon",
|
||||
"forums_mod_actions_anon_desc",
|
||||
"404_forums_topic",
|
||||
"403_forums_topic",
|
||||
"AchievementAction__AnswerMarkedBest",
|
||||
"achievement_filter_AnswerMarkedBest_forum",
|
||||
"achievement_filter_AnswerMarkedBest_forum_prefix",
|
||||
"achievement_filter_AnswerMarkedBest_poster",
|
||||
"achievement_filter_AnswerMarkedBest_asker",
|
||||
"achievement_filter_AnswerMarkedBest_nth",
|
||||
"achievement_filter_AnswerMarkedBest_nth_suffix",
|
||||
"AchievementAction__AnswerMarkedBest_log_subject",
|
||||
"AchievementAction__AnswerMarkedBest_log_other",
|
||||
"AchievementAction__AnswerMarkedBest_log_deleted",
|
||||
"AchievementAction__AnswerMarkedBest_title"
|
||||
],
|
||||
"edited": [
|
||||
"forum_allow_poll",
|
||||
"forum_inc_postcount",
|
||||
"forum_use_feature_color_desc"
|
||||
],
|
||||
"removed": [
|
||||
"first_unread_post",
|
||||
"get_last_post"
|
||||
]
|
||||
},
|
||||
"js": {
|
||||
"added": [],
|
||||
"edited": [],
|
||||
"removed": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"1": {
|
||||
"method": "addColumn",
|
||||
"params": [
|
||||
"forums_forums",
|
||||
{
|
||||
"name": "allow_anonymous",
|
||||
"type": "TINYINT",
|
||||
"length": null,
|
||||
"decimals": null,
|
||||
"values": null,
|
||||
"allow_null": false,
|
||||
"default": "0",
|
||||
"comment": "",
|
||||
"unsigned": true,
|
||||
"auto_increment": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"2": {
|
||||
"method": "addColumn",
|
||||
"params": [
|
||||
"forums_topics",
|
||||
{
|
||||
"name": "is_anon",
|
||||
"type": "TINYINT",
|
||||
"length": null,
|
||||
"decimals": null,
|
||||
"values": null,
|
||||
"allow_null": false,
|
||||
"default": "0",
|
||||
"comment": "",
|
||||
"unsigned": true,
|
||||
"auto_increment": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"3": {
|
||||
"method": "addColumn",
|
||||
"params": [
|
||||
"forums_forums",
|
||||
{
|
||||
"name": "last_poster_anon",
|
||||
"type": "TINYINT",
|
||||
"length": null,
|
||||
"decimals": null,
|
||||
"values": null,
|
||||
"allow_null": true,
|
||||
"default": "0",
|
||||
"comment": "",
|
||||
"unsigned": true,
|
||||
"auto_increment": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"4": {
|
||||
"method": "addColumn",
|
||||
"params": [
|
||||
"forums_topics",
|
||||
{
|
||||
"name": "last_poster_anon",
|
||||
"type": "TINYINT",
|
||||
"length": null,
|
||||
"decimals": null,
|
||||
"values": null,
|
||||
"allow_null": true,
|
||||
"default": "0",
|
||||
"comment": "",
|
||||
"unsigned": true,
|
||||
"auto_increment": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"5": {
|
||||
"method": "update",
|
||||
"params": [
|
||||
"core_notifications",
|
||||
{
|
||||
"notification_key": "my_solution"
|
||||
},
|
||||
[
|
||||
"notification_app=? and notification_key=?",
|
||||
"core",
|
||||
"best_answer"
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"added": [
|
||||
"forums_mod_actions_anon"
|
||||
],
|
||||
"edited": [],
|
||||
"removed": []
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"html": {
|
||||
"added": [
|
||||
"front\/index\/simplifiedTopicRowSnippet",
|
||||
"admin\/stats\/solvedPercentage",
|
||||
"admin\/stats\/timeToSolved"
|
||||
],
|
||||
"edited": [
|
||||
"front\/forums\/forumHome",
|
||||
"front\/forums\/forumPasswordPopup",
|
||||
"front\/forums\/forumTable",
|
||||
"front\/forums\/popularQuestionRow",
|
||||
"front\/forums\/questionRow",
|
||||
"front\/forums\/topicHover",
|
||||
"front\/forums\/topicRow",
|
||||
"front\/forums\/topicRowSnippet",
|
||||
"front\/global\/commentTableHeader",
|
||||
"front\/global\/embedTopic",
|
||||
"front\/global\/row",
|
||||
"front\/index\/forumGridItem",
|
||||
"front\/index\/forumRow",
|
||||
"front\/index\/simplifiedForumTable",
|
||||
"front\/index\/simplifiedTopicRow",
|
||||
"front\/index\/simplifiedViewSidebar",
|
||||
"front\/topics\/activity",
|
||||
"front\/topics\/post",
|
||||
"front\/topics\/postContainer",
|
||||
"front\/topics\/topic",
|
||||
"front\/widgets\/forumStatistics",
|
||||
"front\/widgets\/hotTopics",
|
||||
"front\/widgets\/pollFormWidget",
|
||||
"front\/widgets\/postFeed",
|
||||
"front\/widgets\/topicFeed"
|
||||
],
|
||||
"removed": []
|
||||
},
|
||||
"css": {
|
||||
"added": [],
|
||||
"edited": [
|
||||
"front\/forums_responsive.css",
|
||||
"front\/forums.css"
|
||||
],
|
||||
"removed": []
|
||||
},
|
||||
"resources": {
|
||||
"added": [],
|
||||
"edited": [],
|
||||
"removed": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 106101,
|
||||
"name": "4.6.0 Beta 1.1",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"added": [
|
||||
"app=forums&module=forums&controller=forums&searchResult=form_2_allow_anonymous",
|
||||
"app=forums&module=forums&controller=forums&searchResult=forum_best_answer"
|
||||
],
|
||||
"edited": [
|
||||
"app=forums&module=forums&controller=forums",
|
||||
"app=forums&module=forums&controller=savedActions"
|
||||
],
|
||||
"removed": [
|
||||
"app=forums&module=forums&controller=forums&do=form",
|
||||
"app=forums&module=forums&controller=forums&do=form&searchResult=form_2_allow_anonymous",
|
||||
"app=forums&module=forums&controller=forums&do=form&searchResult=forum_best_answer",
|
||||
"app=forums&module=forums&controller=savedActions&do=form"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 106103,
|
||||
"name": "4.6.0 Beta 2",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": true,
|
||||
"theme": true,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": true,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"normal": {
|
||||
"added": [
|
||||
"forums_sg_lc"
|
||||
],
|
||||
"edited": [],
|
||||
"removed": []
|
||||
},
|
||||
"js": {
|
||||
"added": [],
|
||||
"edited": [],
|
||||
"removed": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"html": {
|
||||
"added": [],
|
||||
"edited": [
|
||||
"front\/topics\/postContainer"
|
||||
],
|
||||
"removed": []
|
||||
},
|
||||
"css": {
|
||||
"added": [],
|
||||
"edited": [
|
||||
"front\/forums_responsive.css"
|
||||
],
|
||||
"removed": []
|
||||
},
|
||||
"resources": {
|
||||
"added": [],
|
||||
"edited": [],
|
||||
"removed": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 106104,
|
||||
"name": "4.6.0 Beta 3",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 106105,
|
||||
"name": "4.6.0 Beta 3.1",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 106106,
|
||||
"name": "4.6.0 Beta 4",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": 106107,
|
||||
"name": "4.6.0",
|
||||
"steps": {
|
||||
"queries": false,
|
||||
"lang": false,
|
||||
"theme": false,
|
||||
"themeSettings": false,
|
||||
"javascript": false,
|
||||
"emailTemplates": false,
|
||||
"hooks": false,
|
||||
"acpSearchKeywords": false,
|
||||
"settings": false,
|
||||
"tasks": false,
|
||||
"modules": false,
|
||||
"widgets": false,
|
||||
"whatsnew": false,
|
||||
"customOptions": false,
|
||||
"customRoutines": false
|
||||
},
|
||||
"forceMainUpgrader": false,
|
||||
"forceManualDownloadNoCiC": false,
|
||||
"forceManualDownloadCiC": false
|
||||
}
|
||||
@@ -25,7 +25,8 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
{
|
||||
use \IPS\Content\ClubContainer;
|
||||
use \IPS\Node\Colorize;
|
||||
|
||||
use \IPS\Node\Statistics;
|
||||
|
||||
/**
|
||||
* @brief [ActiveRecord] Multiton Store
|
||||
*/
|
||||
@@ -304,7 +305,7 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
*/
|
||||
public function get__sortBy()
|
||||
{
|
||||
return $this->sort_key;
|
||||
return $this->sort_key ?: 'last_post';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -352,6 +353,7 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
$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;
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
@@ -361,6 +363,7 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
$this->last_poster_name = '';
|
||||
$this->last_title = NULL;
|
||||
$this->last_id = NULL;
|
||||
$this->last_poster_anon = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -372,21 +375,24 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
$this->last_title = $comment->item()->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();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get last comment time
|
||||
*
|
||||
* @note This should return the last comment time for this node only, not for children nodes
|
||||
* @param \IPS\Member|NULL $member MemberObject
|
||||
* @return \IPS\DateTime|NULL
|
||||
*/
|
||||
public function getLastCommentTime()
|
||||
public function getLastCommentTime( \IPS\Member $member = NULL )
|
||||
{
|
||||
if( !$this->memberCanAccessOthersTopics( \IPS\Member::loggedIn() ) )
|
||||
$member = $member ?: \IPS\Member::loggedIn();
|
||||
if( !$this->memberCanAccessOthersTopics( $member ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$select = \IPS\Db::i()->select('*', 'forums_posts', array("forums_posts.queued=0 AND forums_topics.forum_id={$this->id} AND forums_topics.approved=1 AND forums_topics.starter_id=?", \IPS\Member::loggedIn()->member_id), 'forums_posts.post_date DESC', 1)->join('forums_topics', 'forums_topics.tid=forums_posts.topic_id')->first();
|
||||
$select = \IPS\Db::i()->select('*', 'forums_posts', array("forums_posts.queued=0 AND forums_topics.forum_id={$this->id} AND forums_topics.approved=1 AND forums_topics.starter_id=?", $member->member_id), 'forums_posts.post_date DESC', 1)->join('forums_topics', 'forums_topics.tid=forums_posts.topic_id')->first();
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
{
|
||||
@@ -697,21 +703,24 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
|
||||
if ( \in_array( $permissionCheck, array( 'read', 'add' ) ) )
|
||||
{
|
||||
$whereString = 'password=? OR ' . \IPS\Db::i()->findInSet( 'forums_forums.password_override', $member->groups );
|
||||
$whereParams = array( NULL );
|
||||
if ( $member->member_id === \IPS\Member::loggedIn()->member_id )
|
||||
if ( static::hasPasswordForums() )
|
||||
{
|
||||
foreach ( \IPS\Request::i()->cookie as $k => $v )
|
||||
$whereString = 'password=? OR ' . \IPS\Db::i()->findInSet( 'forums_forums.password_override', $member->groups );
|
||||
$whereParams = array( NULL );
|
||||
if ( $member->member_id === \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
if ( mb_substr( $k, 0, 13 ) === 'ipbforumpass_' )
|
||||
foreach ( \IPS\Request::i()->cookie as $k => $v )
|
||||
{
|
||||
$whereString .= ' OR ( forums_forums.id=? AND MD5(forums_forums.password)=? )';
|
||||
$whereParams[] = (int) mb_substr( $k, 13 );
|
||||
$whereParams[] = $v;
|
||||
if ( mb_substr( $k, 0, 13 ) === 'ipbforumpass_' )
|
||||
{
|
||||
$whereString .= ' OR ( forums_forums.id=? AND MD5(forums_forums.password)=? )';
|
||||
$whereParams[] = (int) mb_substr( $k, 13 );
|
||||
$whereParams[] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
$where[] = array_merge( array( '( ' . $whereString . ' )' ), $whereParams );
|
||||
}
|
||||
$where[] = array_merge( array( '( ' . $whereString . ' )' ), $whereParams );
|
||||
}
|
||||
|
||||
return parent::loadIntoMemory( $permissionCheck, $member, $where );
|
||||
@@ -897,7 +906,8 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
'category' => array(
|
||||
"form_{$id}_tab_forum_display",
|
||||
'forum_rules_title',
|
||||
'forum_rules_text'
|
||||
'forum_rules_text',
|
||||
'forum_use_feature_color'
|
||||
),
|
||||
'redirect' => array(
|
||||
'forum_password_on',
|
||||
@@ -938,14 +948,14 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
$form->add( new \IPS\Helpers\Form\Color( 'forum_feature_color', $this->feature_color ?: '', FALSE, array(), NULL, NULL, NULL, 'forum_feature_color' ) );
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Upload( 'forum_icon', $this->icon ? \IPS\File::get( 'forums_Icons', $this->icon ) : NULL, FALSE, array( 'image' => TRUE, 'storageExtension' => 'forums_Icons' ), NULL, NULL, NULL, 'forum_icon' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Upload( 'forum_card_image', $this->card_image ? \IPS\File::get( 'forums_Cards', $this->card_image ) : NULL, FALSE, array( 'image' => TRUE, 'storageExtension' => 'forums_Cards', 'allowStockPhotos' => TRUE ), NULL, NULL, NULL, 'forum_card_image' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Upload( 'forum_card_image', $this->card_image ? \IPS\File::get( 'forums_Cards', $this->card_image ) : NULL, FALSE, array( 'image' => array( 'maxWidth' => 800, 'maxHeight' => 800 ), 'storageExtension' => 'forums_Cards', 'allowStockPhotos' => TRUE ), NULL, NULL, NULL, 'forum_card_image' ) );
|
||||
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Url( 'forum_redirect_url', $this->id ? $this->redirect_url : array(), FALSE, array( 'placeholder' => 'http://www.example.com/' ), NULL, NULL, NULL, 'forum_redirect_url' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'forum_redirect_hits', $this->id ? $this->redirect_hits : 0, FALSE, array(), NULL, NULL, NULL, 'forum_redirect_hits' ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'forum_password_on', $this->id ? ( $this->password !== NULL ) : FALSE, FALSE, array( 'togglesOn' => array( 'forum_password', 'forum_password_override' ) ), NULL, NULL, NULL, 'forum_password_on' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'forum_password', $this->password, FALSE, array(), NULL, NULL, NULL, 'forum_password' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'forum_password_override', $this->id ? explode( ',', $this->password_override ) : array(), FALSE, array( 'options' => $groups, 'multiple' => TRUE ), NULL, NULL, NULL, 'forum_password_override' ) );
|
||||
$form->add( new \IPS\Helpers\Form\CheckboxSet( 'forum_password_override', $this->id ? explode( ',', $this->password_override ) : array(), FALSE, array( 'options' => $groups, 'multiple' => TRUE ), NULL, NULL, NULL, 'forum_password_override' ) );
|
||||
if ( \count( \IPS\Theme::themes() ) > 1 )
|
||||
{
|
||||
$themes = array( 0 => 'forum_skin_id_default' );
|
||||
@@ -1018,8 +1028,8 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
$form->addHeader( 'forum_display_topic' );
|
||||
$form->addHeader( 'forum_display_question' );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'bw_enable_answers_member', $this->id ? $this->forums_bitoptions['bw_enable_answers_member'] : TRUE, FALSE, array(), NULL, NULL, NULL, 'bw_enable_answers_member' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'forum_qa_rate_questions', $this->id ? ( ( $this->qa_rate_questions == '*' or $this->qa_rate_questions === NULL ) ? '*' : explode( ',', $this->qa_rate_questions ) ) : '*', FALSE, array( 'options' => $groupsNoGuests, 'unlimited' => '*', 'multiple' => TRUE ), NULL, NULL, NULL, 'forum_qa_rate_questions' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Select( '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 ), NULL, NULL, NULL, 'forum_qa_rate_answers' ) );
|
||||
$form->add( new \IPS\Helpers\Form\CheckboxSet( 'forum_qa_rate_questions', $this->id ? ( ( $this->qa_rate_questions == '*' or $this->qa_rate_questions === NULL ) ? '*' : explode( ',', $this->qa_rate_questions ) ) : '*', FALSE, array( 'options' => $groupsNoGuests, 'unlimited' => '*', 'multiple' => TRUE, 'impliedUnlimited' => TRUE ), NULL, NULL, NULL, 'forum_qa_rate_questions' ) );
|
||||
$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' ) );
|
||||
@@ -1048,6 +1058,7 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
$form->add( new \IPS\Helpers\Form\CheckboxSet( 'forum_preview_posts', $previewPosts, FALSE, array( 'options' => array( 'topics' => 'forum_preview_posts_topics', 'posts' => 'forum_preview_posts_posts' ) ), NULL, NULL, NULL, 'forum_preview_posts' ) );
|
||||
$form->add( new \IPS\Helpers\Form\CheckboxSet( 'forum_preview_posts_qa', $previewPosts, FALSE, array( 'options' => array( 'topics' => 'forum_preview_posts_questions', 'posts' => 'forum_preview_posts_answers' ) ), NULL, NULL, NULL, 'forum_preview_posts_qa' ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'forum_inc_postcount', $this->id ? $this->inc_postcount : TRUE, FALSE, array() ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'allow_anonymous', $this->id ? $this->allow_anonymous : FALSE, FALSE, array() ) );
|
||||
$form->addHeader( 'polls' );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'forum_allow_poll', $this->id ? $this->allow_poll : TRUE, FALSE, array() ) );
|
||||
$form->addHeader( 'posting_requirements' );
|
||||
@@ -1290,6 +1301,8 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
*/
|
||||
public function postSaveForm( $values )
|
||||
{
|
||||
unset( \IPS\Data\Store::i()->forumsHavePasswords );
|
||||
|
||||
\IPS\File::claimAttachments( 'forums-new-forum', $this->id, NULL, 'description', TRUE );
|
||||
\IPS\File::claimAttachments( 'forums-new-permerror', $this->id, NULL, 'permerror', TRUE );
|
||||
\IPS\File::claimAttachments( 'forums-new-rules', $this->id, NULL, 'rules', TRUE );
|
||||
@@ -1343,7 +1356,9 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
\IPS\File::get( 'forums_Icons', $this->icon )->delete();
|
||||
}
|
||||
catch( \Exception $ex ) { }
|
||||
|
||||
|
||||
unset( \IPS\Data\Store::i()->forumsHavePasswords );
|
||||
|
||||
parent::delete();
|
||||
|
||||
foreach ( array( 'rules_title' => "forums_forum_{$this->id}_rulestitle", 'rules_text' => "forums_forum_{$this->id}_rules", 'permission_custom_error' => "forums_forum_{$this->id}_permerror" ) as $fieldKey => $langKey )
|
||||
@@ -1386,6 +1401,7 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
|
||||
$oldId = $this->id;
|
||||
$oldIcon = $this->icon;
|
||||
$oldGridImage = $this->card_image;
|
||||
|
||||
$this->show_rules = 0;
|
||||
|
||||
@@ -1412,6 +1428,22 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
|
||||
$this->save();
|
||||
}
|
||||
|
||||
if ( $oldGridImage )
|
||||
{
|
||||
try
|
||||
{
|
||||
$gridImg = \IPS\File::get( 'forums_Cards', $oldGridImage );
|
||||
$newImage = \IPS\File::create( 'forums_Cards', $gridImg->originalFilename, $gridImg->contents() );
|
||||
$this->card_image = (string) $newImage;
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
$this->card_image = NULL;
|
||||
}
|
||||
|
||||
$this->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1449,7 +1481,7 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
{
|
||||
$forumsTheMemberIsModeratorOf = $member->modPermission('forums');
|
||||
|
||||
if ( $forumsTheMemberIsModeratorOf === TRUE ) // All forums
|
||||
if ( $forumsTheMemberIsModeratorOf === TRUE OR $forumsTheMemberIsModeratorOf == -1 ) // All forums
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1490,7 +1522,12 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
{
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_moderators' ) as $moderator )
|
||||
{
|
||||
if ( $moderator['perms'] === '*' or \in_array( 'can_read_all_topics', explode( ',', $moderator['perms'] ) ) )
|
||||
$json = json_decode( $moderator['perms'], TRUE );
|
||||
|
||||
if ( $moderator['perms'] === '*' OR
|
||||
(
|
||||
!empty( $json['can_read_all_topics'] ) AND ( isset( $json['forums'] ) AND ( $json['forums'] === -1 OR \in_array( $this->_id, $json['forums'] ) ) )
|
||||
) )
|
||||
{
|
||||
if( $moderator['type'] === 'g' )
|
||||
{
|
||||
@@ -1503,7 +1540,7 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$return = ( $normal == '*' ) ? array_unique( $return ) : array_intersect( explode( ',', $normal ), array_unique( $return ) );
|
||||
|
||||
if( \count( $members ) )
|
||||
@@ -1761,9 +1798,10 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
* @apiresponse int id ID number
|
||||
* @apiresponse string name Forum name
|
||||
* @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|null parentId Parent Node ID
|
||||
* @clientapiresponse object|null permissions Node permissions
|
||||
*/
|
||||
public function apiOutput( \IPS\Member $authorizedMember = NULL )
|
||||
@@ -1775,12 +1813,27 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
}
|
||||
$path[] = $this->_title;
|
||||
|
||||
$type = 'discussions';
|
||||
if ( $this->redirect_url )
|
||||
{
|
||||
$type = 'redirect';
|
||||
}
|
||||
elseif ( !$this->sub_can_post )
|
||||
{
|
||||
$type = 'category';
|
||||
}
|
||||
elseif ( $this->forums_bitoptions['bw_enable_answers'] )
|
||||
{
|
||||
$type = 'questions';
|
||||
}
|
||||
|
||||
$return = array(
|
||||
'id' => $this->id,
|
||||
'name' => $this->_title,
|
||||
'path' => implode( ' > ', $path ),
|
||||
'topics' => $this->topics,
|
||||
'url' => (string) $this->url(),
|
||||
'id' => $this->id,
|
||||
'name' => $this->_title,
|
||||
'path' => implode( ' > ', $path ),
|
||||
'type' => $type,
|
||||
'topics' => $this->topics,
|
||||
'url' => (string) $this->url(),
|
||||
'parentId' => static::$databaseColumnParent ? $this->{static::$databaseColumnParent} : NULL
|
||||
);
|
||||
|
||||
@@ -1963,6 +2016,21 @@ class _Forum extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
return $method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if this forum has a password set or not
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static function hasPasswordForums()
|
||||
{
|
||||
if ( ! isset( \IPS\Data\Store::i()->forumsHavePasswords ) )
|
||||
{
|
||||
\IPS\Data\Store::i()->forumsHavePasswords = (bool) \IPS\Db::i()->select( 'COUNT(*)', 'forums_forums', array( 'password IS NOT NULL' ) )->first();
|
||||
}
|
||||
|
||||
return \IPS\Data\Store::i()->forumsHavePasswords;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get URL
|
||||
*
|
||||
|
||||
@@ -109,12 +109,21 @@ class _ArchivedPost extends Post
|
||||
* @param \IPS\Member $member The memner
|
||||
* @return int
|
||||
*/
|
||||
public static function memberPostCount( \IPS\Member $member )
|
||||
public static function memberPostCount( \IPS\Member $member, bool $includeNonPostCountIncreasing = FALSE, bool $includeHiddenAndPendingApproval = TRUE )
|
||||
{
|
||||
return static::db()->select( 'COUNT(*)', 'forums_archive_posts', array(
|
||||
array( 'archive_author_id=?', $member->member_id ),
|
||||
array( \IPS\Db::i()->in( 'archive_forum_id', iterator_to_array( \IPS\Db::i()->select( 'id', 'forums_forums', 'inc_postcount=0' ) ), TRUE ) )
|
||||
) )->first();
|
||||
$where = [];
|
||||
$where[] = [ 'archive_author_id=?', $member->member_id ];
|
||||
|
||||
if ( !$includeNonPostCountIncreasing )
|
||||
{
|
||||
$where[] = [ \IPS\Db::i()->in( 'archive_forum_id', iterator_to_array( \IPS\Db::i()->select( 'id', 'forums_forums', 'inc_postcount=0' ) ) ) ];
|
||||
}
|
||||
if ( !$includeHiddenAndPendingApproval )
|
||||
{
|
||||
$where[] = [ 'archive_queued=0' ];
|
||||
}
|
||||
|
||||
return \IPS\Db::i()->select( 'COUNT(*)', 'forums_posts', $where )->first();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,9 +21,9 @@ if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
/**
|
||||
* Post Model
|
||||
*/
|
||||
class _Post extends \IPS\Content\Comment implements \IPS\Content\EditHistory, \IPS\Content\Hideable, \IPS\Content\Shareable, \IPS\Content\Searchable, \IPS\Content\Embeddable
|
||||
class _Post extends \IPS\Content\Comment implements \IPS\Content\EditHistory, \IPS\Content\Hideable, \IPS\Content\Shareable, \IPS\Content\Searchable, \IPS\Content\Embeddable, \IPS\Content\Anonymous
|
||||
{
|
||||
use \IPS\Content\Reactable, \IPS\Content\Reportable;
|
||||
use \IPS\Content\Reactable, \IPS\Content\Reportable, \IPS\Content\Recognizable;
|
||||
|
||||
/**
|
||||
* @brief [ActiveRecord] Multiton Store
|
||||
@@ -75,7 +75,8 @@ class _Post extends \IPS\Content\Comment implements \IPS\Content\EditHistory, \I
|
||||
'edit_member_name' => 'edit_name',
|
||||
'edit_reason' => 'post_edit_reason',
|
||||
'hidden' => 'queued',
|
||||
'first' => 'new_topic'
|
||||
'first' => 'new_topic',
|
||||
'is_anon' => 'post_field_t2'
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -178,25 +179,27 @@ class _Post extends \IPS\Content\Comment implements \IPS\Content\EditHistory, \I
|
||||
* @param \IPS\Member $member The memner
|
||||
* @return int
|
||||
*/
|
||||
public static function memberPostCount( \IPS\Member $member )
|
||||
public static function memberPostCount( \IPS\Member $member, bool $includeNonPostCountIncreasing = FALSE, bool $includeHiddenAndPendingApproval = TRUE )
|
||||
{
|
||||
return \IPS\Db::i()->select( 'COUNT(*)', 'forums_posts', array(
|
||||
'author_id=? AND forums_topics.forum_id IN(?)',
|
||||
$member->member_id,
|
||||
\IPS\Db::i()->select( 'id', 'forums_forums', 'inc_postcount=1' )
|
||||
) )->join( 'forums_topics', 'tid=topic_id' )->first() ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Post count for member
|
||||
*
|
||||
* @param \IPS\Member $member The memner
|
||||
* @return int
|
||||
*/
|
||||
public static function rawMemberPostCount( \IPS\Member $member )
|
||||
{
|
||||
/* Explicitly calling to the parent so we don't filter by forum ID */
|
||||
return parent::memberPostCount( $member );
|
||||
$where = [];
|
||||
$where[] = [ 'author_id=?', $member->member_id ];
|
||||
|
||||
if ( !$includeNonPostCountIncreasing )
|
||||
{
|
||||
$where[] = [ 'forums_topics.forum_id IN(?)', \IPS\Db::i()->select( 'id', 'forums_forums', 'inc_postcount=1' ) ];
|
||||
}
|
||||
if ( !$includeHiddenAndPendingApproval )
|
||||
{
|
||||
$where[] = [ 'queued=0' ];
|
||||
}
|
||||
|
||||
$query = \IPS\Db::i()->select( 'COUNT(*)', 'forums_posts', $where );
|
||||
if ( !$includeNonPostCountIncreasing )
|
||||
{
|
||||
$query = $query->join( 'forums_topics', 'tid=topic_id' );
|
||||
}
|
||||
|
||||
return $query->first();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -240,7 +243,7 @@ class _Post extends \IPS\Content\Comment implements \IPS\Content\EditHistory, \I
|
||||
* @param array $reactions Reaction Data
|
||||
* @return string
|
||||
*/
|
||||
public static function searchResult( array $indexData, array $authorData, array $itemData, array $containerData = NULL, array $reputationData, $reviewRating, $iPostedIn, $view, $asItem, $canIgnoreComments=FALSE, $template=NULL, $reactions=array() )
|
||||
public static function searchResult( array $indexData, array $authorData, array $itemData, ?array $containerData, array $reputationData, $reviewRating, $iPostedIn, $view, $asItem, $canIgnoreComments=FALSE, $template=NULL, $reactions=array() )
|
||||
{
|
||||
/* Password protected */
|
||||
if (
|
||||
@@ -405,6 +408,11 @@ class _Post extends \IPS\Content\Comment implements \IPS\Content\EditHistory, \I
|
||||
*/
|
||||
public static function _indefiniteArticle( array $containerData = NULL, \IPS\Lang $lang = NULL )
|
||||
{
|
||||
if ( !$containerData )
|
||||
{
|
||||
return parent::_indefiniteArticle( $containerData, $lang );
|
||||
}
|
||||
|
||||
$bitOptions = ( $containerData['forums_bitoptions'] instanceof \IPS\Patterns\Bitwise ) ? $containerData['forums_bitoptions'] : new \IPS\Patterns\Bitwise( array( 'forums_bitoptions' => $containerData['forums_bitoptions'] ), \IPS\forums\Forum::$bitOptions['forums_bitoptions'] );
|
||||
|
||||
if ( $bitOptions['bw_enable_answers'] )
|
||||
@@ -424,20 +432,32 @@ class _Post extends \IPS\Content\Comment implements \IPS\Content\EditHistory, \I
|
||||
* @param array|NULL $containerData Basic data about the container. Only includes columns returned by container::basicDataColumns()
|
||||
* @param \IPS\Lang|NULL $lang The language to use, or NULL for the language of the currently logged in member
|
||||
* @param array $options Options to pass to \IPS\Lang::addToStack
|
||||
* @param integer|boolean $count Count of things; if int > 1, uses pluralized version of definite article
|
||||
* @return string
|
||||
*/
|
||||
public static function _definiteArticle( array $containerData = NULL, \IPS\Lang $lang = NULL, $options = array() )
|
||||
public static function _definiteArticle( array $containerData = NULL, \IPS\Lang $lang = NULL, $options = array(), $count = FALSE )
|
||||
{
|
||||
if ( !$containerData )
|
||||
{
|
||||
return parent::_definiteArticle( $containerData, $lang, $options );
|
||||
}
|
||||
|
||||
$bitOptions = ( $containerData['forums_bitoptions'] instanceof \IPS\Patterns\Bitwise ) ? $containerData['forums_bitoptions'] : new \IPS\Patterns\Bitwise( array( 'forums_bitoptions' => $containerData['forums_bitoptions'] ), \IPS\forums\Forum::$bitOptions['forums_bitoptions'] );
|
||||
|
||||
if ( $bitOptions['bw_enable_answers'] )
|
||||
{
|
||||
$lang = $lang ?: \IPS\Member::loggedIn()->language();
|
||||
if( \is_int( $count ) )
|
||||
{
|
||||
$options['pluralize'] = array( $count );
|
||||
return $lang->addToStack( '__defart_answer_plural', FALSE, $options );
|
||||
}
|
||||
|
||||
return $lang->addToStack( '__defart_answer', FALSE, $options );
|
||||
}
|
||||
else
|
||||
{
|
||||
return parent::_definiteArticle( $containerData, $lang, $options );
|
||||
return parent::_definiteArticle( $containerData, $lang, $options, $count );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,9 +33,10 @@ class _Topic extends \IPS\Content\Item implements
|
||||
\IPS\Content\Ratings,
|
||||
\IPS\Content\Searchable,
|
||||
\IPS\Content\Embeddable,
|
||||
\IPS\Content\MetaData
|
||||
\IPS\Content\MetaData,
|
||||
\IPS\Content\Anonymous
|
||||
{
|
||||
use \IPS\Content\Reactable, \IPS\Content\Reportable, \IPS\Content\Statistics, \IPS\Content\Solvable;
|
||||
use \IPS\Content\Reactable, \IPS\Content\Reportable, \IPS\Content\Statistics, \IPS\Content\Solvable { toggleSolveComment as protected _toggleSolveComment; }
|
||||
|
||||
/**
|
||||
* @brief Not archived
|
||||
@@ -119,7 +120,9 @@ class _Topic extends \IPS\Content\Item implements
|
||||
'state' => 'state',
|
||||
'updated' => 'last_post',
|
||||
'meta_data' => 'topic_meta_data',
|
||||
'solved_comment_id' => 'topic_answered_pid'
|
||||
'solved_comment_id' => 'topic_answered_pid',
|
||||
'is_anon' => 'is_anon',
|
||||
'last_comment_anon' => 'last_poster_anon',
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -332,23 +335,27 @@ class _Topic extends \IPS\Content\Item implements
|
||||
{
|
||||
$joinContainer = TRUE;
|
||||
$member = $member ?: \IPS\Member::loggedIn();
|
||||
|
||||
$whereString = 'forums_forums.password=? OR ' . \IPS\Db::i()->findInSet( 'forums_forums.password_override', $member->groups );
|
||||
$whereParams = array( NULL );
|
||||
if ( \IPS\Dispatcher::hasInstance() AND $member->member_id === \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
foreach ( \IPS\Request::i()->cookie as $k => $v )
|
||||
$containerClass = static::$containerNodeClass;
|
||||
|
||||
if ( $containerClass::hasPasswordForums() )
|
||||
{
|
||||
$whereString = 'forums_forums.password=? OR ' . \IPS\Db::i()->findInSet( 'forums_forums.password_override', $member->groups );
|
||||
$whereParams = array( NULL );
|
||||
if ( \IPS\Dispatcher::hasInstance() AND $member->member_id === \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
if ( mb_substr( $k, 0, 13 ) === 'ipbforumpass_' )
|
||||
foreach ( \IPS\Request::i()->cookie as $k => $v )
|
||||
{
|
||||
$whereString .= ' OR ( forums_forums.id=? AND MD5(forums_forums.password)=? )';
|
||||
$whereParams[] = (int) mb_substr( $k, 13 );
|
||||
$whereParams[] = $v;
|
||||
if ( mb_substr( $k, 0, 13 ) === 'ipbforumpass_' )
|
||||
{
|
||||
$whereString .= ' OR ( forums_forums.id=? AND MD5(forums_forums.password)=? )';
|
||||
$whereParams[] = (int) mb_substr( $k, 13 );
|
||||
$whereParams[] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$where['container'][] = array_merge( array( '( ' . $whereString . ' )' ), $whereParams );
|
||||
}
|
||||
|
||||
$where['container'][] = array_merge( array( '( ' . $whereString . ' )' ), $whereParams );
|
||||
}
|
||||
|
||||
/* Don't show topics from forums in which topics only show to the poster */
|
||||
@@ -370,7 +377,7 @@ class _Topic extends \IPS\Content\Item implements
|
||||
$where['item'][] = array( 'forums_topics.starter_id=?', $member->member_id );
|
||||
}
|
||||
}
|
||||
elseif ( !$member->modPermission('can_read_all_topics') or ( $member->modPermission('forums') !== TRUE and !\in_array( $skipPermission->_id, $member->modPermission('forums') ) ) )
|
||||
elseif ( !$member->modPermission('can_read_all_topics') or ( \is_array( $member->modPermission('forums') ) and !\in_array( $skipPermission->_id, $member->modPermission('forums') ) ) )
|
||||
{
|
||||
$where['item'][] = array( 'forums_topics.starter_id=?', $member->member_id );
|
||||
}
|
||||
@@ -674,17 +681,16 @@ class _Topic extends \IPS\Content\Item implements
|
||||
/* Moderator actions */
|
||||
if ( isset( $values['topic_create_state'] ) )
|
||||
{
|
||||
if ( $this->canHide() )
|
||||
if( \in_array( 'hide', $values['topic_create_state'] ) )
|
||||
{
|
||||
if( \in_array( 'hide', $values['topic_create_state'] ) )
|
||||
if ( $this->canHide() )
|
||||
{
|
||||
$this->hide( NULL );
|
||||
}
|
||||
/* Only unhide if the topic is not pending approval */
|
||||
elseif( $this->hidden() !== 1 )
|
||||
{
|
||||
$this->unhide( NULL );
|
||||
}
|
||||
}
|
||||
elseif( $this->hidden() and $this->hidden() !== 1 and $this->canUnhide() )
|
||||
{
|
||||
$this->unhide( NULL );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1040,12 +1046,15 @@ class _Topic extends \IPS\Content\Item implements
|
||||
{
|
||||
parent::delete();
|
||||
|
||||
try
|
||||
if( \in_array( $this->archive_status, array( static::ARCHIVE_DONE, static::ARCHIVE_WORKING, static::ARCHIVE_RESTORE ) ) )
|
||||
{
|
||||
\IPS\forums\Topic\ArchivedPost::db()->delete( 'forums_archive_posts', array( 'archive_topic_id=?', $this->tid ) );
|
||||
try
|
||||
{
|
||||
\IPS\forums\Topic\ArchivedPost::db()->delete( 'forums_archive_posts', array( 'archive_topic_id=?', $this->tid ) );
|
||||
}
|
||||
/* catch db exceptions if e.g. if the connection credentials didn't work or if the database doesn't exist anymore */
|
||||
catch ( \IPS\Db\Exception $e ){}
|
||||
}
|
||||
/* catch db exceptions if e.g. if the connection credentials didn't work or if the database doesn't exist anymore */
|
||||
catch ( \IPS\Db\Exception $e ){}
|
||||
|
||||
\IPS\Db::i()->delete( 'forums_question_ratings', array( 'topic=?', $this->tid ) );
|
||||
\IPS\Db::i()->delete( 'forums_answer_ratings', array( 'topic=?', $this->tid ) );
|
||||
@@ -1314,7 +1323,25 @@ class _Topic extends \IPS\Content\Item implements
|
||||
*/
|
||||
public function containerAllowsMemberSolvable()
|
||||
{
|
||||
return $this->container()->forums_bitoptions['bw_enable_answers_member'];
|
||||
return ( $this->containerAllowsSolvable() AND $this->container()->forums_bitoptions['bw_enable_answers_member'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the solve value of a comment
|
||||
*
|
||||
* @param int $commentId The comment ID
|
||||
* @param boolean $value TRUE/FALSE value
|
||||
* @param \IPS\Member $member The member (null for currently logged in member)
|
||||
*/
|
||||
public function toggleSolveComment( $commentId, $value, \IPS\Member $member = NULL )
|
||||
{
|
||||
if ( $value )
|
||||
{
|
||||
$post = \IPS\forums\Topic\Post::load( $commentId );
|
||||
$post->author()->achievementAction( 'forums', 'AnswerMarkedBest', $post );
|
||||
}
|
||||
|
||||
return $this->_toggleSolveComment( $commentId, $value, $member );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1533,21 +1560,34 @@ class _Topic extends \IPS\Content\Item implements
|
||||
* @param array $containerData Basic data about the container. Only includes columns returned by container::basicDataColumns()
|
||||
* @param \IPS\Lang|NULL $lang The language to use, or NULL for the language of the currently logged in member
|
||||
* @param array $options Options to pass to \IPS\Lang::addToStack
|
||||
* @param integer|boolean $count Number of items. If not false, pluralized version of phrase will be used.
|
||||
* @return string
|
||||
*/
|
||||
public static function _definiteArticle( array $containerData = NULL, \IPS\Lang $lang = NULL, $options = array() )
|
||||
public static function _definiteArticle( array $containerData = NULL, \IPS\Lang $lang = NULL, $options = array(), $count = FALSE )
|
||||
{
|
||||
$bitOptions = ( $containerData['forums_bitoptions'] instanceof \IPS\Patterns\Bitwise ) ? $containerData['forums_bitoptions'] : new \IPS\Patterns\Bitwise( array( 'forums_bitoptions' => $containerData['forums_bitoptions'] ), \IPS\forums\Forum::$bitOptions['forums_bitoptions'] );
|
||||
if( $containerData !== NULL )
|
||||
{
|
||||
$bitOptions = ( $containerData['forums_bitoptions'] instanceof \IPS\Patterns\Bitwise ) ? $containerData['forums_bitoptions'] : new \IPS\Patterns\Bitwise( array( 'forums_bitoptions' => $containerData['forums_bitoptions'] ), \IPS\forums\Forum::$bitOptions['forums_bitoptions'] );
|
||||
|
||||
if ( $bitOptions['bw_enable_answers'] )
|
||||
{
|
||||
$lang = $lang ?: \IPS\Member::loggedIn()->language();
|
||||
|
||||
if( $count === TRUE || \is_int( $count ) )
|
||||
{
|
||||
if( \is_int( $count ) )
|
||||
{
|
||||
$options['pluralize'] = array( $count );
|
||||
}
|
||||
|
||||
return $lang->addToStack( '__defart_question_plural', FALSE, $options );
|
||||
}
|
||||
|
||||
return $lang->addToStack( '__defart_question', FALSE, $options );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $bitOptions['bw_enable_answers'] )
|
||||
{
|
||||
$lang = $lang ?: \IPS\Member::loggedIn()->language();
|
||||
return $lang->addToStack( '__defart_question', FALSE, $options );
|
||||
}
|
||||
else
|
||||
{
|
||||
return parent::_definiteArticle( $containerData, $lang, $options );
|
||||
}
|
||||
return parent::_definiteArticle( $containerData, $lang, $options, $count );
|
||||
}
|
||||
|
||||
/* !Sitemap */
|
||||
@@ -2149,8 +2189,6 @@ class _Topic extends \IPS\Content\Item implements
|
||||
|
||||
/* ! Reactions */
|
||||
|
||||
public $reputation = array();
|
||||
|
||||
/**
|
||||
* Reaction type
|
||||
*
|
||||
@@ -2265,4 +2303,34 @@ class _Topic extends \IPS\Content\Item implements
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* We need to force an index so that super long topics load when fetching IDs before running the main query
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
/**
|
||||
* We need to force an index so that super long topics load when fetching IDs before running the main query
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function forceIndexForPaginatedIds()
|
||||
{
|
||||
if ( ! $this->isArchived() )
|
||||
{
|
||||
return 'first_post';
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* WHERE clause for getting items for ACP overview statistics
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function overviewStatisticsWhere()
|
||||
{
|
||||
return array( array( \IPS\Db::i()->in( 'state', array( 'link', 'merged' ), TRUE ) ) );
|
||||
}
|
||||
}
|
||||
@@ -175,8 +175,9 @@ class _archive extends \IPS\Task
|
||||
/* Insert */
|
||||
$this->storage->replace( 'forums_archive_posts', $archive );
|
||||
|
||||
/* Update reports table */
|
||||
/* Update reports and promote tables */
|
||||
\IPS\Db::i()->update( 'core_rc_index', array( 'class' => 'IPS\forums\Topic\ArchivedPost' ), array( 'class=? AND content_id=?', 'IPS\forums\Topic\Post', $post['pid'] ) );
|
||||
\IPS\Db::i()->update( 'core_social_promote', array( 'promote_class' => 'IPS\forums\Topic\ArchivedPost' ), array( 'promote_class=? AND promote_class_id=?', 'IPS\forums\Topic\Post', $post['pid'] ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,7 +27,7 @@ class _unarchive extends \IPS\Task
|
||||
* @brief Number of items to process per cycle
|
||||
*/
|
||||
const PROCESS_PER_BATCH = 250;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Storage database
|
||||
*/
|
||||
@@ -56,9 +56,6 @@ class _unarchive extends \IPS\Task
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Init */
|
||||
$postsProcessed = 0;
|
||||
|
||||
/* Connect to the remote DB if needed */
|
||||
if ( \IPS\CIC2 )
|
||||
{
|
||||
@@ -77,10 +74,21 @@ class _unarchive extends \IPS\Task
|
||||
'sql_utf8mb4' => isset( \IPS\Settings::i()->sql_utf8mb4 ) ? \IPS\Settings::i()->sql_utf8mb4 : FALSE
|
||||
) );
|
||||
}
|
||||
|
||||
/* Loop topics */
|
||||
foreach ( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'forums_topics', array( 'topic_archive_status=?', \IPS\forums\Topic::ARCHIVE_RESTORE ), 'tid ASC', 250 ), 'IPS\forums\Topic' ) as $topic )
|
||||
{
|
||||
|
||||
$this->runUntilTimeout( function(){
|
||||
/* Init */
|
||||
$postsProcessed = 0;
|
||||
|
||||
/* Loop topics */
|
||||
try
|
||||
{
|
||||
$topic = \IPS\forums\Topic::constructFromData( \IPS\Db::i()->select( '*', 'forums_topics', array( 'topic_archive_status=?', \IPS\forums\Topic::ARCHIVE_RESTORE ), 'tid ASC', 1 )->first() );
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Do as many posts as we can */
|
||||
$offset = \IPS\Db::i()->select( 'MAX(pid)', 'forums_posts', array( 'topic_id=?', $topic->tid ) )->first();
|
||||
foreach ( $this->storage->select( '*', 'forums_archive_posts', array( 'archive_id>? AND archive_topic_id=?', \intval( $offset ), $topic->tid ), 'archive_id ASC', static::PROCESS_PER_BATCH - $postsProcessed ) as $post )
|
||||
@@ -89,7 +97,7 @@ class _unarchive extends \IPS\Task
|
||||
$postsProcessed++;
|
||||
if ( $postsProcessed >= static::PROCESS_PER_BATCH )
|
||||
{
|
||||
break 2;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,9 +105,9 @@ class _unarchive extends \IPS\Task
|
||||
\IPS\Content\Search\Index::i()->indexSingleItem( $topic );
|
||||
\IPS\Db::i()->update( 'forums_topics', array( 'topic_archive_status' => \IPS\forums\Topic::ARCHIVE_EXCLUDE ), array( 'tid=?', $topic->tid ) );
|
||||
$this->storage->delete( 'forums_archive_posts', array( 'archive_topic_id=?', $topic->tid ) );
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return TRUE;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,8 +142,9 @@ class _unarchive extends \IPS\Task
|
||||
/* Insert */
|
||||
\IPS\Db::i()->replace( 'forums_posts', $row );
|
||||
|
||||
/* Update reports table */
|
||||
/* Update reports and promotes tables */
|
||||
\IPS\Db::i()->update( 'core_rc_index', array( 'class' => 'IPS\forums\Topic\Post' ), array( 'class=? AND content_id=?', 'IPS\forums\Topic\ArchivedPost', $post['archive_id'] ) );
|
||||
\IPS\Db::i()->update( 'core_social_promote', array( 'promote_class' => 'IPS\forums\Topic\Post' ), array( "promote_class=? AND promote_class_id=?", 'IPS\forums\Topic\ArchivedPost', $post['archive_id'] ) );
|
||||
|
||||
return \IPS\forums\Topic\Post::constructFromData( $row );
|
||||
}
|
||||
|
||||
@@ -38,6 +38,11 @@ class _forumStatistics extends \IPS\Widget\StaticCache
|
||||
*/
|
||||
public $plugin = '';
|
||||
|
||||
/**
|
||||
* @brief Cache Expiration - 24h
|
||||
*/
|
||||
public $cacheExpiration = 86400;
|
||||
|
||||
/**
|
||||
* Render a widget
|
||||
*
|
||||
@@ -46,12 +51,29 @@ class _forumStatistics extends \IPS\Widget\StaticCache
|
||||
public function render()
|
||||
{
|
||||
$stats = array();
|
||||
|
||||
$stats['total_posts'] = \IPS\Db::i()->select( "COUNT(*)", 'forums_posts', array( 'queued = ?', 0 ) )->first();
|
||||
|
||||
$approxRows = \IPS\Db::i()->query( "SHOW TABLE STATUS LIKE '" . \IPS\Db::i()->prefix . "forums_posts';" )->fetch_assoc();
|
||||
|
||||
if( (int) $approxRows['Rows'] > 1000000 )
|
||||
{
|
||||
$stats['total_posts'] = (int) $approxRows['Rows'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$stats['total_posts'] = \IPS\Db::i()->select( "COUNT(*)", 'forums_posts', array( 'queued = ?', 0 ) )->first();
|
||||
}
|
||||
|
||||
if ( \IPS\Settings::i()->archive_on )
|
||||
{
|
||||
$stats['total_posts'] += \IPS\forums\Topic\ArchivedPost::db()->select( 'COUNT(*)', 'forums_archive_posts', array( 'archive_queued = ?', 0 ) )->first();
|
||||
$approxRows = \IPS\forums\Topic\ArchivedPost::db()->query( "SHOW TABLE STATUS LIKE '" . \IPS\forums\Topic\ArchivedPost::db()->prefix . "forums_archive_posts';" )->fetch_assoc();
|
||||
if( (int) $approxRows['Rows'] > 1000000 )
|
||||
{
|
||||
$stats['total_posts'] += (int) $approxRows['Rows'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$stats['total_posts'] += \IPS\forums\Topic\ArchivedPost::db()->select( 'COUNT(*)', 'forums_archive_posts', array( 'archive_queued = ?', 0 ) )->first();
|
||||
}
|
||||
}
|
||||
|
||||
$stats['total_topics'] = \IPS\Db::i()->select( "COUNT(*)", 'forums_topics', array( 'approved = ?', 1 ) )->first();
|
||||
|
||||
@@ -82,10 +82,20 @@ class _postFeed extends \IPS\Content\WidgetComment
|
||||
*/
|
||||
protected function buildWhere()
|
||||
{
|
||||
$class = static::$class;
|
||||
$itemClass = $class::$itemClass;
|
||||
$containerClass = $itemClass::$containerNodeClass;
|
||||
$where = parent::buildWhere();
|
||||
if ( !isset( $this->configuration['widget_feed_use_perms'] ) or $this->configuration['widget_feed_use_perms'] )
|
||||
{
|
||||
$where['container'][] = array( 'forums_forums.password IS NULL AND forums_forums.can_view_others=1' );
|
||||
if ( $containerClass::hasPasswordForums() )
|
||||
{
|
||||
$where['container'][] = array( 'forums_forums.password IS NULL AND forums_forums.can_view_others=1' );
|
||||
}
|
||||
else
|
||||
{
|
||||
$where['container'][] = array( 'forums_forums.can_view_others=1' );
|
||||
}
|
||||
}
|
||||
return $where;
|
||||
}
|
||||
|
||||
@@ -76,10 +76,24 @@ class _topicFeed extends \IPS\Content\Widget
|
||||
*/
|
||||
protected function buildWhere()
|
||||
{
|
||||
$class = static::$class;
|
||||
$containerClass = $class::$containerNodeClass;
|
||||
$where = parent::buildWhere();
|
||||
if ( !isset( $this->configuration['widget_feed_use_perms'] ) or $this->configuration['widget_feed_use_perms'] )
|
||||
{
|
||||
$where['container'][] = array( 'forums_forums.password IS NULL AND forums_forums.can_view_others=1' );
|
||||
if ( $containerClass::hasPasswordForums() )
|
||||
{
|
||||
$where['container'][] = array( 'forums_forums.password IS NULL AND forums_forums.can_view_others=1' );
|
||||
}
|
||||
else
|
||||
{
|
||||
$where['container'][] = array( 'forums_forums.can_view_others=1' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $this->configuration['widget_feed_status_solved'] ) and $this->configuration['widget_feed_status_solved'] == 'unsolved' and empty( $this->configuration['widget_feed_container'] ) )
|
||||
{
|
||||
$where['container'][] = array( '( (' . \IPS\Db::i()->bitwiseWhere( \IPS\forums\Forum::$bitOptions['forums_bitoptions'], 'bw_enable_answers' ) . ') OR ( ' . \IPS\Db::i()->bitwiseWhere( \IPS\forums\Forum::$bitOptions['forums_bitoptions'], 'bw_enable_answers_moderator' ) . ' ) )' );
|
||||
}
|
||||
|
||||
return $where;
|
||||
|
||||
Reference in new issue
Block a user