From bdd76c782d94750b2671a122b4391cba6801204d Mon Sep 17 00:00:00 2001 From: John Henley Date: Thu, 18 Sep 2025 18:14:32 +0000 Subject: [PATCH 01/20] ENH: Change phrasing of "Subscribe to Topics" to "Auto-Subscribe to My Topics" #1579 --- .../App_LocalResources/SharedResources.de-DE.resx | 6 +++--- .../App_LocalResources/SharedResources.es-ES.resx | 6 +++--- .../App_LocalResources/SharedResources.fr-FR.resx | 6 +++--- .../App_LocalResources/SharedResources.it-IT.resx | 6 +++--- .../App_LocalResources/SharedResources.nl-NL.resx | 6 +++--- Dnn.CommunityForums/App_LocalResources/SharedResources.resx | 2 +- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Dnn.CommunityForums/App_LocalResources/SharedResources.de-DE.resx b/Dnn.CommunityForums/App_LocalResources/SharedResources.de-DE.resx index 0c91d5a87..1e06588d5 100644 --- a/Dnn.CommunityForums/App_LocalResources/SharedResources.de-DE.resx +++ b/Dnn.CommunityForums/App_LocalResources/SharedResources.de-DE.resx @@ -814,9 +814,6 @@ Von Dies ist Ihre Standardeinstellung, wenn Sie ein Thema erstellen oder eine Antwort hinzufügen. Dies hat keine Auswirkungen auf Abonnements auf Forumsebene. - - Themen abonnieren - Der Forenadministrator hat Ihnen möglicherweise erlaubt, verschiedene Abonnementformen auszuwählen. Sie können Ihre gewünschte Präferenz auswählen. @@ -1862,4 +1859,7 @@ Von Abmelden + + Automatisches Abonnieren von "Meine Themen" + \ No newline at end of file diff --git a/Dnn.CommunityForums/App_LocalResources/SharedResources.es-ES.resx b/Dnn.CommunityForums/App_LocalResources/SharedResources.es-ES.resx index da5d91662..5ed99899e 100644 --- a/Dnn.CommunityForums/App_LocalResources/SharedResources.es-ES.resx +++ b/Dnn.CommunityForums/App_LocalResources/SharedResources.es-ES.resx @@ -814,9 +814,6 @@ De Esta será su configuración predeterminada cuando cree un tema o agregue una respuesta. Esto no afecta a las suscripciones a nivel de foro. - - Suscribirse a Temas - Es posible que el administrador del foro le haya permitido elegir diferentes formas de suscripción. Puede seleccionar su preferencia deseada. @@ -1861,4 +1858,7 @@ De Anular la suscripción + + Suscríbete automáticamente a Mis temas + \ No newline at end of file diff --git a/Dnn.CommunityForums/App_LocalResources/SharedResources.fr-FR.resx b/Dnn.CommunityForums/App_LocalResources/SharedResources.fr-FR.resx index 0797308dd..2d6842640 100644 --- a/Dnn.CommunityForums/App_LocalResources/SharedResources.fr-FR.resx +++ b/Dnn.CommunityForums/App_LocalResources/SharedResources.fr-FR.resx @@ -811,9 +811,6 @@ De, Ceci sera votre réglage par défault lors de la création d'un sujet ou l'ajout d'une réponse. Ceci n'affecte pas l'abonnement au niveau du forum. - - S'abonner à des sujets - L'administrateur du forum peut vous avoir permis de choisir différents formulaires pour les abonnements. Vous pouvez choisir votre préférence ici. @@ -1858,4 +1855,7 @@ De, Se désabonner + + S’abonner automatiquement à Mes sujets + \ No newline at end of file diff --git a/Dnn.CommunityForums/App_LocalResources/SharedResources.it-IT.resx b/Dnn.CommunityForums/App_LocalResources/SharedResources.it-IT.resx index e8184e45d..93f69fa22 100644 --- a/Dnn.CommunityForums/App_LocalResources/SharedResources.it-IT.resx +++ b/Dnn.CommunityForums/App_LocalResources/SharedResources.it-IT.resx @@ -814,9 +814,6 @@ Da Questa sarà l'impostazione predefinita quando crei un argomento o aggiungi una risposta. Ciò non influisce sulle iscrizioni a livello di forum. - - Iscriviti agli argomenti - L'amministratore del forum potrebbe averti permesso di scegliere diverse forme di iscrizione. È possibile selezionare la preferenza desiderata. @@ -1861,4 +1858,7 @@ Da Disiscrizione + + Iscrizione automatica ai miei argomenti + \ No newline at end of file diff --git a/Dnn.CommunityForums/App_LocalResources/SharedResources.nl-NL.resx b/Dnn.CommunityForums/App_LocalResources/SharedResources.nl-NL.resx index b39bed637..254dfc2c4 100644 --- a/Dnn.CommunityForums/App_LocalResources/SharedResources.nl-NL.resx +++ b/Dnn.CommunityForums/App_LocalResources/SharedResources.nl-NL.resx @@ -900,9 +900,6 @@ Type abonnement - - Abonneer op onderwerpen - Uw profiel is bijgewerkt. @@ -1897,4 +1894,7 @@ Van, Uitschrijven + + Automatisch abonneren op Mijn onderwerpen + \ No newline at end of file diff --git a/Dnn.CommunityForums/App_LocalResources/SharedResources.resx b/Dnn.CommunityForums/App_LocalResources/SharedResources.resx index 199ccb5e8..e1171912b 100644 --- a/Dnn.CommunityForums/App_LocalResources/SharedResources.resx +++ b/Dnn.CommunityForums/App_LocalResources/SharedResources.resx @@ -904,7 +904,7 @@ Subscription Type - Subscribe to Topics + Auto-Subscribe to My Topics Your profile has been updated. From 8ebe572f408f42b069665dc62c53ac2c0e809b6e Mon Sep 17 00:00:00 2001 From: John Henley Date: Tue, 23 Sep 2025 22:15:46 +0000 Subject: [PATCH 02/20] TASK: settings table revamp Refactor settings and modernize codebase Refactored settings management by replacing `SettingsInfo` with the new `ModuleSettings` class, streamlining handling of module settings. `SettingsInfo' is now used to manage feature settings Updated database schema to rename `GroupKey` to `SettingsKey` and removed obsolete functions and procedures. Introduced `SettingsController` for structured CRUD operations. Updated token replacement and template handling to align with the new settings structure. Modernized code with inline property initializers, string interpolation, and improved readability. Incremented module version to `09.02.00` and updated `.dnn` manifest files. Removed deprecated SQL functions and procedures. Updated unit tests and UI components to use `ModuleSettings`. Enhanced release notes and documentation to reflect changes. --- .github/copilot-instructions.md | 87 ++ Dnn.CommunityForums/Classic.ascx.cs | 26 +- .../Controllers/EmailController.cs | 4 +- .../Controllers/ForumController.cs | 2 +- .../Controllers/ForumGroupController.cs | 7 +- .../Controllers/ForumUserController.cs | 8 +- .../Controllers/SettingsController.cs | 91 ++ .../Controllers/TemplateController.cs | 6 +- .../Controllers/TopicController.cs | 2 +- .../Controllers/UrlController.cs | 4 +- .../CustomControls/HTML/TopicBrowser.cs | 2 +- .../ServerControls/QuickReply.cs | 2 +- .../CustomControls/ServerControls/TagCloud.cs | 2 +- .../ServerControls/TopicNavigator.cs | 2 +- .../ServerControls/TopicsNavigator.cs | 2 +- .../CustomControls/UserControls/ForumView.cs | 18 +- .../CustomControls/UserControls/Members.cs | 6 +- .../CustomControls/UserControls/SubmitForm.cs | 6 +- .../CustomControls/UserControls/TopicView.cs | 38 +- .../CustomControls/UserControls/TopicsView.cs | 34 +- .../UserControls/UserProfile.cs | 8 +- Dnn.CommunityForums/DnnCommunityForums.dnn | 15 +- .../DnnCommunityForums_Symbols.dnn | 4 +- .../Entities/FeatureSettings.cs | 8 +- .../Entities/ForumGroupInfo.cs | 20 +- Dnn.CommunityForums/Entities/ForumInfo.cs | 8 +- Dnn.CommunityForums/Entities/ForumUserInfo.cs | 42 +- Dnn.CommunityForums/Entities/SettingsInfo.cs | 43 + .../SqlDataProvider/SqlDataProvider.cs | 6 +- Dnn.CommunityForums/ReleaseNotes.txt | 25 +- .../Services/AdminServiceController.cs | 2 +- .../Services/Controllers/ControllerBase.cs | 4 +- .../Controllers/FeatureSettingsController.cs | 184 +++ .../Services/Controllers/ForumController.cs | 326 ++++- .../Controllers/ForumGroupController.cs | 310 +++++ .../Services/Controllers/UserController.cs | 1 + .../Services/Tokens/TokenReplacer.cs | 36 +- Dnn.CommunityForums/class/ActiveAdminBase.cs | 4 +- Dnn.CommunityForums/class/Cache.cs | 34 +- Dnn.CommunityForums/class/DataProvider.cs | 5 + Dnn.CommunityForums/class/ForumBase.cs | 2 +- Dnn.CommunityForums/class/ForumsConfig.cs | 78 +- Dnn.CommunityForums/class/ModuleSettings.cs | 209 ++++ Dnn.CommunityForums/class/Settings.cs | 375 ------ Dnn.CommunityForums/class/SettingsBase.cs | 198 +-- Dnn.CommunityForums/class/TemplateUtils.cs | 2 +- Dnn.CommunityForums/class/Utilities.cs | 2 +- .../components/Common/HandlerBase.cs | 4 +- Dnn.CommunityForums/components/Data/Common.cs | 4 +- .../components/Extensions/ReWriter.cs | 4 +- .../Helpers/UpgradeModuleSettings.cs | 10 +- .../components/Topics/TopicsController.cs | 2 +- .../admin_manageforums_forumeditor.ascx.cs | 92 +- .../controls/admin_manageforums_home.ascx.cs | 2 +- .../controls/admin_templates.ascx.cs | 2 +- Dnn.CommunityForums/controls/af_grid.ascx.cs | 20 +- Dnn.CommunityForums/controls/af_likes.ascx.cs | 14 +- .../controls/af_members.ascx.cs | 2 +- .../controls/af_modtopics.ascx.cs | 2 +- Dnn.CommunityForums/controls/af_post.ascx.cs | 22 +- .../controls/af_profile.ascx.cs | 6 +- .../controls/af_quickreply.ascx.cs | 4 +- .../controls/af_recycle_bin.ascx.cs | 2 +- .../controls/af_search.ascx.cs | 10 +- .../controls/af_sendto.ascx.cs | 8 +- .../controls/af_usersonline.ascx.cs | 2 +- .../controls/profile_mypreferences.ascx.cs | 4 +- Dnn.CommunityForums/feeds.aspx.cs | 2 +- .../sql/09.02.00.SqlDataProvider | 1057 +++++++++++++++++ .../sql/Uninstall.SqlDataProvider | 8 +- Dnn.CommunityForumsTests/TestBase.cs | 4 +- .../WebApiTests/WebApiForumGroupTests1.http | 39 + DnnCommunityForums.sln | 1 + 73 files changed, 2716 insertions(+), 911 deletions(-) create mode 100644 .github/copilot-instructions.md create mode 100644 Dnn.CommunityForums/Controllers/SettingsController.cs create mode 100644 Dnn.CommunityForums/Entities/SettingsInfo.cs create mode 100644 Dnn.CommunityForums/Services/Controllers/FeatureSettingsController.cs create mode 100644 Dnn.CommunityForums/Services/Controllers/ForumGroupController.cs create mode 100644 Dnn.CommunityForums/class/ModuleSettings.cs delete mode 100644 Dnn.CommunityForums/class/Settings.cs create mode 100644 Dnn.CommunityForums/sql/09.02.00.SqlDataProvider create mode 100644 Dnn.CommunityForumsTests/WebApiTests/WebApiForumGroupTests1.http diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 000000000..e9ca2ee30 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,87 @@ + + + +You are a senior .NET developer, experienced in C#, JavaScript, HTML, ASP.NET Framework 4.8, CSS, and SQL. +You understand the priciples of DNN (DotNetNuke) and how to develop DNN modules. +You use Visual Studio Enterprise for running, debugging, and testing DNN (DotNetNuke) modules. + +## Code Style and Structure +- Write idiomatic and efficient C# code. +- Follow .NET conventions. +- Follow DNN module development best practices. +- Always follow DNN's StyleCop rules for C# and JavaScript. +- Always use StyleCop to add file header license to all C# files. +- Always put using directives inside the namespace, sorted alphabetically and grouped by system and third-party libraries. +- Always put a blank link between system and third-party libraries using directives. +- Use Razor syntax when possible for component-based UI development. +- Async/await should be used where applicable to ensure non-blocking UI operations. +- Classes should always be internal unless they are intended to be public APIs. +- Always add using directives for namespaces that are used in the file, and remove unused using directives. +- Never use 'Active Forums' in code, always use 'DNN Community Forums' instead. + +## Naming Conventions +- Follow PascalCase for component names, method names, and public members. +- Use underscore prefix and then PascalCase for private fields. +- Use camelCase for local variables. +- Prefix interface names with "I" (e.g., IUserService). + +## .NET Specific Guidelines +- Leverage DNN Dependency Injection for services when possible. +- DNN modules should be developed using DNN version 9.11 and compatible with .NET Framework 4.8. +- Always use the latest stable version of .NET libraries and packages compatible with DNN. +- Use NuGet packages for third-party libraries, ensuring they are compatible with DNN and .NET Framework 4.8. +- Use C# compatible with .NET Framework 4.8, avoiding features exclusive to .NET Core or .NET 5+. + +## Error Handling and Validation +- Implement proper error handling for Web API calls. + +## DNN Entities, Controllers, and Services +- Always create and use DNN-style entities (e.g., ForumUserInfo, ForumPostInfo) for data representation. +- Always create and use DNN-style services (e.g., IForumService, IUserService) for business logic. +- Always create controllers in Controllers folder, and use the appropriate namespaces, such as DotNetNuke.Modules.ActiveForums.Controllers. +- Always create controllers that inherit from DotNetNuke.Modules.ActiveForums.Controllers.RepositoryControllerBase for the appropriate entity. +- Always create controllers as internal classes, unless they are intended to be public APIs. +- Always create an entity class for each DNN entity, such as ForumUserInfo, ForumPostInfo, etc., in the Entities folder, and use namespace DotNetNuke.Modules.ActiveForums.Entities. +- Entity classes should use DNN DAL2 PetaPoco standards, and include TableName and PrimaryKey attributes, for example: + [TableName("activeforums_Content")] + [PrimaryKey("ContentId", AutoIncrement = true)] +- Always map entity's DateUpdated and DateCreated properties, ensuring they are stored in UTC format. +- Always add using DotNetNuke.ComponentModel.DataAnnotations; to the entity class files. + +## SQL DataProvider and Database Access +- Use DNN's built-in DataProvider pattern for database access. +- Create SQL scripts for database migrations and updates, ensuring they are compatible with DNN's upgrade process. +- Always use GETUTCDATE() for date and time storage in the database. +- Always add DateCreated and DataModified to all tables. +- Always default DateCreated to GETUTCDATE() and DateUpdated to GETUTCDATE() on insert and update operations. +- Database object names should be in camelCase. +- Always prefix database object names with activeforums_ to avoid conflicts with other modules. +- Always prefix database objects (tables, views, stored procedures) with the {databaseOwner}{objectQualifier} prefixes to ensure compatibility with DNN's multi-tenant architecture. +- Examples : {databaseOwner}[{objectQualifier}activeforums_ForumPosts] for ForumPosts table, IX_{objectQualifier}activeforums_Content_ModuleId for an index. +- Always add an auto-incrementing identity as primary key to all tables, using the naming convention PK_{objectQualifier}activeforums_{TableName} (e.g., PK_activeforums_ForumPosts). +- Always add indexes to frequently queried columns, using the naming convention IX_{objectQualifier}activeforums_{TableName}_{ColumnName} (e.g., IX_activeforums_ForumPosts_ModuleId). +- Always use NOT EXISTS check when creating tables and adding columns ot existing tables. +- Always use EXISTS check with DROP statements when creating indexes. +- Always use parameterized queries to prevent SQL injection attacks. +- Always create a matching entity class when creating a new table, such as ForumUserInfo, ForumPostInfo, etc., in the Entities folder. +- When adding a new SqlDataProvider, always offer to update the DNN manifest file (DnnCommunityForums.dnn) to reference the new version, ensuring it is compatible with DNN's upgrade process. + +## Caching Strategies +- Implement in-memory caching for all Controllers and services to improve performance and reduce database load. +- Caching should use methods in Cache.cs, such as ContentCacheRetrieve, ContentCacheStore, and ContentCacheRemove for content, and SettingsCache, SettingsCacheRetrieve, and SettingsCacheStore for settings. + +## API Design and Integration +- Use HttpClient or other appropriate services to communicate with external APIs or your own backend. +- Implement error handling for API calls using try-catch and provide proper user feedback in the UI. + +## Testing and Debugging in Visual Studio +- Create unit tests for all public and internal methods using NUnit. +- Use Moq for mocking dependencies during tests, leveraging TestBase.cs for shared test setup. +- Create unit tests in DnnCommunityForumsTests project for testing DNN module functionality. + +## Security and Authentication +- All user properties should be accesed using ForumUserInfo and then DNN UserInfo. +- Use HTTPS for all web communication and ensure proper CORS policies are implemented. + +## API Documentation +- Ensure XML documentation for models and API methods for enhancing sufficient documentation. \ No newline at end of file diff --git a/Dnn.CommunityForums/Classic.ascx.cs b/Dnn.CommunityForums/Classic.ascx.cs index be8d512ab..070192d8b 100644 --- a/Dnn.CommunityForums/Classic.ascx.cs +++ b/Dnn.CommunityForums/Classic.ascx.cs @@ -67,7 +67,7 @@ protected override void OnLoad(EventArgs e) try { - if (this.MainSettings != null && this.MainSettings.InstallDate > Utilities.NullDate()) + if (this.ModuleSettings != null && this.ModuleSettings.InstallDate > Utilities.NullDate()) { if (this.ForumModuleId < 1) { @@ -134,7 +134,7 @@ protected override void OnLoad(EventArgs e) if (this.Request.IsAuthenticated) { - if (this.MainSettings.UsersOnlineEnabled) + if (this.ModuleSettings.UsersOnlineEnabled) { DataProvider.Instance().Profiles_UpdateActivity(this.PortalId, this.UserId); } @@ -287,8 +287,8 @@ private void GetControl(string view, string options) ControlsConfig cc = new ControlsConfig(); cc.AppPath = this.Page.ResolveUrl(Globals.ModulePath); - cc.ThemePath = this.Page.ResolveUrl(this.MainSettings.ThemeLocation); - cc.TemplatePath = this.Page.ResolveUrl(this.MainSettings.TemplatePath + "/"); + cc.ThemePath = this.Page.ResolveUrl(this.ModuleSettings.ThemeLocation); + cc.TemplatePath = this.Page.ResolveUrl(this.ModuleSettings.TemplatePath + "/"); cc.PortalId = this.PortalId; cc.PageId = this.TabId; cc.ModuleId = this.ModuleId; @@ -360,27 +360,27 @@ private void SetupPage() } } - if (System.IO.File.Exists(Utilities.MapPath(this.MainSettings.ThemeLocation + "theme.min.css"))) + if (System.IO.File.Exists(Utilities.MapPath(this.ModuleSettings.ThemeLocation + "theme.min.css"))) { - ClientResourceManager.RegisterStyleSheet(this.Page, this.MainSettings.ThemeLocation + "theme.min.css", priority: 12); + ClientResourceManager.RegisterStyleSheet(this.Page, this.ModuleSettings.ThemeLocation + "theme.min.css", priority: 12); } else { - if (System.IO.File.Exists(Utilities.MapPath(this.MainSettings.ThemeLocation + "theme.css"))) + if (System.IO.File.Exists(Utilities.MapPath(this.ModuleSettings.ThemeLocation + "theme.css"))) { - ClientResourceManager.RegisterStyleSheet(this.Page, this.MainSettings.ThemeLocation + "theme.css", priority: 12); + ClientResourceManager.RegisterStyleSheet(this.Page, this.ModuleSettings.ThemeLocation + "theme.css", priority: 12); } } - if (System.IO.File.Exists(Utilities.MapPath(this.MainSettings.ThemeLocation + "custom/theme.min.css"))) + if (System.IO.File.Exists(Utilities.MapPath(this.ModuleSettings.ThemeLocation + "custom/theme.min.css"))) { - ClientResourceManager.RegisterStyleSheet(this.Page, this.MainSettings.ThemeLocation + "custom/theme.min.css", priority: 13); + ClientResourceManager.RegisterStyleSheet(this.Page, this.ModuleSettings.ThemeLocation + "custom/theme.min.css", priority: 13); } else { - if (System.IO.File.Exists(Utilities.MapPath(this.MainSettings.ThemeLocation + "custom/theme.css"))) + if (System.IO.File.Exists(Utilities.MapPath(this.ModuleSettings.ThemeLocation + "custom/theme.css"))) { - ClientResourceManager.RegisterStyleSheet(this.Page, this.MainSettings.ThemeLocation + "custom/theme.css", priority: 13); + ClientResourceManager.RegisterStyleSheet(this.Page, this.ModuleSettings.ThemeLocation + "custom/theme.css", priority: 13); } } @@ -421,7 +421,7 @@ private void SetupPage() sLoadImg += "var afSpin = new Image();afSpin.src='" + VirtualPathUtility.ToAbsolute(Globals.ModulePath + "images/spinner.gif") + "';"; sb.AppendLine(sLoadImg); sb.AppendLine(Utilities.LocalizeControl(Utilities.GetFile(Utilities.MapPath(Globals.ModulePath + "scripts/resx.js")), false, true)); - if (HttpContext.Current.Request.IsAuthenticated && this.MainSettings.UsersOnlineEnabled) + if (HttpContext.Current.Request.IsAuthenticated && this.ModuleSettings.UsersOnlineEnabled) { sb.AppendLine("setInterval('amaf_updateuseronline(" + this.ModuleId.ToString() + ")',120000);"); } diff --git a/Dnn.CommunityForums/Controllers/EmailController.cs b/Dnn.CommunityForums/Controllers/EmailController.cs index 2dbef5fb8..08da35fb8 100644 --- a/Dnn.CommunityForums/Controllers/EmailController.cs +++ b/Dnn.CommunityForums/Controllers/EmailController.cs @@ -51,7 +51,7 @@ internal static void SendEmail(Enums.TemplateType templateType, int tabId, DotNe fi.FeatureSettings.EmailNotificationSubjectTemplate : (!string.IsNullOrEmpty(fi.ForumGroup.FeatureSettings.EmailNotificationSubjectTemplate) ? fi.ForumGroup.FeatureSettings.EmailNotificationSubjectTemplate : - SettingsBase.GetModuleSettings(fi.ModuleId).ForumFeatureSettings.EmailNotificationSubjectTemplate); + SettingsBase.GetModuleSettings(fi.ModuleId).DefaultFeatureSettings.EmailNotificationSubjectTemplate); var bodyTemplate = DotNetNuke.Modules.ActiveForums.Controllers.TemplateController.Template_Get(fi.ModuleId, templateType, fi.FeatureSettings.TemplateFileNameSuffix); var subject = TemplateUtils.ParseEmailTemplate(subjectTemplate, fi.PortalId, fi.ModuleId, tabId, fi.ForumID, topicId, replyId, author, accessingUser: author.ForumUser, topicSubscriber: false, new Services.URLNavigator().NavigationManager(), HttpContext.Current.Request.Url, HttpContext.Current.Request.RawUrl); var body = TemplateUtils.ParseEmailTemplate(bodyTemplate, fi.PortalId, fi.ModuleId, tabId, fi.ForumID, topicId, replyId, author, accessingUser: author.ForumUser, topicSubscriber: false, new Services.URLNavigator().NavigationManager(), HttpContext.Current.Request.Url, HttpContext.Current.Request.RawUrl); @@ -82,7 +82,7 @@ internal static void SendTemplatedEmail(int topicId, int replyId, int moduleId, fi.FeatureSettings.EmailNotificationSubjectTemplate : (!string.IsNullOrEmpty(fi.ForumGroup.FeatureSettings.EmailNotificationSubjectTemplate) ? fi.ForumGroup.FeatureSettings.EmailNotificationSubjectTemplate : - SettingsBase.GetModuleSettings(moduleId).ForumFeatureSettings.EmailNotificationSubjectTemplate); + SettingsBase.GetModuleSettings(moduleId).DefaultFeatureSettings.EmailNotificationSubjectTemplate); IEnumerable userCultures = subs.Select(s => s.UserCulture).Distinct(); foreach (CultureInfo userCulture in userCultures) { diff --git a/Dnn.CommunityForums/Controllers/ForumController.cs b/Dnn.CommunityForums/Controllers/ForumController.cs index e0e89c5ad..d2a593729 100644 --- a/Dnn.CommunityForums/Controllers/ForumController.cs +++ b/Dnn.CommunityForums/Controllers/ForumController.cs @@ -287,7 +287,7 @@ public int Forums_Save(int portalId, DotNetNuke.Modules.ActiveForums.Entities.Fo // if now inheriting group settings, remove any previously-defined forum settings if (forumInfo.InheritSettings) { - DataContext.Instance().Execute(System.Data.CommandType.Text, "DELETE FROM {databaseOwner}{objectQualifier}activeforums_Settings WHERE ModuleId = @0 AND GroupKey = @1", forumInfo.ModuleId, $"F:{forumInfo.ForumID}"); + new DotNetNuke.Modules.ActiveForums.Controllers.SettingsController().DeleteForModuleIdSettingsKey(forumInfo.ModuleId, $"F:{forumInfo.ForumID}"); } // Clear the caches diff --git a/Dnn.CommunityForums/Controllers/ForumGroupController.cs b/Dnn.CommunityForums/Controllers/ForumGroupController.cs index 744cee541..438d49a82 100644 --- a/Dnn.CommunityForums/Controllers/ForumGroupController.cs +++ b/Dnn.CommunityForums/Controllers/ForumGroupController.cs @@ -142,7 +142,7 @@ public int Groups_Save(int portalId, DotNetNuke.Modules.ActiveForums.Entities.Fo // if new group and not using default features, copy default features to group features as starting point if (copyDownDefaultSettings) { - forumGroupInfo.FeatureSettings = SettingsBase.GetModuleSettings(forumGroupInfo.ModuleId).ForumFeatureSettings; + forumGroupInfo.FeatureSettings = SettingsBase.GetModuleSettings(forumGroupInfo.ModuleId).DefaultFeatureSettings; FeatureSettings.Save(forumGroupInfo.ModuleId, forumGroupInfo.GroupSettingsKey, forumGroupInfo.FeatureSettings); this.Update(forumGroupInfo); } @@ -152,9 +152,10 @@ public int Groups_Save(int portalId, DotNetNuke.Modules.ActiveForums.Entities.Fo new DotNetNuke.Modules.ActiveForums.Controllers.PermissionController().RemoveIfUnused(permissionId: oldPermissionsId, moduleId: forumGroupInfo.ModuleId); } - if (useDefaultFeatures) /* if now using default module settings, remove group settings */ + /* if now using default module settings, remove group settings */ + if (useDefaultFeatures) { - DataContext.Instance().Execute(System.Data.CommandType.Text, "DELETE FROM {databaseOwner}{objectQualifier}activeforums_Settings WHERE ModuleId = @0 AND GroupKey = @1", forumGroupInfo.ModuleId, $"G:{forumGroupInfo.ForumGroupId}"); + new DotNetNuke.Modules.ActiveForums.Controllers.SettingsController().DeleteForModuleIdSettingsKey(forumGroupInfo.ModuleId, $"G:{forumGroupInfo.ForumGroupId}"); } ClearSettingsCache(forumGroupInfo.ModuleId); diff --git a/Dnn.CommunityForums/Controllers/ForumUserController.cs b/Dnn.CommunityForums/Controllers/ForumUserController.cs index c6cab0db9..6b9a48d80 100644 --- a/Dnn.CommunityForums/Controllers/ForumUserController.cs +++ b/Dnn.CommunityForums/Controllers/ForumUserController.cs @@ -363,7 +363,7 @@ public static string GetUserRank(int moduleId, DotNetNuke.Modules.ActiveForums.E } } - internal static bool CanLinkToProfile(DotNetNuke.Entities.Portals.PortalSettings portalSettings, SettingsInfo mainSettings, int moduleId, DotNetNuke.Modules.ActiveForums.Entities.ForumUserInfo accessingUser, DotNetNuke.Modules.ActiveForums.Entities.ForumUserInfo forumUser) + internal static bool CanLinkToProfile(DotNetNuke.Entities.Portals.PortalSettings portalSettings, ModuleSettings moduleSettings, int moduleId, DotNetNuke.Modules.ActiveForums.Entities.ForumUserInfo accessingUser, DotNetNuke.Modules.ActiveForums.Entities.ForumUserInfo forumUser) { if (portalSettings == null) { @@ -380,7 +380,7 @@ internal static bool CanLinkToProfile(DotNetNuke.Entities.Portals.PortalSettings portalSettings?.UserTabId != DotNetNuke.Common.Utilities.Null.NullInteger && portalSettings?.UserTabId != -1) { - var profileVisibility = mainSettings.ProfileVisibility; + var profileVisibility = moduleSettings.ProfileVisibility; switch (profileVisibility) { @@ -409,7 +409,7 @@ internal static bool CanLinkToProfile(DotNetNuke.Entities.Portals.PortalSettings return canLinkToProfile; } - internal static string GetDisplayName(DotNetNuke.Entities.Portals.PortalSettings portalSettings, SettingsInfo mainSettings, bool isMod, bool isAdmin, int userId, string username, string firstName = "", string lastName = "", string displayName = "") + internal static string GetDisplayName(DotNetNuke.Entities.Portals.PortalSettings portalSettings, ModuleSettings mainSettings, bool isMod, bool isAdmin, int userId, string username, string firstName = "", string lastName = "", string displayName = "") { if (portalSettings == null) { @@ -537,7 +537,7 @@ internal static void UpdateUserTopicCount(int portalId, int userId) DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.ClearCache(portalId, userId); } - internal string GetUsersOnline(DotNetNuke.Entities.Portals.PortalSettings portalSettings, DotNetNuke.Modules.ActiveForums.SettingsInfo mainSettings, int moduleId, DotNetNuke.Modules.ActiveForums.Entities.ForumUserInfo forumUser) + internal string GetUsersOnline(DotNetNuke.Entities.Portals.PortalSettings portalSettings, DotNetNuke.Modules.ActiveForums.ModuleSettings mainSettings, int moduleId, DotNetNuke.Modules.ActiveForums.Entities.ForumUserInfo forumUser) { bool isAdmin = forumUser.IsAdmin || forumUser.IsSuperUser; var sb = new StringBuilder(); diff --git a/Dnn.CommunityForums/Controllers/SettingsController.cs b/Dnn.CommunityForums/Controllers/SettingsController.cs new file mode 100644 index 000000000..0c05a20c0 --- /dev/null +++ b/Dnn.CommunityForums/Controllers/SettingsController.cs @@ -0,0 +1,91 @@ +// Copyright (c) by DNN Community +// +// DNN Community licenses this file to you under the MIT license. +// +// See the LICENSE file in the project root for more information. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +namespace DotNetNuke.Modules.ActiveForums.Controllers +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Reflection; + using System.Text.RegularExpressions; + + using DotNetNuke.Collections; + + internal class SettingsController : DotNetNuke.Modules.ActiveForums.Controllers.RepositoryControllerBase + { + public static void SaveSetting(int moduleId, string settingsKey, string settingName, string settingValue) + { + try + { + var sc = new DotNetNuke.Modules.ActiveForums.Controllers.SettingsController(); + var setting = sc.GetSettingForModuleIdSettingsKeySettingName(moduleId, settingsKey, settingName); + if (setting == null) + { + setting = new DotNetNuke.Modules.ActiveForums.Entities.SettingsInfo + { + ModuleId = moduleId, + SettingsKey = settingsKey, + SettingName = settingName, + SettingValue = settingValue, + }; + sc.Insert(setting); + } + else + { + setting.SettingValue = settingValue; + sc.Update(setting); + } + } + catch (Exception ex) + { + DotNetNuke.Modules.ActiveForums.Exceptions.LogException(ex); + } + } + + public IEnumerable GetSettingsForModuleIdSettingsKey(int moduleID, string settingsKey) + { + return this.Find("WHERE ModuleId = @0 AND SettingsKey = @1", moduleID, settingsKey); + } + + public Hashtable GetSettingsHashTableForModuleIdSettingsKey(int moduleId, string settingsKey) + { + var ht = new Hashtable(); + this.GetSettingsForModuleIdSettingsKey(moduleId, settingsKey).ForEach(s => ht.Add(s.SettingName, s.SettingValue)); + return ht; + } + + public DotNetNuke.Modules.ActiveForums.Entities.SettingsInfo GetSettingForModuleIdSettingsKeySettingName(int moduleID, string settingsKey, string settingName) + { + return this.Find("WHERE ModuleId = @0 AND SettingsKey = @1 AND SettingName = @2", moduleID, settingsKey, settingName).FirstOrDefault(); + } + + public void DeleteForModuleIdSettingsKey(int moduleId, string settingsKey) + { + this.Delete("WHERE ModuleId = @0 AND SettingsKey = @1", moduleId, settingsKey); + } + + public void DeleteForModuleIdSettingsKeySettingName(int moduleId, string settingsKey, string settingName) + { + this.Delete("WHERE ModuleId = @0 AND SettingsKey = @1 AND SettingName = @2", moduleId, settingsKey, settingName); + } + } +} diff --git a/Dnn.CommunityForums/Controllers/TemplateController.cs b/Dnn.CommunityForums/Controllers/TemplateController.cs index 15bbbdf5f..3a8d65e8b 100644 --- a/Dnn.CommunityForums/Controllers/TemplateController.cs +++ b/Dnn.CommunityForums/Controllers/TemplateController.cs @@ -35,7 +35,7 @@ public void Template_Save(int moduleId, DotNetNuke.Modules.ActiveForums.Entities { string templatePathFileName = Globals.TemplatesPath + templateInfo.FileName; - SettingsInfo moduleSettings = SettingsBase.GetModuleSettings(moduleId); + ModuleSettings moduleSettings = SettingsBase.GetModuleSettings(moduleId); templatePathFileName = moduleSettings.TemplatePath + templateInfo.FileName; if (!System.IO.Directory.Exists(Utilities.MapPath(moduleSettings.TemplatePath))) { @@ -53,7 +53,7 @@ public void Template_Save(int moduleId, DotNetNuke.Modules.ActiveForums.Entities public void Template_Delete(int moduleId, Enums.TemplateType templateType, string templateFileNameSuffix) { string fileNameBase = templateType.ToString().ToLowerInvariant(); - SettingsInfo moduleSettings = SettingsBase.GetModuleSettings(moduleId); + ModuleSettings moduleSettings = SettingsBase.GetModuleSettings(moduleId); try { if (!string.IsNullOrEmpty(templateFileNameSuffix)) @@ -101,7 +101,7 @@ private static string Template_Get(int moduleId, string templateBaseFileName, st string sTemplate = string.Empty; string fileName = string.Empty; string templateFilePathFileName = string.Empty; - SettingsInfo moduleSettings = SettingsBase.GetModuleSettings(moduleId); + ModuleSettings moduleSettings = SettingsBase.GetModuleSettings(moduleId); templateBaseFileName = templateBaseFileName.ToLowerInvariant(); string cacheKey = string.Format(CacheKeys.Template, moduleId, templateBaseFileName, templateFileNameSuffix); object obj = null; diff --git a/Dnn.CommunityForums/Controllers/TopicController.cs b/Dnn.CommunityForums/Controllers/TopicController.cs index 6e880ce6c..92714a6f2 100644 --- a/Dnn.CommunityForums/Controllers/TopicController.cs +++ b/Dnn.CommunityForums/Controllers/TopicController.cs @@ -199,7 +199,7 @@ public static void Move(int moduleId, int userId, int topicId, int newForumId) { DotNetNuke.Modules.ActiveForums.Entities.TopicInfo ti = new DotNetNuke.Modules.ActiveForums.Controllers.TopicController(moduleId).GetById(topicId); int oldForumId = (int)ti.ForumId; - SettingsInfo settings = SettingsBase.GetModuleSettings(ti.ModuleId); + ModuleSettings settings = SettingsBase.GetModuleSettings(ti.ModuleId); if (settings.URLRewriteEnabled) { try diff --git a/Dnn.CommunityForums/Controllers/UrlController.cs b/Dnn.CommunityForums/Controllers/UrlController.cs index 7a4c90d4c..9da339828 100644 --- a/Dnn.CommunityForums/Controllers/UrlController.cs +++ b/Dnn.CommunityForums/Controllers/UrlController.cs @@ -93,14 +93,14 @@ internal static string BuildForumUrlSegment(int portalId, int moduleId, DotNetNu return url; } - internal static string BuildForumUrl(INavigationManager navigationManager, DotNetNuke.Abstractions.Portals.IPortalSettings portalSettings, SettingsInfo mainSettings, DotNetNuke.Modules.ActiveForums.Entities.ForumInfo forumInfo) + internal static string BuildForumUrl(INavigationManager navigationManager, DotNetNuke.Abstractions.Portals.IPortalSettings portalSettings, ModuleSettings mainSettings, DotNetNuke.Modules.ActiveForums.Entities.ForumInfo forumInfo) { // Build the forum Url return mainSettings.UseShortUrls ? navigationManager.NavigateURL(forumInfo.GetTabId(), portalSettings, string.Empty, new[] { $"{ParamKeys.ForumId}={forumInfo.ForumID}" }) : navigationManager.NavigateURL(forumInfo.GetTabId(), portalSettings, string.Empty, new[] { $"{ParamKeys.ForumId}={forumInfo.ForumID}", $"{ParamKeys.ViewType}={Views.Topics}" }); } - internal static string BuildModeratorUrl(INavigationManager navigationManager, DotNetNuke.Abstractions.Portals.IPortalSettings portalSettings, SettingsInfo mainSettings, DotNetNuke.Modules.ActiveForums.Entities.ForumInfo forumInfo) + internal static string BuildModeratorUrl(INavigationManager navigationManager, DotNetNuke.Abstractions.Portals.IPortalSettings portalSettings, ModuleSettings mainSettings, DotNetNuke.Modules.ActiveForums.Entities.ForumInfo forumInfo) { return navigationManager.NavigateURL(forumInfo.GetTabId(), portalSettings, string.Empty, new[] { $"{ParamKeys.ViewType}={Views.ModerateTopics}", $"{ParamKeys.ForumId}={forumInfo.ForumID}" }); } diff --git a/Dnn.CommunityForums/CustomControls/HTML/TopicBrowser.cs b/Dnn.CommunityForums/CustomControls/HTML/TopicBrowser.cs index 4a475059d..d0e45ff17 100644 --- a/Dnn.CommunityForums/CustomControls/HTML/TopicBrowser.cs +++ b/Dnn.CommunityForums/CustomControls/HTML/TopicBrowser.cs @@ -67,7 +67,7 @@ public class TopicBrowser public bool MaintainPage { get; set; } = false; - private SettingsInfo _mainSettings = null; + private ModuleSettings _mainSettings = null; private bool _canEdit = false; public string Render() diff --git a/Dnn.CommunityForums/CustomControls/ServerControls/QuickReply.cs b/Dnn.CommunityForums/CustomControls/ServerControls/QuickReply.cs index e9d4f10a4..cb048bd9e 100644 --- a/Dnn.CommunityForums/CustomControls/ServerControls/QuickReply.cs +++ b/Dnn.CommunityForums/CustomControls/ServerControls/QuickReply.cs @@ -182,7 +182,7 @@ private void SaveQuickReply() DotNetNuke.Modules.ActiveForums.Entities.ForumInfo forumInfo = DotNetNuke.Modules.ActiveForums.Controllers.ForumController.Forums_Get(this.portalId, this.moduleId, this.ForumId, false, this.TopicId); if (!Utilities.HasFloodIntervalPassed(floodInterval: this.ForumInfo.MainSettings.FloodInterval, forumUser: this.ForumUser, forumInfo: forumInfo)) { - this.plhMessage.Controls.Add(new InfoMessage { Message = "
" + string.Format(this.GetSharedResource("[RESX:Error:FloodControl]"), this.MainSettings.FloodInterval) + "
" }); + this.plhMessage.Controls.Add(new InfoMessage { Message = "
" + string.Format(this.GetSharedResource("[RESX:Error:FloodControl]"), this.ModuleSettings.FloodInterval) + "
" }); return; } diff --git a/Dnn.CommunityForums/CustomControls/ServerControls/TagCloud.cs b/Dnn.CommunityForums/CustomControls/ServerControls/TagCloud.cs index 9d086e207..8c01cd9a5 100644 --- a/Dnn.CommunityForums/CustomControls/ServerControls/TagCloud.cs +++ b/Dnn.CommunityForums/CustomControls/ServerControls/TagCloud.cs @@ -60,7 +60,7 @@ protected override void Render(HtmlTextWriter writer) } } - SettingsInfo _mainSettings = SettingsBase.GetModuleSettings(this.ModuleId); + ModuleSettings _mainSettings = SettingsBase.GetModuleSettings(this.ModuleId); Data.Common db = new Data.Common(); IDataReader dr = db.TagCloud_Get(this.PortalId, this.ModuleId, this.ForumIds, this.TagCount); ControlUtils ctlUtils = new ControlUtils(); diff --git a/Dnn.CommunityForums/CustomControls/ServerControls/TopicNavigator.cs b/Dnn.CommunityForums/CustomControls/ServerControls/TopicNavigator.cs index 8d066d286..78c319bc1 100644 --- a/Dnn.CommunityForums/CustomControls/ServerControls/TopicNavigator.cs +++ b/Dnn.CommunityForums/CustomControls/ServerControls/TopicNavigator.cs @@ -79,7 +79,7 @@ protected override void Render(HtmlTextWriter writer) tb.ModuleId = this.ForumModuleId; tb.TabId = this.ForumTabId; tb.PageIndex = this.PageId; - tb.PageSize = this.MainSettings.PageSize; + tb.PageSize = this.ModuleSettings.PageSize; tb.Template = this.ItemTemplate.Text; // tb.HeaderTemplate = HeaderTemplate.Text diff --git a/Dnn.CommunityForums/CustomControls/ServerControls/TopicsNavigator.cs b/Dnn.CommunityForums/CustomControls/ServerControls/TopicsNavigator.cs index 9e69f3e83..ace2b23d9 100644 --- a/Dnn.CommunityForums/CustomControls/ServerControls/TopicsNavigator.cs +++ b/Dnn.CommunityForums/CustomControls/ServerControls/TopicsNavigator.cs @@ -130,7 +130,7 @@ protected override void Render(HtmlTextWriter writer) tb.ForumUser = this.ForumUser; tb.PageIndex = this.PageId; - tb.PageSize = this.MainSettings.PageSize; + tb.PageSize = this.ModuleSettings.PageSize; tb.Template = this.ItemTemplate.Text; tb.HeaderTemplate = this.HeaderTemplate.Text; tb.FooterTemplate = this.FooterTemplate.Text; diff --git a/Dnn.CommunityForums/CustomControls/UserControls/ForumView.cs b/Dnn.CommunityForums/CustomControls/UserControls/ForumView.cs index 293402c32..27928f82c 100644 --- a/Dnn.CommunityForums/CustomControls/UserControls/ForumView.cs +++ b/Dnn.CommunityForums/CustomControls/UserControls/ForumView.cs @@ -142,18 +142,18 @@ public string BuildForumView() { try { - string sTemplate = DotNetNuke.Modules.ActiveForums.Controllers.TemplateController.Template_Get(this.ForumModuleId, Enums.TemplateType.ForumView, SettingsBase.GetModuleSettings(this.ForumModuleId).ForumFeatureSettings.TemplateFileNameSuffix); + string sTemplate = DotNetNuke.Modules.ActiveForums.Controllers.TemplateController.Template_Get(this.ForumModuleId, Enums.TemplateType.ForumView, SettingsBase.GetModuleSettings(this.ForumModuleId).DefaultFeatureSettings.TemplateFileNameSuffix); StringBuilder stringBuilder = new StringBuilder(sTemplate); #region "Backward compatilbility -- remove in v10.00.00" stringBuilder = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.RemoveObsoleteTokens(stringBuilder); - stringBuilder = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyUserTokenSynonyms(stringBuilder, this.PortalSettings, this.MainSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale); + stringBuilder = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyUserTokenSynonyms(stringBuilder, this.PortalSettings, this.ModuleSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale); stringBuilder = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyForumTokenSynonyms(stringBuilder, this.PortalSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale); #endregion "Backward compatilbility -- remove in v10.00.00" stringBuilder.Replace("[JUMPTO]", ""); stringBuilder.Replace("[STATISTICS]", ""); - stringBuilder.Replace("[WHOSONLINE]", this.MainSettings.UsersOnlineEnabled ? "" : string.Empty); + stringBuilder.Replace("[WHOSONLINE]", this.ModuleSettings.UsersOnlineEnabled ? "" : string.Empty); if (stringBuilder.ToString().Contains("[NOTOOLBAR]")) { @@ -233,7 +233,7 @@ public string BuildForumView() sGroupName = this.Forums?.Where(f => f.ForumID == this.ParentForumId).FirstOrDefault().GroupName; } - if (this.MainSettings.UseSkinBreadCrumb && this.Forums?.Count > 0 && this.SubsOnly == false && this.ForumGroupId != -1) + if (this.ModuleSettings.UseSkinBreadCrumb && this.Forums?.Count > 0 && this.SubsOnly == false && this.ForumGroupId != -1) { DotNetNuke.Modules.ActiveForums.Environment.UpdateBreadCrumb(this.Page.Controls, "" + sGroupName + ""); sTemplate = sTemplate.Replace("
[FORUMMAINLINK] > [FORUMGROUPLINK]
", string.Empty); @@ -253,7 +253,7 @@ public string BuildForumView() foreach (var fi in this.Forums.Where(f => !this.SubsOnly || f.ParentForumId > 0).OrderBy(f => f.ForumGroup?.SortOrder).ThenBy(f => f.ForumGroupId).ThenBy(f => f.SortOrder).Take(Globals.ForumCount)) { fi.PortalSettings = this.PortalSettings; - fi.MainSettings = this.MainSettings; + fi.MainSettings = this.ModuleSettings; bool canView = DotNetNuke.Modules.ActiveForums.Controllers.PermissionController.HasRequiredPerm(fi.Security?.ViewRoleIds, this.ForumUser.UserRoleIds); if (this.UserInfo.IsSuperUser || (canView && !fi.ForumGroup.Hidden)) { @@ -272,12 +272,12 @@ public string BuildForumView() sGroupSectionTemp = TemplateUtils.GetTemplateSection(sTemplate, "[GROUPSECTION]", "[/GROUPSECTION]"); StringBuilder sGroupSectionTempStringBuilder = new StringBuilder(sGroupSectionTemp); - sGroupSectionTempStringBuilder = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceForumGroupTokens(sGroupSectionTempStringBuilder, fi.ForumGroup, this.PortalSettings, this.MainSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.TabId, this.ForumUser.CurrentUserType, this.Request.Url, this.Request.RawUrl); + sGroupSectionTempStringBuilder = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceForumGroupTokens(sGroupSectionTempStringBuilder, fi.ForumGroup, this.PortalSettings, this.ModuleSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.TabId, this.ForumUser.CurrentUserType, this.Request.Url, this.Request.RawUrl); sGroupSectionTemp = sGroupSectionTempStringBuilder.ToString(); // any replacements on the group StringBuilder sNewGroupStringBuilder = new StringBuilder("
" + sGroupTemplate + "
"); - sNewGroupStringBuilder = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceForumGroupTokens(sNewGroupStringBuilder, fi.ForumGroup, this.PortalSettings, this.MainSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.TabId, this.ForumUser.CurrentUserType, this.Request.Url, this.Request.RawUrl); + sNewGroupStringBuilder = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceForumGroupTokens(sNewGroupStringBuilder, fi.ForumGroup, this.PortalSettings, this.ModuleSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.TabId, this.ForumUser.CurrentUserType, this.Request.Url, this.Request.RawUrl); string sNewGroup = sNewGroupStringBuilder.ToString(); sGroupSectionTemp = TemplateUtils.ReplaceSubSection(sGroupSectionTemp, sNewGroup, "[GROUP]", "[/GROUP]"); @@ -385,7 +385,7 @@ private string ParseForumRow(string template, DotNetNuke.Modules.ActiveForums.En } StringBuilder templateStringBuilder = new StringBuilder(template); - templateStringBuilder = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceForumTokens(templateStringBuilder, fi, this.PortalSettings, this.MainSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.TabId, this.ForumUser.CurrentUserType, this.Request.Url, this.Request.RawUrl); + templateStringBuilder = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceForumTokens(templateStringBuilder, fi, this.PortalSettings, this.ModuleSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.TabId, this.ForumUser.CurrentUserType, this.Request.Url, this.Request.RawUrl); if (templateStringBuilder.ToString().Contains("[AF:CONTROL:TOGGLESUBSCRIBE]")) { @@ -426,7 +426,7 @@ private string GetSubForums(string template, int forumId, int tabId) string subForum; foreach (DotNetNuke.Modules.ActiveForums.Entities.ForumInfo fi in subforums) { - subForum = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceForumTokens(new StringBuilder("[FORUMLINK]"), fi, this.PortalSettings, this.MainSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.TabId, this.ForumUser.CurrentUserType, this.Request.Url, this.Request.RawUrl).ToString(); + subForum = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceForumTokens(new StringBuilder("[FORUMLINK]"), fi, this.PortalSettings, this.ModuleSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.TabId, this.ForumUser.CurrentUserType, this.Request.Url, this.Request.RawUrl).ToString(); if (subForum != string.Empty) { sb.Append(subForum); diff --git a/Dnn.CommunityForums/CustomControls/UserControls/Members.cs b/Dnn.CommunityForums/CustomControls/UserControls/Members.cs index 6ad9bf607..24c136a64 100644 --- a/Dnn.CommunityForums/CustomControls/UserControls/Members.cs +++ b/Dnn.CommunityForums/CustomControls/UserControls/Members.cs @@ -97,8 +97,8 @@ protected override void OnLoad(EventArgs e) private void BuildControl() { System.Text.StringBuilder sb = new System.Text.StringBuilder(1024); - SettingsInfo moduleSettings = SettingsBase.GetModuleSettings(this.ForumModuleId); - string sTemplate = DotNetNuke.Modules.ActiveForums.Controllers.TemplateController.Template_Get(this.ForumModuleId, Enums.TemplateType._memberList, SettingsBase.GetModuleSettings(this.ForumModuleId).ForumFeatureSettings.TemplateFileNameSuffix); + ModuleSettings moduleSettings = SettingsBase.GetModuleSettings(this.ForumModuleId); + string sTemplate = DotNetNuke.Modules.ActiveForums.Controllers.TemplateController.Template_Get(this.ForumModuleId, Enums.TemplateType._memberList, SettingsBase.GetModuleSettings(this.ForumModuleId).DefaultFeatureSettings.TemplateFileNameSuffix); if (!(sTemplate == string.Empty)) { string sGrid = TemplateUtils.GetTemplateSection(sTemplate, "[AF:CONTROL:LIST]", "[/AF:CONTROL:LIST]"); @@ -212,7 +212,7 @@ private string BuildAlphaList() { List upl = new List(); DotNetNuke.Modules.ActiveForums.Entities.ForumUserInfo upi = null; - this.pageSize = this.MainSettings.PageSize; + this.pageSize = this.ModuleSettings.PageSize; if (this.PageId == 1) { this.rowIndex = 0; diff --git a/Dnn.CommunityForums/CustomControls/UserControls/SubmitForm.cs b/Dnn.CommunityForums/CustomControls/UserControls/SubmitForm.cs index 280317f4b..aac847a8e 100644 --- a/Dnn.CommunityForums/CustomControls/UserControls/SubmitForm.cs +++ b/Dnn.CommunityForums/CustomControls/UserControls/SubmitForm.cs @@ -705,7 +705,7 @@ private string ParseForm(string template) if (template.Contains("[AF:CONTROL:POSTICONS]") && this.ForumInfo.FeatureSettings.AllowPostIcon) { template = template.Replace("[AF:UI:FIELDSET:POSTICONS]", "
[RESX:PostIcons]
[RESX:PostIcons:Note]
"); - template = template.Replace("[AF:CONTROL:POSTICONS]", ""); + template = template.Replace("[AF:CONTROL:POSTICONS]", ""); template = template.Replace("[/AF:UI:FIELDSET:POSTICONS]", "
"); /* tokens [AF:UI:SECTION:POSTICONS][/AF:UI:SECTION:POSTICONS] can now surround post icons to support removing entire section; if using post icons, just remove the tokens*/ template = template.Replace("[AF:UI:SECTION:POSTICONS]", string.Empty); @@ -723,7 +723,7 @@ private string ParseForm(string template) if (template.Contains("[AF:CONTROL:EMOTICONS]") && this.ForumInfo.FeatureSettings.AllowEmoticons) { - template = template.Replace("[AF:CONTROL:EMOTICONS]", "
[RESX:Smilies]" + DotNetNuke.Modules.ActiveForums.Controllers.EmoticonController.LoadEmoticons(this.ForumModuleId, this.Page.ResolveUrl(this.MainSettings.ThemeLocation), this.EditorType) + "
"); + template = template.Replace("[AF:CONTROL:EMOTICONS]", "
[RESX:Smilies]" + DotNetNuke.Modules.ActiveForums.Controllers.EmoticonController.LoadEmoticons(this.ForumModuleId, this.Page.ResolveUrl(this.ModuleSettings.ThemeLocation), this.EditorType) + "
"); } else { @@ -1035,7 +1035,7 @@ protected override void OnLoad(EventArgs e) // not sure why this gets set twice. this.txtSubject.CssClass = "aftextbox dcf-topic-edit-subject"; - string myTheme = this.MainSettings.Theme; + string myTheme = this.ModuleSettings.Theme; string myThemePath = this.Page.ResolveUrl("~/DesktopModules/ActiveForums/themes/" + myTheme); this.txtSubject.MaxLength = 255; this.txtSummary.MaxLength = 2000; diff --git a/Dnn.CommunityForums/CustomControls/UserControls/TopicView.cs b/Dnn.CommunityForums/CustomControls/UserControls/TopicView.cs index 3baa7164a..9ae23b49f 100644 --- a/Dnn.CommunityForums/CustomControls/UserControls/TopicView.cs +++ b/Dnn.CommunityForums/CustomControls/UserControls/TopicView.cs @@ -125,7 +125,7 @@ protected override void OnLoad(EventArgs e) if (firstUnreadPost > lastPostRead) { var tURL = Utilities.NavigateURL(this.TabId, string.Empty, new[] { ParamKeys.ForumId + "=" + this.ForumId, ParamKeys.TopicId + "=" + this.TopicId, ParamKeys.ViewType + "=topic", ParamKeys.ContentJumpId + "=" + firstUnreadPost }); - if (this.MainSettings.UseShortUrls) + if (this.ModuleSettings.UseShortUrls) { tURL = Utilities.NavigateURL(this.TabId, string.Empty, new[] { ParamKeys.TopicId + "=" + this.TopicId, ParamKeys.ContentJumpId + "=" + firstUnreadPost }); } @@ -184,7 +184,7 @@ private void LoadData(int pageId) this.pageSize = this.OptPageSize; if (this.pageSize <= 0) { - this.pageSize = this.UserId > 0 ? this.UserDefaultPageSize : this.MainSettings.PageSize; + this.pageSize = this.UserId > 0 ? this.UserDefaultPageSize : this.ModuleSettings.PageSize; if (this.pageSize < 5) { this.pageSize = 10; @@ -231,7 +231,7 @@ private void LoadData(int pageId) { if (pageId > 1) { - if (this.MainSettings.UseShortUrls) + if (this.ModuleSettings.UseShortUrls) { this.Response.Redirect(Utilities.NavigateURL(this.TabId, string.Empty, new[] { ParamKeys.TopicId + "=" + this.TopicId }), false); this.Context.ApplicationInstance.CompleteRequest(); @@ -244,7 +244,7 @@ private void LoadData(int pageId) } else { - if (this.MainSettings.UseShortUrls) + if (this.ModuleSettings.UseShortUrls) { this.Response.Redirect(Utilities.NavigateURL(this.TabId, string.Empty, new[] { ParamKeys.ForumId + "=" + this.ForumId }), false); this.Context.ApplicationInstance.CompleteRequest(); @@ -376,7 +376,7 @@ private void LoadData(int pageId) var sURL = string.Empty; - if (this.MainSettings.URLRewriteEnabled && !string.IsNullOrEmpty(this.topic.TopicUrl)) + if (this.ModuleSettings.URLRewriteEnabled && !string.IsNullOrEmpty(this.topic.TopicUrl)) { var db = new Data.Common(); sURL = db.GetUrl(this.ModuleId, this.ForumGroupId, this.ForumId, this.TopicId, this.UserId, contentJumpId); @@ -402,7 +402,7 @@ private void LoadData(int pageId) $"{ParamKeys.TopicId}={this.TopicId}", $"{ParamKeys.ViewType}={Views.Topic}", }; - if (this.MainSettings.UseShortUrls) + if (this.ModuleSettings.UseShortUrls) { @params = new List { ParamKeys.TopicId + "=" + this.TopicId }; } @@ -516,8 +516,8 @@ private void BindTopic() this.MetaTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.RemoveObsoleteTokens(new StringBuilder(this.MetaTemplate)).ToString(); this.MetaTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyForumTokenSynonyms(new StringBuilder(this.MetaTemplate), this.PortalSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale).ToString(); this.MetaTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyTopicTokenSynonyms(new StringBuilder(this.MetaTemplate), this.PortalSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale).ToString(); - this.MetaTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceTopicTokens(new StringBuilder(this.MetaTemplate), this.topic, this.PortalSettings, this.MainSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl).ToString(); - this.MetaTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceForumTokens(new StringBuilder(this.MetaTemplate), this.ForumInfo, this.PortalSettings, this.MainSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.TabId, this.ForumUser.CurrentUserType, this.Request.Url, this.Request.RawUrl).ToString(); + this.MetaTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceTopicTokens(new StringBuilder(this.MetaTemplate), this.topic, this.PortalSettings, this.ModuleSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl).ToString(); + this.MetaTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceForumTokens(new StringBuilder(this.MetaTemplate), this.ForumInfo, this.PortalSettings, this.ModuleSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.TabId, this.ForumUser.CurrentUserType, this.Request.Url, this.Request.RawUrl).ToString(); this.MetaTemplate = this.MetaTemplate.Replace("[TAGS]", this.tags); this.MetaTitle = TemplateUtils.GetTemplateSection(this.MetaTemplate, "[TITLE]", "[/TITLE]").Replace("[TITLE]", string.Empty).Replace("[/TITLE]", string.Empty); @@ -533,7 +533,7 @@ private void BindTopic() var breadCrumb = TemplateUtils.GetTemplateSection(sOutput, "[BREADCRUMB]", "[/BREADCRUMB]").Replace("[BREADCRUMB]", string.Empty).Replace("[/BREADCRUMB]", string.Empty); - if (this.MainSettings.UseSkinBreadCrumb) + if (this.ModuleSettings.UseSkinBreadCrumb) { var ctlUtils = new ControlUtils(); @@ -576,7 +576,7 @@ private void BindTopic() { sOutput = TemplateUtils.ReplaceSubSection(sOutput, "", "[AF:CONTROL:CALLBACK]", "[/AF:CONTROL:CALLBACK]"); sOutput = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyTopicTokenSynonyms(new StringBuilder(sOutput), this.PortalSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale).ToString(); - sOutput = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceTopicTokens(new StringBuilder(sOutput), this.topic, this.PortalSettings, this.MainSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl).ToString(); + sOutput = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceTopicTokens(new StringBuilder(sOutput), this.topic, this.PortalSettings, this.ModuleSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl).ToString(); sOutput = Utilities.DecodeBrackets(sOutput); sOutput = Utilities.LocalizeControl(sOutput); sOutput = Utilities.StripTokens(sOutput); @@ -958,8 +958,8 @@ private string ParseTopic(string sOutput) var sReplyTemplate = TemplateUtils.GetTemplateSection(sOutput, "[REPLIES]", "[/REPLIES]"); #region "Backward compatilbility -- remove in v10.00.00" - sTopicTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyUserTokenSynonyms(new StringBuilder(sTopicTemplate), this.PortalSettings, this.MainSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale).ToString(); - sTopicTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyAuthorTokenSynonyms(new StringBuilder(sTopicTemplate), this.PortalSettings, this.MainSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale).ToString(); + sTopicTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyUserTokenSynonyms(new StringBuilder(sTopicTemplate), this.PortalSettings, this.ModuleSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale).ToString(); + sTopicTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyAuthorTokenSynonyms(new StringBuilder(sTopicTemplate), this.PortalSettings, this.ModuleSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale).ToString(); sTopicTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyTopicTokenSynonyms(new StringBuilder(sTopicTemplate), this.PortalSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale).ToString(); sTopicTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyPostTokenSynonyms(new StringBuilder(sTopicTemplate), this.PortalSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale).ToString(); sReplyTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyPostTokenSynonyms(new StringBuilder(sReplyTemplate), this.PortalSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale).ToString(); @@ -1021,7 +1021,7 @@ private string ParseTopic(string sOutput) /* this handles token replacement for anything outside of the [TOPIC] or [REPLIES] sections */ sOutput = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyTopicTokenSynonyms(new StringBuilder(sOutput), this.PortalSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale).ToString(); - sOutput = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceTopicTokens(new StringBuilder(sOutput), this.topic, this.PortalSettings, this.MainSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl).ToString(); + sOutput = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceTopicTokens(new StringBuilder(sOutput), this.topic, this.PortalSettings, this.ModuleSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl).ToString(); return sOutput; } @@ -1115,13 +1115,13 @@ private string ParseContent(DataRow dr, string template, int rowcount) }; sbOutput.Replace("[ATTACHMENTS]", this.GetAttachments(reply.ContentId, true, this.PortalId, this.ForumModuleId)); sbOutput.Replace("[SPLITCHECKBOX]", "
"); - sbOutput = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplacePostTokens(sbOutput, reply, this.PortalSettings, this.MainSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl); + sbOutput = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplacePostTokens(sbOutput, reply, this.PortalSettings, this.ModuleSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl); } else { sbOutput.Replace("[ATTACHMENTS]", this.GetAttachments(this.topic.ContentId, true, this.PortalId, this.ForumModuleId)); sbOutput.Replace("[SPLITCHECKBOX]", string.Empty); - sbOutput = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplacePostTokens(sbOutput, this.topic, this.PortalSettings, this.MainSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl); + sbOutput = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplacePostTokens(sbOutput, this.topic, this.PortalSettings, this.ModuleSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl); } sOutput = sbOutput.ToString(); @@ -1218,13 +1218,13 @@ private void BuildPager() pager1.CurrentPage = this.PageId; pager1.TabID = Utilities.SafeConvertInt(this.Request.Params["TabId"], -1); pager1.ForumID = this.ForumId; - pager1.UseShortUrls = this.MainSettings.UseShortUrls; + pager1.UseShortUrls = this.ModuleSettings.UseShortUrls; pager1.PageText = Utilities.GetSharedResource("[RESX:Page]"); pager1.OfText = Utilities.GetSharedResource("[RESX:PageOf]"); pager1.View = Views.Topic; pager1.TopicId = this.topic.TopicId; pager1.PageMode = PagerNav.Mode.Links; - if (this.MainSettings.URLRewriteEnabled) + if (this.ModuleSettings.URLRewriteEnabled) { pager1.BaseURL = URL.ForumLink(this.TabId, this.ForumInfo) + this.topic.TopicUrl; } @@ -1238,13 +1238,13 @@ private void BuildPager() pager2.CurrentPage = this.PageId; pager2.TabID = Utilities.SafeConvertInt(this.Request.Params["TabId"], -1); pager2.ForumID = this.ForumId; - pager2.UseShortUrls = this.MainSettings.UseShortUrls; + pager2.UseShortUrls = this.ModuleSettings.UseShortUrls; pager2.PageText = Utilities.GetSharedResource("[RESX:Page]"); pager2.OfText = Utilities.GetSharedResource("[RESX:PageOf]"); pager2.View = Views.Topic; pager2.TopicId = this.topic.TopicId; pager2.PageMode = PagerNav.Mode.Links; - if (this.MainSettings.URLRewriteEnabled) + if (this.ModuleSettings.URLRewriteEnabled) { pager2.BaseURL = URL.ForumLink(this.TabId, this.ForumInfo) + this.topic.TopicUrl; } diff --git a/Dnn.CommunityForums/CustomControls/UserControls/TopicsView.cs b/Dnn.CommunityForums/CustomControls/UserControls/TopicsView.cs index df30fcb91..f3a7f6366 100644 --- a/Dnn.CommunityForums/CustomControls/UserControls/TopicsView.cs +++ b/Dnn.CommunityForums/CustomControls/UserControls/TopicsView.cs @@ -127,15 +127,15 @@ protected override void OnLoad(EventArgs e) } topicsTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.RemoveObsoleteTokens(new StringBuilder(topicsTemplate)).ToString(); - topicsTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyUserTokenSynonyms(new StringBuilder(topicsTemplate), this.PortalSettings, this.MainSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale).ToString(); - topicsTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyAuthorTokenSynonyms(new StringBuilder(topicsTemplate), this.PortalSettings, this.MainSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale).ToString(); + topicsTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyUserTokenSynonyms(new StringBuilder(topicsTemplate), this.PortalSettings, this.ModuleSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale).ToString(); + topicsTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyAuthorTokenSynonyms(new StringBuilder(topicsTemplate), this.PortalSettings, this.ModuleSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale).ToString(); topicsTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyForumTokenSynonyms(new StringBuilder(topicsTemplate), this.PortalSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale).ToString(); topicsTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyTopicTokenSynonyms(new StringBuilder(topicsTemplate), this.PortalSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale).ToString(); topicsTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyTopicActionTokenSynonyms(new StringBuilder(topicsTemplate), this.PortalSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale, this.useListActions).ToString(); #endregion "Backward compatilbility -- remove in v10.00.00" - this.pageSize = this.MainSettings.PageSize; + this.pageSize = this.ModuleSettings.PageSize; if (this.UserId > 0) { this.pageSize = this.UserDefaultPageSize; @@ -198,7 +198,7 @@ protected override void OnLoad(EventArgs e) this.isSubscribedForum = new DotNetNuke.Modules.ActiveForums.Controllers.SubscriptionController().Subscribed(this.PortalId, this.ForumModuleId, this.UserId, this.ForumId); } - if (this.MainSettings.UseSkinBreadCrumb) + if (this.ModuleSettings.UseSkinBreadCrumb) { string groupURL = new ControlUtils().BuildUrl(this.PortalId, this.TabId, this.ModuleId, this.ForumInfo.ForumGroup.PrefixURL, string.Empty, this.ForumInfo.ForumGroupId, -1, -1, -1, string.Empty, 1, -1, this.SocialGroupId); DotNetNuke.Modules.ActiveForums.Environment.UpdateBreadCrumb(this.Page.Controls, "" + this.ForumInfo.ForumGroup.GroupName + ""); @@ -215,7 +215,7 @@ protected override void OnLoad(EventArgs e) if (!string.IsNullOrEmpty(this.MetaTemplate)) { this.MetaTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.RemoveObsoleteTokens(new StringBuilder(this.MetaTemplate)).ToString(); - this.MetaTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceForumTokens(new StringBuilder(this.MetaTemplate), this.ForumInfo, this.PortalSettings, this.MainSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.TabId, this.ForumUser.CurrentUserType, this.Request.Url, this.Request.RawUrl).ToString(); + this.MetaTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceForumTokens(new StringBuilder(this.MetaTemplate), this.ForumInfo, this.PortalSettings, this.ModuleSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.TabId, this.ForumUser.CurrentUserType, this.Request.Url, this.Request.RawUrl).ToString(); this.MetaTitle = TemplateUtils.GetTemplateSection(this.MetaTemplate, "[TITLE]", "[/TITLE]").Replace("[TITLE]", string.Empty).Replace("[/TITLE]", string.Empty); this.MetaTitle = this.MetaTitle.TruncateAtWord(SEOConstants.MaxMetaTitleLength); this.MetaDescription = TemplateUtils.GetTemplateSection(this.MetaTemplate, "[DESCRIPTION]", "[/DESCRIPTION]").Replace("[DESCRIPTION]", string.Empty).Replace("[/DESCRIPTION]", string.Empty); @@ -310,7 +310,7 @@ private void BindTopics(string topicsTemplate) } StringBuilder stringBuilder = new StringBuilder(sOutput); - stringBuilder = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceForumTokens(stringBuilder, this.ForumInfo, this.PortalSettings, this.MainSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.TabId, this.ForumUser.CurrentUserType, this.Request.Url, this.Request.RawUrl); + stringBuilder = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceForumTokens(stringBuilder, this.ForumInfo, this.PortalSettings, this.ModuleSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.TabId, this.ForumUser.CurrentUserType, this.Request.Url, this.Request.RawUrl); sOutput = stringBuilder.ToString(); sOutput = Utilities.LocalizeControl(sOutput); @@ -371,7 +371,7 @@ private void LinkControls(ControlCollection ctrls) private string ParseControls(string Template) { - string MyTheme = this.MainSettings.Theme; + string MyTheme = this.ModuleSettings.Theme; string sOutput = Template; sOutput = "<%@ Register TagPrefix=\"ac\" Namespace=\"DotNetNuke.Modules.ActiveForums.Controls\" Assembly=\"DotNetNuke.Modules.ActiveForums\" %>" + sOutput; @@ -434,7 +434,7 @@ private string ParseControls(string Template) if (this.Request.IsAuthenticated) { string Url = this.NavigateUrl(this.TabId, string.Empty, new string[] { ParamKeys.ViewType + "=sendto", ParamKeys.ForumId + "=" + this.ForumId, ParamKeys.TopicId + "=" + this.TopicId }); - sOutput = sOutput.Replace("[AF:CONTROL:EMAIL]", "\"[RESX:EmailThis]\""); + sOutput = sOutput.Replace("[AF:CONTROL:EMAIL]", "\"[RESX:EmailThis]\""); } else { @@ -617,7 +617,7 @@ private string ParseTopics(string Template, DataTable Topics, string Section) stringBuilder.Replace("[AF:URL:LASTREAD]", string.Empty); } - stringBuilder = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceTopicTokens(stringBuilder, topicInfo, this.PortalSettings, this.MainSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl); + stringBuilder = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceTopicTokens(stringBuilder, topicInfo, this.PortalSettings, this.ModuleSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl); stringBuilder.Replace("[LASTPOST]", string.Empty).Replace("[/LASTPOST]", string.Empty); stringBuilder.Replace("[ROWCSS]", this.GetRowCSS(UserLastTopicRead, UserLastReplyRead, topicInfo.TopicId, topicInfo.LastReplyId, rowcount)); @@ -657,7 +657,7 @@ private void BuildPager() intPages = Convert.ToInt32(System.Math.Ceiling(this.topicRowCount / (double)this.pageSize)); pager1.PageCount = intPages; pager1.PageMode = PagerNav.Mode.Links; - if (this.MainSettings.URLRewriteEnabled) + if (this.ModuleSettings.URLRewriteEnabled) { pager1.BaseURL = URL.ForumLink(this.TabId, this.ForumInfo); } @@ -665,7 +665,7 @@ private void BuildPager() pager1.CurrentPage = this.PageId; pager1.TabID = Convert.ToInt32(this.Request.Params["TabId"]); pager1.ForumID = this.ForumId; - pager1.UseShortUrls = this.MainSettings.UseShortUrls; + pager1.UseShortUrls = this.ModuleSettings.UseShortUrls; pager1.PageText = Utilities.GetSharedResource("[RESX:Page]"); pager1.OfText = Utilities.GetSharedResource("[RESX:PageOf]"); pager1.View = Views.Topics; @@ -683,11 +683,11 @@ private void BuildPager() if (pager2 != null) { pager2.PageMode = Modules.ActiveForums.Controls.PagerNav.Mode.Links; - if (this.MainSettings.URLRewriteEnabled) + if (this.ModuleSettings.URLRewriteEnabled) { pager2.BaseURL = URL.ForumLink(this.TabId, this.ForumInfo); } - pager2.UseShortUrls = this.MainSettings.UseShortUrls; + pager2.UseShortUrls = this.ModuleSettings.UseShortUrls; pager2.PageCount = intPages; pager2.CurrentPage = this.PageId; pager2.TabID = Convert.ToInt32(this.Request.Params["TabId"]); @@ -707,7 +707,7 @@ private string GetSubPages(int tabID, int replies, int forumID, int postID) if (replies + 1 > this.pageSize) { List Params = new List(); - sOut = "
(\"[RESX:MultiPageTopic]\""; + sOut = "
(\"[RESX:MultiPageTopic]\""; // Jump to pages int intPostPages = 0; @@ -718,7 +718,7 @@ private string GetSubPages(int tabID, int replies, int forumID, int postID) { Params = new List { ParamKeys.ForumId + "=" + forumID, ParamKeys.TopicId + "=" + postID, ParamKeys.ViewType + "=" + Views.Topic }; - if (this.MainSettings.UseShortUrls) + if (this.ModuleSettings.UseShortUrls) { Params = new List { ParamKeys.TopicId + "=" + postID }; } @@ -736,7 +736,7 @@ private string GetSubPages(int tabID, int replies, int forumID, int postID) } Params = new List { ParamKeys.ForumId + "=" + forumID, ParamKeys.TopicId + "=" + postID, ParamKeys.ViewType + "=" + Views.Topic }; - if (this.MainSettings.UseShortUrls) + if (this.ModuleSettings.UseShortUrls) { Params = new List { ParamKeys.TopicId + "=" + postID }; } @@ -756,7 +756,7 @@ private string GetSubPages(int tabID, int replies, int forumID, int postID) for (i = 1; i <= intPostPages; i++) { Params = new List { ParamKeys.ForumId + "=" + forumID, ParamKeys.TopicId + "=" + postID, ParamKeys.ViewType + "=" + Views.Topic }; - if (this.MainSettings.UseShortUrls) + if (this.ModuleSettings.UseShortUrls) { Params = new List { ParamKeys.TopicId + "=" + postID }; } diff --git a/Dnn.CommunityForums/CustomControls/UserControls/UserProfile.cs b/Dnn.CommunityForums/CustomControls/UserControls/UserProfile.cs index d94855658..2d0e5cde1 100644 --- a/Dnn.CommunityForums/CustomControls/UserControls/UserProfile.cs +++ b/Dnn.CommunityForums/CustomControls/UserControls/UserProfile.cs @@ -116,7 +116,7 @@ protected override void OnInit(EventArgs e) protected override void OnLoad(EventArgs e) { base.OnLoad(e); - string sTemplate = DotNetNuke.Modules.ActiveForums.Controllers.TemplateController.Template_Get(this.ForumModuleId, Enums.TemplateType._userProfile, SettingsBase.GetModuleSettings(this.ForumModuleId).ForumFeatureSettings.TemplateFileNameSuffix); + string sTemplate = DotNetNuke.Modules.ActiveForums.Controllers.TemplateController.Template_Get(this.ForumModuleId, Enums.TemplateType._userProfile, SettingsBase.GetModuleSettings(this.ForumModuleId).DefaultFeatureSettings.TemplateFileNameSuffix); if (this.ProfileMode == ProfileModes.Edit) { @@ -226,7 +226,7 @@ protected override void OnLoad(EventArgs e) { ForumView ctlForums = new ForumView(); ctlForums.ModuleConfiguration = this.ModuleConfiguration; - ctlForums.DisplayTemplate = DotNetNuke.Modules.ActiveForums.Controllers.TemplateController.Template_Get(this.ForumModuleId, (Enums.TemplateType)Enum.Parse(typeof(Enums.TemplateType), "ForumTracking", true), SettingsBase.GetModuleSettings(this.ForumModuleId).ForumFeatureSettings.TemplateFileNameSuffix); + ctlForums.DisplayTemplate = DotNetNuke.Modules.ActiveForums.Controllers.TemplateController.Template_Get(this.ForumModuleId, (Enums.TemplateType)Enum.Parse(typeof(Enums.TemplateType), "ForumTracking", true), SettingsBase.GetModuleSettings(this.ForumModuleId).DefaultFeatureSettings.TemplateFileNameSuffix); ctlForums.CurrentUserId = this.UID; ctlForums.ForumIds = user.UserForums; this.plhTracker.Controls.Add(ctlForums); @@ -358,13 +358,13 @@ private bool SaveProfile() var user = new DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController(this.ForumModuleId).GetByUserId(this.PortalId, this.UID); if (user != null) { - if (this.MainSettings.AllowSignatures == 1) + if (this.ModuleSettings.AllowSignatures == 1) { user.Signature = Utilities.XSSFilter(this.txtSignature.Text, true); user.Signature = Utilities.StripHTMLTag(user.Signature); user.Signature = System.Net.WebUtility.HtmlEncode(user.Signature); } - else if (this.MainSettings.AllowSignatures == 2) + else if (this.ModuleSettings.AllowSignatures == 2) { user.Signature = Utilities.XSSFilter(this.txtSignature.Text, false); } diff --git a/Dnn.CommunityForums/DnnCommunityForums.dnn b/Dnn.CommunityForums/DnnCommunityForums.dnn index 25eeaebdc..5fd38177c 100644 --- a/Dnn.CommunityForums/DnnCommunityForums.dnn +++ b/Dnn.CommunityForums/DnnCommunityForums.dnn @@ -1,6 +1,6 @@  - + DNN Community Forums DNN Community Forums: The official online forums module for the DNN Community. DesktopModules/ActiveForums/images/branding/logo/DNN-Community-Forums-Icon-64px.png @@ -86,7 +86,7 @@ DotNetNuke.Modules.ActiveForums.dll bin\DotNetNuke.Modules.ActiveForums.dll - 09.01.01 + 09.02.00 @@ -439,10 +439,15 @@ 09.01.00.SqlDataProvider 09.01.00 + @@ -486,7 +491,7 @@ - + DNN Community Forums What's New ActiveForumsWhatsNew DNN Community Forums: Display the most recent topics or replies from selected forums on any page within your site. @@ -555,7 +560,7 @@ - + DNN Community Forums Forums Viewer ActiveForumsViewer DNN Community Forums: Display any forum topic view on any page within your site. diff --git a/Dnn.CommunityForums/DnnCommunityForums_Symbols.dnn b/Dnn.CommunityForums/DnnCommunityForums_Symbols.dnn index 7a9340c9a..be5cde55a 100644 --- a/Dnn.CommunityForums/DnnCommunityForums_Symbols.dnn +++ b/Dnn.CommunityForums/DnnCommunityForums_Symbols.dnn @@ -1,6 +1,6 @@  - + DNN Community Forums Symbols DNN Community Forums: The official online forums module for the DNN Community. DesktopModules/ActiveForums/images/branding/logo/DNN-Community-Forums-Icon-64px.png @@ -14,7 +14,7 @@ True - Active Forums + Active Forums diff --git a/Dnn.CommunityForums/Entities/FeatureSettings.cs b/Dnn.CommunityForums/Entities/FeatureSettings.cs index 457a83319..33b380255 100644 --- a/Dnn.CommunityForums/Entities/FeatureSettings.cs +++ b/Dnn.CommunityForums/Entities/FeatureSettings.cs @@ -41,12 +41,18 @@ public FeatureSettings(Hashtable featureSettings) internal static void Save(int moduleId, string settingsKey, FeatureSettings settings) { + new DotNetNuke.Modules.ActiveForums.Controllers.SettingsController().DeleteForModuleIdSettingsKey(moduleId, settingsKey); foreach (DictionaryEntry setting in settings.featureSettings) { - Settings.SaveSetting(moduleId, settingsKey, setting.Key.ToString(), setting.Value.ToString()); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, settingsKey, setting.Key.ToString(), setting.Value.ToString()); } } + internal static void Delete(int moduleId, string settingsKey, string settingName) + { + new DotNetNuke.Modules.ActiveForums.Controllers.SettingsController().DeleteForModuleIdSettingsKeySettingName(moduleId, settingsKey, settingName); + } + [IgnoreColumn] public bool AllowAttach => Utilities.SafeConvertBool(this.featureSettings[ForumSettingKeys.AllowAttach]); diff --git a/Dnn.CommunityForums/Entities/ForumGroupInfo.cs b/Dnn.CommunityForums/Entities/ForumGroupInfo.cs index f807189c3..958ffb693 100644 --- a/Dnn.CommunityForums/Entities/ForumGroupInfo.cs +++ b/Dnn.CommunityForums/Entities/ForumGroupInfo.cs @@ -40,7 +40,7 @@ public partial class ForumGroupInfo : DotNetNuke.Services.Tokens.IPropertyAccess private DotNetNuke.Modules.ActiveForums.Entities.PermissionInfo security; private FeatureSettings featureSettings; - private DotNetNuke.Modules.ActiveForums.SettingsInfo mainSettings; + private DotNetNuke.Modules.ActiveForums.ModuleSettings moduleSettings; private PortalSettings portalSettings; private ModuleInfo moduleInfo; private int? tabId; @@ -79,10 +79,10 @@ public int TabId public string ThemeLocation => Utilities.ResolveUrl(SettingsBase.GetModuleSettings(this.ModuleId).ThemeLocation); [IgnoreColumn] - public bool InheritSecurity => this.PermissionsId == this.MainSettings.DefaultPermissionId; + public bool InheritSecurity => this.PermissionsId == this.ModuleSettings.DefaultPermissionId; [IgnoreColumn] - public bool InheritSettings => this.GroupSettingsKey == this.MainSettings.DefaultSettingsKey; + public bool InheritSettings => this.GroupSettingsKey == this.ModuleSettings.DefaultSettingsKey; [IgnoreColumn] public DotNetNuke.Modules.ActiveForums.Entities.PermissionInfo Security @@ -148,29 +148,29 @@ internal FeatureSettings LoadFeatureSettings() } [IgnoreColumn] - public SettingsInfo MainSettings + public DotNetNuke.Modules.ActiveForums.ModuleSettings ModuleSettings { get { - if (this.mainSettings == null) + if (this.moduleSettings == null) { - this.mainSettings = this.LoadMainSettings(); + this.moduleSettings = this.LoadModuleSettings(); this.UpdateCache(); } - return this.mainSettings; + return this.moduleSettings; } set { - this.mainSettings = value; + this.moduleSettings = value; this.UpdateCache(); } } - internal SettingsInfo LoadMainSettings() + internal DotNetNuke.Modules.ActiveForums.ModuleSettings LoadModuleSettings() { - return this.mainSettings = SettingsBase.GetModuleSettings(this.ModuleId); + return this.moduleSettings = SettingsBase.GetModuleSettings(this.ModuleId); } [IgnoreColumn] diff --git a/Dnn.CommunityForums/Entities/ForumInfo.cs b/Dnn.CommunityForums/Entities/ForumInfo.cs index 4e52db101..7de1323a8 100644 --- a/Dnn.CommunityForums/Entities/ForumInfo.cs +++ b/Dnn.CommunityForums/Entities/ForumInfo.cs @@ -50,7 +50,7 @@ public class ForumInfo : DotNetNuke.Services.Tokens.IPropertyAccess private DotNetNuke.Modules.ActiveForums.Entities.PermissionInfo security; private DotNetNuke.Modules.ActiveForums.Entities.IPostInfo lastPostInfo; private FeatureSettings featureSettings; - private DotNetNuke.Modules.ActiveForums.SettingsInfo mainSettings; + private DotNetNuke.Modules.ActiveForums.ModuleSettings mainSettings; private PortalSettings portalSettings; private ModuleInfo moduleInfo; private int? subscriberCount; @@ -547,7 +547,7 @@ internal PermissionInfo LoadSecurity() } [IgnoreColumn] - public SettingsInfo MainSettings + public DotNetNuke.Modules.ActiveForums.ModuleSettings MainSettings { get { @@ -567,7 +567,7 @@ public SettingsInfo MainSettings } } - internal SettingsInfo LoadMainSettings() + internal DotNetNuke.Modules.ActiveForums.ModuleSettings LoadMainSettings() { return this.mainSettings = SettingsBase.GetModuleSettings(this.ModuleId); } @@ -713,7 +713,7 @@ internal string GetForumStatusCss(DotNetNuke.Modules.ActiveForums.Entities.Forum } } - internal string GetForumFolderIcon(DotNetNuke.Modules.ActiveForums.Entities.ForumUserInfo forumUser, DotNetNuke.Modules.ActiveForums.SettingsInfo mainSettings) + internal string GetForumFolderIcon(DotNetNuke.Modules.ActiveForums.Entities.ForumUserInfo forumUser, DotNetNuke.Modules.ActiveForums.ModuleSettings mainSettings) { switch (this.GetForumStatusForUser(forumUser)) { diff --git a/Dnn.CommunityForums/Entities/ForumUserInfo.cs b/Dnn.CommunityForums/Entities/ForumUserInfo.cs index e7817cdf9..02a4fab38 100644 --- a/Dnn.CommunityForums/Entities/ForumUserInfo.cs +++ b/Dnn.CommunityForums/Entities/ForumUserInfo.cs @@ -42,7 +42,7 @@ public class ForumUserInfo : DotNetNuke.Services.Tokens.IPropertyAccess private DotNetNuke.Entities.Users.UserInfo userInfo; private PortalSettings portalSettings; - private SettingsInfo mainSettings; + private DotNetNuke.Modules.ActiveForums.ModuleSettings moduleSettings; private ModuleInfo moduleInfo; private HashSet userRoleIds; private string userPermSet; @@ -262,29 +262,29 @@ public CurrentUserTypes CurrentUserType TimeSpan TimeZoneOffsetForUser => Utilities.GetTimeZoneOffsetForUser(this.UserInfo); [IgnoreColumn] - public SettingsInfo MainSettings + public DotNetNuke.Modules.ActiveForums.ModuleSettings ModuleSettings { get { - if (this.mainSettings == null) + if (this.moduleSettings == null) { - this.mainSettings = this.LoadMainSettings(); + this.moduleSettings = this.LoadModuleSettings(); this.UpdateCache(); } - return this.mainSettings; + return this.moduleSettings; } set { - this.mainSettings = value; + this.moduleSettings = value; this.UpdateCache(); } } - internal SettingsInfo LoadMainSettings() + internal DotNetNuke.Modules.ActiveForums.ModuleSettings LoadModuleSettings() { - return this.mainSettings = SettingsBase.GetModuleSettings(this.ModuleId); + return this.moduleSettings = SettingsBase.GetModuleSettings(this.ModuleId); } [IgnoreColumn] @@ -579,8 +579,8 @@ public string GetProperty(string propertyName, string format, System.Globalizati return PropertyAccess.FormatString(string.Empty, format); } - var height = this.MainSettings.AvatarHeight; - var width = this.MainSettings.AvatarWidth; + var height = this.ModuleSettings.AvatarHeight; + var width = this.ModuleSettings.AvatarWidth; if (length > 0) { height = length; @@ -591,7 +591,7 @@ public string GetProperty(string propertyName, string format, System.Globalizati case "usercaption": return PropertyAccess.FormatString(this.UserCaption, format); case "displayname": - return PropertyAccess.FormatString(DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.GetDisplayName(this.PortalSettings, this.MainSettings, isMod: new DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController(this.ModuleId).GetByUserId(portalId: accessingUser.PortalID, userId: accessingUser.UserID).GetIsMod(this.ModuleId), isAdmin: new DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController(this.ModuleId).GetByUserId(portalId: accessingUser.PortalID, userId: accessingUser.UserID).IsAdmin, this.UserId, this.Username, this.FirstName, this.LastName, this.DisplayName), format); + return PropertyAccess.FormatString(DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.GetDisplayName(this.PortalSettings, this.ModuleSettings, isMod: new DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController(this.ModuleId).GetByUserId(portalId: accessingUser.PortalID, userId: accessingUser.UserID).GetIsMod(this.ModuleId), isAdmin: new DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController(this.ModuleId).GetByUserId(portalId: accessingUser.PortalID, userId: accessingUser.UserID).IsAdmin, this.UserId, this.Username, this.FirstName, this.LastName, this.DisplayName), format); case "datecreated": return Utilities.GetUserFormattedDateTime(this.DateCreated, formatProvider, accessingUser.Profile.PreferredTimeZone.GetUtcOffset(DateTime.UtcNow)); case "dateupdated": @@ -611,31 +611,31 @@ public string GetProperty(string propertyName, string format, System.Globalizati case "topiccount": return PropertyAccess.FormatString(this.TopicCount.ToString(), format); case "answercount": - return PropertyAccess.FormatString(this.MainSettings.EnablePoints && this.UserId > 0 ? this.AnswerCount.ToString() : string.Empty, format); + return PropertyAccess.FormatString(this.ModuleSettings.EnablePoints && this.UserId > 0 ? this.AnswerCount.ToString() : string.Empty, format); case "rewardpoints": - return PropertyAccess.FormatString(this.MainSettings.EnablePoints && this.UserId > 0 ? this.RewardPoints.ToString() : string.Empty, format); + return PropertyAccess.FormatString(this.ModuleSettings.EnablePoints && this.UserId > 0 ? this.RewardPoints.ToString() : string.Empty, format); case "totalpoints": - return PropertyAccess.FormatString(this.MainSettings.EnablePoints && this.UserId > 0 ? ((this.TopicCount * this.MainSettings.TopicPointValue) + (this.ReplyCount * this.MainSettings.ReplyPointValue) + (this.AnswerCount * this.MainSettings.AnswerPointValue) + this.RewardPoints).ToString() : string.Empty, format); + return PropertyAccess.FormatString(this.ModuleSettings.EnablePoints && this.UserId > 0 ? ((this.TopicCount * this.ModuleSettings.TopicPointValue) + (this.ReplyCount * this.ModuleSettings.ReplyPointValue) + (this.AnswerCount * this.ModuleSettings.AnswerPointValue) + this.RewardPoints).ToString() : string.Empty, format); case "rankdisplay": return PropertyAccess.FormatString(this.UserId > 0 ? DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.GetUserRank(this.ModuleId, this, 0) : string.Empty, format); case "rankname": return PropertyAccess.FormatString(this.UserId > 0 ? DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.GetUserRank(this.ModuleId, this, 1) : string.Empty, format); case "userprofilelink": return PropertyAccess.FormatString(DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.CanLinkToProfile(portalSettings: this.PortalSettings, - mainSettings: this.MainSettings, + moduleSettings: this.ModuleSettings, moduleId: this.ModuleId, accessingUser: new DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController(this.ModuleId).GetByUserId(accessingUser.PortalID, accessingUser.UserID), forumUser: this) ? Utilities.NavigateURL(this.PortalSettings.UserTabId, string.Empty, new[] { $"userId={this.UserId}" }) : string.Empty, format); case "signature": var sSignature = string.Empty; - if (this.MainSettings.AllowSignatures != 0 && !this.PrefBlockSignatures && !this.SignatureDisabled) + if (this.ModuleSettings.AllowSignatures != 0 && !this.PrefBlockSignatures && !this.SignatureDisabled) { sSignature = this?.Signature ?? string.Empty; if (!string.IsNullOrEmpty(sSignature)) { sSignature = Utilities.ManageImagePath(sSignature, this.RequestUri); - switch (this.MainSettings.AllowSignatures) + switch (this.ModuleSettings.AllowSignatures) { case 1: sSignature = System.Net.WebUtility.HtmlEncode(sSignature); @@ -651,12 +651,12 @@ public string GetProperty(string propertyName, string format, System.Globalizati return PropertyAccess.FormatString(sSignature, format); case "userstatus": { - return PropertyAccess.FormatString(this.MainSettings != null && this.MainSettings.UsersOnlineEnabled && this.UserId > 0 ? DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.GetTokenFormatString(this.IsUserOnline ? "[FORUMUSER-USERONLINE]" : "[FORUMUSER-USEROFFLINE]", this.PortalSettings, accessingUser.Profile.PreferredLocale) : string.Empty, format); + return PropertyAccess.FormatString(this.ModuleSettings != null && this.ModuleSettings.UsersOnlineEnabled && this.UserId > 0 ? DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.GetTokenFormatString(this.IsUserOnline ? "[FORUMUSER-USERONLINE]" : "[FORUMUSER-USEROFFLINE]", this.PortalSettings, accessingUser.Profile.PreferredLocale) : string.Empty, format); } case "userstatuscss": { - return PropertyAccess.FormatString(this.MainSettings != null && this.MainSettings.UsersOnlineEnabled && this.UserId > 0 ? DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.GetTokenFormatString(this.IsUserOnline ? "[FORUMUSER-USERONLINECSS]" : "[FORUMUSER-USEROFFLINECSS]", this.PortalSettings, accessingUser.Profile.PreferredLocale) : string.Empty, format); + return PropertyAccess.FormatString(this.ModuleSettings != null && this.ModuleSettings.UsersOnlineEnabled && this.UserId > 0 ? DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.GetTokenFormatString(this.IsUserOnline ? "[FORUMUSER-USERONLINECSS]" : "[FORUMUSER-USEROFFLINECSS]", this.PortalSettings, accessingUser.Profile.PreferredLocale) : string.Empty, format); } case "userid": @@ -668,7 +668,7 @@ public string GetProperty(string propertyName, string format, System.Globalizati return PropertyAccess.FormatString( Controllers.ForumUserController.CanLinkToProfile( this.PortalSettings, - this.MainSettings, + this.ModuleSettings, this.ModuleId, new Controllers.ForumUserController(this.ModuleId).GetByUserId( accessingUser.PortalID, @@ -685,7 +685,7 @@ public string GetProperty(string propertyName, string format, System.Globalizati return PropertyAccess.FormatString(string.IsNullOrEmpty(this.DisplayName) ? this.Username : DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.GetDisplayName( this.PortalSettings, - this.MainSettings, + this.ModuleSettings, isMod: new DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController(this.ModuleId).GetByUserId(accessingUser.PortalID, accessingUser.UserID).GetIsMod(this.ModuleId), isAdmin: new DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController(this.ModuleId).GetByUserId(accessingUser.PortalID, accessingUser.UserID).IsAdmin || new DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController(this.ModuleId).GetByUserId(accessingUser.PortalID, accessingUser.UserID).IsSuperUser, this.UserId, diff --git a/Dnn.CommunityForums/Entities/SettingsInfo.cs b/Dnn.CommunityForums/Entities/SettingsInfo.cs new file mode 100644 index 000000000..bfba7e61c --- /dev/null +++ b/Dnn.CommunityForums/Entities/SettingsInfo.cs @@ -0,0 +1,43 @@ +// Copyright (c) by DNN Community +// +// DNN Community licenses this file to you under the MIT license. +// +// See the LICENSE file in the project root for more information. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +namespace DotNetNuke.Modules.ActiveForums.Entities +{ + using System.Web.Caching; + + using DotNetNuke.ComponentModel.DataAnnotations; + + [TableName("activeforums_Settings")] + [PrimaryKey("SettingsId", AutoIncrement = true)] + [Scope("ModuleId")] + [Cacheable("activeforums_Settings", CacheItemPriority.High)] + public partial class SettingsInfo + { + public int ModuleId { get; set; } + + public int SettingsId { get; set; } + + public string SettingsKey { get; set; } + + public string SettingName { get; set; } + + public string SettingValue { get; set; } + } +} diff --git a/Dnn.CommunityForums/Providers/DataProviders/SqlDataProvider/SqlDataProvider.cs b/Dnn.CommunityForums/Providers/DataProviders/SqlDataProvider/SqlDataProvider.cs index b553ad276..5ca477ae0 100644 --- a/Dnn.CommunityForums/Providers/DataProviders/SqlDataProvider/SqlDataProvider.cs +++ b/Dnn.CommunityForums/Providers/DataProviders/SqlDataProvider/SqlDataProvider.cs @@ -403,27 +403,31 @@ public override IDataReader Security_GetByKey(string SecurityKey) #endregion #region Settings + [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. No Longer Used.")] public override void Settings_Delete(int ModuleId, string GroupKey, string SettingName) { SqlHelper.ExecuteNonQuery(this.ConnectionString, this.DatabaseOwner + this.ObjectQualifier + "activeforums_Settings_Delete", ModuleId, GroupKey, SettingName); } + [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. No Longer Used.")] public override string Settings_Get(int ModuleId, string GroupKey, string SettingName) { return Convert.ToString(SqlHelper.ExecuteScalar(this.ConnectionString, this.DatabaseOwner + this.ObjectQualifier + "activeforums_Settings_Get", ModuleId, GroupKey, SettingName)); } + [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. No Longer Used.")] public override System.Data.IDataReader Settings_List(int ModuleId, string GroupKey) { return SqlHelper.ExecuteReader(this.ConnectionString, this.DatabaseOwner + this.ObjectQualifier + "activeforums_Settings_List", ModuleId, GroupKey); } - // KR - grabs all settings for caching + [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. No Longer Used.")] public override System.Data.IDataReader Settings_ListAll(int ModuleId) { return SqlHelper.ExecuteReader(this.ConnectionString, this.DatabaseOwner + this.ObjectQualifier + "activeforums_Settings_ListAll", ModuleId); } + [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. No Longer Used.")] public override void Settings_Save(int ModuleId, string GroupKey, string SettingName, string SettingValue) { SqlHelper.ExecuteNonQuery(this.ConnectionString, this.DatabaseOwner + this.ObjectQualifier + "activeforums_Settings_Save", ModuleId, GroupKey, SettingName, SettingValue); diff --git a/Dnn.CommunityForums/ReleaseNotes.txt b/Dnn.CommunityForums/ReleaseNotes.txt index 429149212..a8381f77c 100644 --- a/Dnn.CommunityForums/ReleaseNotes.txt +++ b/Dnn.CommunityForums/ReleaseNotes.txt @@ -46,16 +46,16 @@ DNN Community Forums Release Notes

- 09.01.01 + 09.02.00

  • None at this time.
  • Bug Fixes

      -
    • FIX: Poor performance for avatar refresh queue on large sites (Issue 1584)
    • -

    Tasks / Development Updates (and Technical Debt)

      +
    • Modernize "Settings" table (Issue 1582)
    • +
    • 09.02.00 Release Prep (Issue TBD)
    • None at this time.
    • +-->

    diff --git a/Dnn.CommunityForums/Services/AdminServiceController.cs b/Dnn.CommunityForums/Services/AdminServiceController.cs index f2b8244d0..1cb8e8f5d 100644 --- a/Dnn.CommunityForums/Services/AdminServiceController.cs +++ b/Dnn.CommunityForums/Services/AdminServiceController.cs @@ -72,7 +72,7 @@ public class RunMaintenanceDTO public HttpResponseMessage RunMaintenance(RunMaintenanceDTO dto) { - var moduleSettings = new SettingsInfo { ModuleId = dto.ModuleId, MainSettings = DotNetNuke.Entities.Modules.ModuleController.Instance.GetModule(moduleId: dto.ModuleId, DotNetNuke.Common.Utilities.Null.NullInteger, true).ModuleSettings }; + var moduleSettings = new ModuleSettings { ModuleId = dto.ModuleId, MainSettings = DotNetNuke.Entities.Modules.ModuleController.Instance.GetModule(moduleId: dto.ModuleId, DotNetNuke.Common.Utilities.Null.NullInteger, true).ModuleSettings }; var rows = DataProvider.Instance().Forum_Maintenance(dto.ForumId, dto.OlderThan, dto.LastActive, dto.ByUserId, dto.WithNoReplies, dto.DryRun, (int)moduleSettings.DeleteBehavior); if (dto.DryRun) { diff --git a/Dnn.CommunityForums/Services/Controllers/ControllerBase.cs b/Dnn.CommunityForums/Services/Controllers/ControllerBase.cs index 39cc04fa6..2c5946976 100644 --- a/Dnn.CommunityForums/Services/Controllers/ControllerBase.cs +++ b/Dnn.CommunityForums/Services/Controllers/ControllerBase.cs @@ -32,7 +32,7 @@ namespace DotNetNuke.Modules.ActiveForums.Services /// /// /// - [SupportedModules(Globals.ModuleName + "," + Globals.ModuleName + " Viewer," + Globals.ModuleFriendlyName + "," + Globals.ModuleFriendlyName + " Viewer")] /* this MUST match DesktopModule.ModuleName so use new constant */ + [SupportedModules(Globals.ModuleName + "," + Globals.ModuleName + " Viewer")] /* this MUST match DesktopModule.ModuleName so use constant */ public class ControllerBase : DnnApiController { private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof(T)); @@ -40,8 +40,8 @@ public class ControllerBase : DnnApiController /// provide a simple method for testing /// /// - [AllowAnonymous] [HttpGet] + [AllowAnonymous] public HttpResponseMessage HelloWorld() { try diff --git a/Dnn.CommunityForums/Services/Controllers/FeatureSettingsController.cs b/Dnn.CommunityForums/Services/Controllers/FeatureSettingsController.cs new file mode 100644 index 000000000..165f00c15 --- /dev/null +++ b/Dnn.CommunityForums/Services/Controllers/FeatureSettingsController.cs @@ -0,0 +1,184 @@ +// Copyright (c) by DNN Community +// +// DNN Community licenses this file to you under the MIT license. +// +// See the LICENSE file in the project root for more information. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +namespace DotNetNuke.Modules.ActiveForums.Services.Controllers +{ + using System; + using System.Collections; + using System.Reflection; + using System.Web.Http; + + using DotNetNuke.Web.Api; + + /// + /// Web API controller for managing feature settings. + /// + public class FeatureSettingsController : ControllerBase + { + /// + /// Gets all settings for a given settings key. + /// + /// settingsKey + /// settings + [HttpGet] + [DnnAuthorize] + [ForumsAuthorize(SecureActions.Ban)] + public IHttpActionResult GetAllSettings(string settingsKey) + { + try + { + var settings = new DotNetNuke.Modules.ActiveForums.Entities.FeatureSettings(this.ForumModuleId, settingsKey); + return this.Ok(settings.featureSettings); + } + catch (Exception ex) + { + return this.InternalServerError(ex); + } + } + + /// + /// Gets a single setting value by key. + /// + /// settingsKey + /// key + /// setting + [HttpGet] + [DnnAuthorize] + [ForumsAuthorize(SecureActions.Ban)] + public IHttpActionResult GetSetting(string settingsKey, string key) + { + try + { + var settings = new DotNetNuke.Modules.ActiveForums.Entities.FeatureSettings(this.ForumModuleId, settingsKey); + if (!settings.featureSettings.ContainsKey(key)) + { + return this.NotFound(); + } + return Ok(settings.featureSettings[key]); + } + catch (Exception ex) + { + return this.InternalServerError(ex); + } + } + + /// + /// Creates or updates a single setting. + /// + /// settingsKey + /// key + /// value + /// HTTP status + [HttpPost] + [DnnAuthorize] + [ForumsAuthorize(SecureActions.Ban)] + public IHttpActionResult SetSetting(string settingsKey, string key, [FromBody] string value) + { + try + { + var settings = new DotNetNuke.Modules.ActiveForums.Entities.FeatureSettings(this.ForumModuleId, settingsKey); + settings.featureSettings[key] = value; + DotNetNuke.Modules.ActiveForums.Entities.FeatureSettings.Save(this.ForumModuleId, settingsKey, settings); + return this.Ok(); + } + catch (Exception ex) + { + return this.InternalServerError(ex); + } + } + + /// + /// Deletes a single setting. + /// + /// settingsKey + /// key + /// HTTP status + [HttpDelete] + [DnnAuthorize] + [ForumsAuthorize(SecureActions.Ban)] + public IHttpActionResult DeleteSetting(string settingsKey, string key) + { + try + { + var settings = new DotNetNuke.Modules.ActiveForums.Entities.FeatureSettings(this.ForumModuleId, settingsKey); + if (!settings.featureSettings.ContainsKey(key)) + { + return this.NotFound(); + } + settings.featureSettings.Remove(key); + DotNetNuke.Modules.ActiveForums.Entities.FeatureSettings.Save(this.ForumModuleId, settingsKey, settings); + return this.Ok(); + } + catch (Exception ex) + { + return this.InternalServerError(ex); + } + } + + /// + /// Updates all settings for a given module and settings key. + /// + /// settingsKey + /// newSettings + /// HTTP status + [HttpPut] + [DnnAuthorize] + [ForumsAuthorize(SecureActions.Ban)] + public IHttpActionResult UpdateAllSettings(string settingsKey, [FromBody] Hashtable newSettings) + { + try + { + var settings = new DotNetNuke.Modules.ActiveForums.Entities.FeatureSettings(newSettings); + DotNetNuke.Modules.ActiveForums.Entities.FeatureSettings.Save(this.ForumModuleId, settingsKey, settings); + return this.Ok(); + } + catch (Exception ex) + { + return this.InternalServerError(ex); + } + } + + /// + /// Deletes all settings for a given settings key. + /// + /// settingsKey + /// HTTP status + [HttpDelete] + [DnnAuthorize] + [ForumsAuthorize(SecureActions.Ban)] + public IHttpActionResult DeleteAllSettings(string settingsKey) + { + try + { + var settings = new DotNetNuke.Modules.ActiveForums.Entities.FeatureSettings(this.ForumModuleId, settingsKey); + foreach (DictionaryEntry entry in settings.featureSettings) + { + new DotNetNuke.Modules.ActiveForums.Controllers.SettingsController().DeleteForModuleIdSettingsKeySettingName(this.ForumModuleId, settingsKey, (string)entry.Key); + } + + return this.Ok(); + } + catch (Exception ex) + { + return this.InternalServerError(ex); + } + } + } +} diff --git a/Dnn.CommunityForums/Services/Controllers/ForumController.cs b/Dnn.CommunityForums/Services/Controllers/ForumController.cs index 87cf5ebaa..e243a982f 100644 --- a/Dnn.CommunityForums/Services/Controllers/ForumController.cs +++ b/Dnn.CommunityForums/Services/Controllers/ForumController.cs @@ -21,16 +21,18 @@ namespace DotNetNuke.Modules.ActiveForums.Services.Controllers { using System; + using System.Collections.Generic; using System.Net; using System.Net.Http; using System.Web.Http; + using System.Web.UI; using DotNetNuke.Web.Api; /// /// /// - public class ForumController : ControllerBase + public class ForumController : ControllerBase { public struct ForumDto { @@ -91,7 +93,7 @@ public HttpResponseMessage SubscriberCount(int forumId) } /// - /// Gets Subscriber count string for a Forum + /// Gets Subscriber count string for a Forum. /// /// /// https://dnndev.me/API/ActiveForums/Forum/SubscriberCountString?ForumId=xxx @@ -115,7 +117,7 @@ public HttpResponseMessage SubscriberCountString(int forumId) } /// - /// Populates list of forums for an HTML control + /// Populates list of forums for an HTML control. /// /// /// @@ -137,5 +139,323 @@ public HttpResponseMessage ListForHtml(ForumDto dto) return this.Request.CreateResponse(HttpStatusCode.BadRequest); } + + /// + /// Gets a forum by ID. + /// + /// Forum ID + /// ForumInfo + /// https://dnndev.me/API/ActiveForums/Forum/Get?forumId=x + [HttpGet] + [DnnAuthorize] + [ForumsAuthorize(SecureActions.Ban)] + public HttpResponseMessage Get(int forumId) + { + try + { + if (forumId > 0) + { + var forum = new DotNetNuke.Modules.ActiveForums.Controllers.ForumController().GetById(forumId: forumId, moduleId: this.ForumModuleId); + if (forum != null) + { + return this.Request.CreateResponse(HttpStatusCode.OK, new DotNetNuke.Modules.ActiveForums.ViewModels.Forum(forum)); + } + + return this.Request.CreateResponse(HttpStatusCode.NotFound); + } + } + catch (Exception ex) + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(ex); + } + + return this.Request.CreateResponse(HttpStatusCode.BadRequest); + } + + /// + /// Creates a new forum. + /// + /// ForumInfo + /// Created forum + [HttpPost] + [DnnAuthorize] + [ValidateAntiForgeryToken] + [ForumsAuthorize(SecureActions.Ban)] + public HttpResponseMessage Create([FromBody] DotNetNuke.Modules.ActiveForums.Entities.ForumInfo forum) + { + try + { + if (forum != null) + { + var fc = new DotNetNuke.Modules.ActiveForums.Controllers.ForumController(); + forum.ForumID = DotNetNuke.Common.Utilities.Null.NullInteger; + forum.ModuleId = this.ForumModuleId; + forum.ParentForumId = 0; + var forumId = fc.Forums_Save(portalId: this.ActiveModule.PortalID, forumInfo: forum, isNew: true, useGroupFeatures: true, useGroupSecurity: true); + var forumCreated = fc.GetById(forumId: forumId, moduleId: this.ForumModuleId); + return this.Request.CreateResponse(HttpStatusCode.Created, forumCreated); + } + } + catch (Exception ex) + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(ex); + } + + return this.Request.CreateResponse(HttpStatusCode.BadRequest); + } + + /// + /// Creates a new forum. + /// + /// ForumInfo + /// + /// + /// Created forum + [HttpPost] + [DnnAuthorize] + [ValidateAntiForgeryToken] + [ForumsAuthorize(SecureActions.Ban)] + public HttpResponseMessage Create([FromBody] DotNetNuke.Modules.ActiveForums.Entities.ForumInfo forum, bool useGroupFeatures, bool useGroupSecurity) + { + try + { + if (forum != null) + { + var fc = new DotNetNuke.Modules.ActiveForums.Controllers.ForumController(); + forum.ForumID = DotNetNuke.Common.Utilities.Null.NullInteger; + forum.ModuleId = this.ForumModuleId; + forum.ParentForumId = 0; + var forumId = fc.Forums_Save(portalId: this.ActiveModule.PortalID, forumInfo: forum, isNew: true, useGroupFeatures: useGroupFeatures, useGroupSecurity: useGroupSecurity); + var forumCreated = fc.GetById(forumId: forumId, moduleId: this.ForumModuleId); + return this.Request.CreateResponse(HttpStatusCode.Created, forumCreated); + } + } + catch (Exception ex) + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(ex); + } + + return this.Request.CreateResponse(HttpStatusCode.BadRequest); + } + + /// + /// Updates an existing forum. + /// + /// ForumInfo + /// updated forum + [HttpPut] + [DnnAuthorize] + [ValidateAntiForgeryToken] + [ForumsAuthorize(SecureActions.Ban)] + public HttpResponseMessage Update([FromBody] DotNetNuke.Modules.ActiveForums.Entities.ForumInfo forum) + { + try + { + if (forum != null && forum.ForumID > 0) + { + var fc = new DotNetNuke.Modules.ActiveForums.Controllers.ForumController(); + var forumId = fc.Forums_Save(portalId: this.ActiveModule.PortalID, forumInfo: forum, isNew: false, useGroupFeatures: forum.InheritSettings, useGroupSecurity: forum.InheritSecurity); + var forumUpdated = fc.GetById(forumId: forum.ForumID, moduleId: this.ForumModuleId); + return this.Request.CreateResponse(HttpStatusCode.Created, forumUpdated); + } + } + catch (Exception ex) + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(ex); + } + + return this.Request.CreateResponse(HttpStatusCode.BadRequest); + } + + /// + /// Updates an existing forum. + /// + /// ForumInfo + /// + /// + /// Success status + [HttpPut] + [DnnAuthorize] + [ValidateAntiForgeryToken] + [ForumsAuthorize(SecureActions.Ban)] + public HttpResponseMessage Update([FromBody] DotNetNuke.Modules.ActiveForums.Entities.ForumInfo forum, bool useGroupFeatures, bool useGroupSecurity) + { + try + { + if (forum != null && forum.ForumID > 0) + { + var fc = new DotNetNuke.Modules.ActiveForums.Controllers.ForumController(); + var forumId = fc.Forums_Save(portalId: this.ActiveModule.PortalID, forumInfo: forum, isNew: false, useGroupFeatures: useGroupFeatures, useGroupSecurity: useGroupSecurity); + var forumUpdated = fc.GetById(forumId: forum.ForumID, moduleId: this.ForumModuleId); + return this.Request.CreateResponse(HttpStatusCode.Created, forumUpdated); + } + } + catch (Exception ex) + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(ex); + } + + return this.Request.CreateResponse(HttpStatusCode.BadRequest); + } + + /// + /// Deletes a forum by ID. + /// + /// Forum ID + /// Success status + [HttpDelete] + [DnnAuthorize] + [ValidateAntiForgeryToken] + [ForumsAuthorize(SecureActions.Ban)] + public HttpResponseMessage Delete(int forumId) + { + try + { + if (forumId > 0) + { + var fc = new DotNetNuke.Modules.ActiveForums.Controllers.ForumController(); + var forum = fc.GetById(forumId: forumId, moduleId: this.ForumModuleId); + if (forum != null) + { + fc.Forums_Delete(forumId: forumId, moduleId: this.ForumModuleId); + return this.Request.CreateResponse(HttpStatusCode.OK, true); + } + + return this.Request.CreateResponse(HttpStatusCode.NotFound); + } + } + catch (Exception ex) + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(ex); + } + + return this.Request.CreateResponse(HttpStatusCode.BadRequest); + } + + /// + /// Lists all forums for the current module. + /// + [HttpGet] + [DnnAuthorize] + [ForumsAuthorize(SecureActions.Ban)] + public HttpResponseMessage List() + { + try + { + var forums = new List(); + new DotNetNuke.Modules.ActiveForums.Controllers.ForumController().GetForums(moduleId: this.ForumModuleId).ForEach(f => forums.Add(new DotNetNuke.Modules.ActiveForums.ViewModels.Forum(f))); + return this.Request.CreateResponse(HttpStatusCode.OK, forums); + } + catch (Exception ex) + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(ex); + return this.Request.CreateResponse(HttpStatusCode.InternalServerError); + } + } + + /// + /// Lists moderators for a forum. + /// + [HttpGet] + [DnnAuthorize] + [ForumsAuthorize(SecureActions.Ban)] + public HttpResponseMessage Moderators(int forumId) + { + try + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(new NotImplementedException("Forum moderators retrieval not implemented yet.")); + return this.Request.CreateResponse(HttpStatusCode.InternalServerError); + } + catch (Exception ex) + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(ex); + return this.Request.CreateResponse(HttpStatusCode.InternalServerError); + } + } + + /// + /// Lists all forums the current user is subscribed to. + /// + [HttpGet] + [DnnAuthorize] + [ForumsAuthorize(SecureActions.Ban)] + public HttpResponseMessage Subscriptions(int userId) + { + try + { + if (userId > 0) + { + var subscriptions = new DotNetNuke.Modules.ActiveForums.Controllers.SubscriptionController().SubscribedForums(portalId: this.ActiveModule.PortalID, moduleId: this.ForumModuleId, userId: userId); + return this.Request.CreateResponse(HttpStatusCode.OK, subscriptions); + } + + return this.Request.CreateResponse(HttpStatusCode.BadRequest); + } + catch (Exception ex) + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(ex); + return this.Request.CreateResponse(HttpStatusCode.InternalServerError); + } + } + + /// + /// Gets forum settings. + /// + [HttpGet] + [DnnAuthorize] + [ForumsAuthorize(SecureActions.Ban)] + public HttpResponseMessage Settings(int forumId) + { + try + { + if (forumId > 0) + { + var forum = new DotNetNuke.Modules.ActiveForums.Controllers.ForumController().GetById(forumId: forumId, moduleId: this.ForumModuleId); + if (forum != null) + { + return this.Request.CreateResponse(HttpStatusCode.OK, forum.FeatureSettings); + } + + return this.Request.CreateResponse(HttpStatusCode.NotFound); + } + + return this.Request.CreateResponse(HttpStatusCode.BadRequest); + } + catch (Exception ex) + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(ex); + return this.Request.CreateResponse(HttpStatusCode.InternalServerError); + } + } + + /// + /// Gets forum security. + /// + [HttpGet] + [DnnAuthorize] + [ForumsAuthorize(SecureActions.Ban)] + public HttpResponseMessage Security(int forumId) + { + try + { + if (forumId > 0) + { + var forum = new DotNetNuke.Modules.ActiveForums.Controllers.ForumController().GetById(forumId: forumId, moduleId: this.ForumModuleId); + if (forum != null) + { + return this.Request.CreateResponse(HttpStatusCode.OK, forum.Security); + } + + return this.Request.CreateResponse(HttpStatusCode.NotFound); + } + + return this.Request.CreateResponse(HttpStatusCode.BadRequest); + } + catch (Exception ex) + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(ex); + return this.Request.CreateResponse(HttpStatusCode.InternalServerError); + } + } } } diff --git a/Dnn.CommunityForums/Services/Controllers/ForumGroupController.cs b/Dnn.CommunityForums/Services/Controllers/ForumGroupController.cs new file mode 100644 index 000000000..d9b58db58 --- /dev/null +++ b/Dnn.CommunityForums/Services/Controllers/ForumGroupController.cs @@ -0,0 +1,310 @@ +// Copyright (c) by DNN Community +// +// DNN Community licenses this file to you under the MIT license. +// +// See the LICENSE file in the project root for more information. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +namespace DotNetNuke.Modules.ActiveForums.Services.Controllers +{ + using System; + using System.Net; + using System.Net.Http; + using System.Web.Http; + + using DotNetNuke.Web.Api; + + /// + /// + /// + public class ForumGroupController : ControllerBase + { + public struct ForumGroupDto + { + public int ForumGroupId { get; set; } + } + + /// + /// Gets a ForumGroup by ID. + /// + /// ForumGroup ID + /// ForumGroupInfo + /// https://dnndev.me/API/ActiveForums/ForumGroup/Get?ForumGroupId=x + [HttpGet] + [DnnAuthorize] + [ForumsAuthorize(SecureActions.Ban)] + public HttpResponseMessage Get(int ForumGroupId) + { + try + { + if (ForumGroupId > 0) + { + var forumGroup = new DotNetNuke.Modules.ActiveForums.Controllers.ForumGroupController().GetById(ForumGroupId, this.ForumModuleId); + if (forumGroup != null) + { + return this.Request.CreateResponse(HttpStatusCode.OK, forumGroup); + } + + return this.Request.CreateResponse(HttpStatusCode.NotFound); + } + } + catch (Exception ex) + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(ex); + } + + return this.Request.CreateResponse(HttpStatusCode.BadRequest); + } + + /// + /// Creates a new ForumGroup. + /// + /// ForumGroupInfo + /// Created ForumGroup + [HttpPost] + [DnnAuthorize] + [ValidateAntiForgeryToken] + [ForumsAuthorize(SecureActions.Ban)] + public HttpResponseMessage Create([FromBody] DotNetNuke.Modules.ActiveForums.Entities.ForumGroupInfo forumGroup) + { + try + { + if (forumGroup != null) + { + var fgc = new DotNetNuke.Modules.ActiveForums.Controllers.ForumGroupController(); + forumGroup.ForumGroupId = DotNetNuke.Common.Utilities.Null.NullInteger; + forumGroup.ModuleId = this.ForumModuleId; + var forumGroupId = fgc.Groups_Save(portalId: this.ActiveModule.PortalID, forumGroupInfo: forumGroup, isNew: true, useDefaultFeatures: true, useDefaultSecurity: true); + var forumGroupCreated = fgc.GetById(forumGroupId, this.ForumModuleId); + return this.Request.CreateResponse(HttpStatusCode.Created, forumGroupCreated); + } + } + catch (Exception ex) + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(ex); + } + + return this.Request.CreateResponse(HttpStatusCode.BadRequest); + } + + /// + /// Creates a new ForumGroup. + /// + /// ForumGroupInfo + /// + /// + /// Created ForumGroup + [HttpPost] + [DnnAuthorize] + [ValidateAntiForgeryToken] + [ForumsAuthorize(SecureActions.Ban)] + public HttpResponseMessage Create([FromBody] DotNetNuke.Modules.ActiveForums.Entities.ForumGroupInfo forumGroup, bool useDefaultFeatures, bool useDefaultSecurity) + { + try + { + if (forumGroup != null) + { + var fgc = new DotNetNuke.Modules.ActiveForums.Controllers.ForumGroupController(); + forumGroup.ForumGroupId = DotNetNuke.Common.Utilities.Null.NullInteger; + forumGroup.ModuleId = this.ForumModuleId; + var forumGroupId = fgc.Groups_Save(portalId: this.ActiveModule.PortalID, forumGroupInfo: forumGroup, isNew: true, useDefaultFeatures: useDefaultFeatures, useDefaultSecurity: useDefaultSecurity); + var forumGroupCreated = fgc.GetById(forumGroupId, this.ForumModuleId); + return this.Request.CreateResponse(HttpStatusCode.Created, forumGroupCreated); + } + } + catch (Exception ex) + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(ex); + } + + return this.Request.CreateResponse(HttpStatusCode.BadRequest); + } + + /// + /// Updates an existing ForumGroup. + /// + /// ForumGroupInfo + /// updated ForumGroup + [HttpPut] + [DnnAuthorize] + [ValidateAntiForgeryToken] + [ForumsAuthorize(SecureActions.Ban)] + public HttpResponseMessage Update([FromBody] DotNetNuke.Modules.ActiveForums.Entities.ForumGroupInfo forumGroup) + { + try + { + if (forumGroup != null && forumGroup.ForumGroupId > 0) + { + var fgc = new DotNetNuke.Modules.ActiveForums.Controllers.ForumGroupController(); + var forumGroupId = fgc.Groups_Save(portalId: this.ActiveModule.PortalID, forumGroupInfo: forumGroup, isNew: false, useDefaultFeatures: forumGroup.InheritSettings, useDefaultSecurity: forumGroup.InheritSecurity); + var forumGroupUpdated = fgc.GetById(forumGroup.ForumGroupId, this.ForumModuleId); + return this.Request.CreateResponse(HttpStatusCode.Created, forumGroupUpdated); + } + } + catch (Exception ex) + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(ex); + } + + return this.Request.CreateResponse(HttpStatusCode.BadRequest); + } + + /// + /// Updates an existing ForumGroup. + /// + /// ForumGroupInfo + /// + /// + /// Success status + [HttpPut] + [DnnAuthorize] + [ValidateAntiForgeryToken] + [ForumsAuthorize(SecureActions.Ban)] + public HttpResponseMessage Update([FromBody] DotNetNuke.Modules.ActiveForums.Entities.ForumGroupInfo forumGroup, bool useDefaultFeatures, bool useDefaultSecurity) + { + try + { + if (forumGroup != null && forumGroup.ForumGroupId > 0) + { + var fgc = new DotNetNuke.Modules.ActiveForums.Controllers.ForumGroupController(); + var forumGroupId = fgc.Groups_Save(portalId: this.ActiveModule.PortalID, forumGroupInfo: forumGroup, isNew: false, useDefaultFeatures: useDefaultFeatures, useDefaultSecurity: useDefaultSecurity); + var forumGroupUpdated = fgc.GetById(forumGroupId: forumGroup.ForumGroupId, moduleId: this.ForumModuleId); + return this.Request.CreateResponse(HttpStatusCode.Created, forumGroupUpdated); + } + } + catch (Exception ex) + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(ex); + } + + return this.Request.CreateResponse(HttpStatusCode.BadRequest); + } + + /// + /// Deletes a ForumGroup by ID. + /// + /// ForumGroup ID + /// Success status + [HttpDelete] + [DnnAuthorize] + [ValidateAntiForgeryToken] + [ForumsAuthorize(SecureActions.Ban)] + public HttpResponseMessage Delete(int forumGroupId) + { + try + { + if (forumGroupId > 0) + { + var fgc = new DotNetNuke.Modules.ActiveForums.Controllers.ForumGroupController(); + var forumGroup = fgc.GetById(forumGroupId: forumGroupId, moduleId: this.ForumModuleId); + if (forumGroup != null) + { + fgc.Groups_Delete(moduleId: this.ForumModuleId, forumGroupId: forumGroupId); + return this.Request.CreateResponse(HttpStatusCode.OK, true); + } + + return this.Request.CreateResponse(HttpStatusCode.NotFound); + } + } + catch (Exception ex) + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(ex); + } + + return this.Request.CreateResponse(HttpStatusCode.BadRequest); + } + + /// + /// Lists all ForumGroups for the current module. + /// + [HttpGet] + [DnnAuthorize] + [ForumsAuthorize(SecureActions.Ban)] + public HttpResponseMessage List() + { + try + { + var forumGroups = new DotNetNuke.Modules.ActiveForums.Controllers.ForumGroupController().Get(scopeValue: this.ForumModuleId); + return this.Request.CreateResponse(HttpStatusCode.OK, forumGroups); + } + catch (Exception ex) + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(ex); + return this.Request.CreateResponse(HttpStatusCode.InternalServerError); + } + } + + /// + /// Gets ForumGroup settings. + /// + [HttpGet] + [DnnAuthorize] + [ForumsAuthorize(SecureActions.Ban)] + public HttpResponseMessage Settings(int ForumGroupId) + { + try + { + if (ForumGroupId > 0) + { + var forumGroup = new DotNetNuke.Modules.ActiveForums.Controllers.ForumGroupController().GetById(forumGroupId: ForumGroupId, moduleId: this.ForumModuleId); + if (forumGroup != null) + { + return this.Request.CreateResponse(HttpStatusCode.OK, forumGroup.FeatureSettings); + } + + return this.Request.CreateResponse(HttpStatusCode.NotFound); + } + + return this.Request.CreateResponse(HttpStatusCode.BadRequest); + } + catch (Exception ex) + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(ex); + return this.Request.CreateResponse(HttpStatusCode.InternalServerError); + } + } + + /// + /// Gets ForumGroup security. + /// + [HttpGet] + [DnnAuthorize] + [ForumsAuthorize(SecureActions.Ban)] + public HttpResponseMessage Security(int ForumGroupId) + { + try + { + if (ForumGroupId > 0) + { + var forumGroup = new DotNetNuke.Modules.ActiveForums.Controllers.ForumGroupController().GetById(forumGroupId: ForumGroupId, moduleId: this.ForumModuleId); + if (forumGroup != null) + { + return this.Request.CreateResponse(HttpStatusCode.OK, forumGroup.Security); + } + + return this.Request.CreateResponse(HttpStatusCode.NotFound); + } + + return this.Request.CreateResponse(HttpStatusCode.BadRequest); + } + catch (Exception ex) + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(ex); + return this.Request.CreateResponse(HttpStatusCode.InternalServerError); + } + } + } +} diff --git a/Dnn.CommunityForums/Services/Controllers/UserController.cs b/Dnn.CommunityForums/Services/Controllers/UserController.cs index 248ab92ed..b011b28a4 100644 --- a/Dnn.CommunityForums/Services/Controllers/UserController.cs +++ b/Dnn.CommunityForums/Services/Controllers/UserController.cs @@ -31,6 +31,7 @@ namespace DotNetNuke.Modules.ActiveForums.Services.Controllers /// /// /// + /// public class UserController : ControllerBase { /// diff --git a/Dnn.CommunityForums/Services/Tokens/TokenReplacer.cs b/Dnn.CommunityForums/Services/Tokens/TokenReplacer.cs index 455891e9e..3e5149efc 100644 --- a/Dnn.CommunityForums/Services/Tokens/TokenReplacer.cs +++ b/Dnn.CommunityForums/Services/Tokens/TokenReplacer.cs @@ -362,7 +362,7 @@ internal static StringBuilder ReplaceForumControlTokens(StringBuilder template, return template; } - internal static StringBuilder ReplaceForumTokens(StringBuilder template, ForumInfo forum, PortalSettings portalSettings, SettingsInfo mainSettings, INavigationManager navigationManager, ForumUserInfo forumUser, int tabId, CurrentUserTypes currentUserType, Uri requestUri, string rawUrl) + internal static StringBuilder ReplaceForumTokens(StringBuilder template, ForumInfo forum, PortalSettings portalSettings, DotNetNuke.Modules.ActiveForums.ModuleSettings moduleSettings, INavigationManager navigationManager, ForumUserInfo forumUser, int tabId, CurrentUserTypes currentUserType, Uri requestUri, string rawUrl) { /* if no last post or subject missing, remove associated last topic tokens */ if (forum.LastPostID == 0 || string.IsNullOrEmpty(System.Net.WebUtility.HtmlDecode(forum.LastPostSubject))) @@ -379,7 +379,7 @@ internal static StringBuilder ReplaceForumTokens(StringBuilder template, ForumIn if (template.ToString().Contains("[AF:CONTROL:ADDFAVORITE]")) { var forumUrl = new ControlUtils().BuildUrl(forum.PortalId, tabId, forum.ModuleId, forum.ForumGroup.PrefixURL, forum.PrefixURL, forum.ForumGroupId, forum.ForumID, -1, -1, string.Empty, 1, -1, forum.SocialGroupId); - template.Replace("[AF:CONTROL:ADDFAVORITE]", "\"[RESX:AddToFavorites]\""); + template.Replace("[AF:CONTROL:ADDFAVORITE]", "\"[RESX:AddToFavorites]\""); } template = ResourceStringTokenReplacer.ReplaceResourceTokens(template); @@ -389,7 +389,7 @@ internal static StringBuilder ReplaceForumTokens(StringBuilder template, ForumIn return template; } - internal static StringBuilder ReplaceForumGroupTokens(StringBuilder template, ForumGroupInfo forumGroup, PortalSettings portalSettings, SettingsInfo mainSettings, INavigationManager navigationManager, ForumUserInfo forumUser, int tabId, CurrentUserTypes currentUserType, Uri requestUri, string rawUrl) + internal static StringBuilder ReplaceForumGroupTokens(StringBuilder template, ForumGroupInfo forumGroup, PortalSettings portalSettings, DotNetNuke.Modules.ActiveForums.ModuleSettings moduleSettings, INavigationManager navigationManager, ForumUserInfo forumUser, int tabId, CurrentUserTypes currentUserType, Uri requestUri, string rawUrl) { template = ResourceStringTokenReplacer.ReplaceResourceTokens(template); var tokenReplacer = new TokenReplacer(portalSettings, forumUser, forumGroup, requestUri, rawUrl) { CurrentAccessLevel = Scope.DefaultSettings, AccessingUser = forumUser.UserInfo, }; @@ -399,7 +399,7 @@ internal static StringBuilder ReplaceForumGroupTokens(StringBuilder template, Fo return template; } - internal static StringBuilder ReplaceAuthorTokens(StringBuilder template, PortalSettings portalSettings, SettingsInfo mainSettings, AuthorInfo author, ForumUserInfo accessingUser, Uri requestUri, string rawUrl, int forumModuleId) + internal static StringBuilder ReplaceAuthorTokens(StringBuilder template, PortalSettings portalSettings, DotNetNuke.Modules.ActiveForums.ModuleSettings moduleSettings, AuthorInfo author, ForumUserInfo accessingUser, Uri requestUri, string rawUrl, int forumModuleId) { template = ResourceStringTokenReplacer.ReplaceResourceTokens(template); var tokenReplacer = new TokenReplacer(portalSettings, author, accessingUser, requestUri, rawUrl) { CurrentAccessLevel = Scope.DefaultSettings, AccessingUser = accessingUser?.UserInfo, }; @@ -409,7 +409,7 @@ internal static StringBuilder ReplaceAuthorTokens(StringBuilder template, Portal return template; } - internal static StringBuilder ReplaceUserTokens(StringBuilder template, PortalSettings portalSettings, SettingsInfo mainSettings, ForumUserInfo forumUser, ForumUserInfo accessingUser, Uri requestUri, string rawUrl, int forumModuleId) + internal static StringBuilder ReplaceUserTokens(StringBuilder template, PortalSettings portalSettings, DotNetNuke.Modules.ActiveForums.ModuleSettings moduleSettings, ForumUserInfo forumUser, ForumUserInfo accessingUser, Uri requestUri, string rawUrl, int forumModuleId) { var language = accessingUser?.UserInfo?.Profile?.PreferredLocale ?? portalSettings?.DefaultLanguage; @@ -423,9 +423,9 @@ internal static StringBuilder ReplaceUserTokens(StringBuilder template, PortalSe return template; } - internal static StringBuilder ReplaceTopicTokens(StringBuilder template, TopicInfo topic, PortalSettings portalSettings, SettingsInfo mainSettings, INavigationManager navigationManager, ForumUserInfo forumUser, Uri requestUri, string rawUrl) + internal static StringBuilder ReplaceTopicTokens(StringBuilder template, TopicInfo topic, PortalSettings portalSettings, DotNetNuke.Modules.ActiveForums.ModuleSettings moduleSettings, INavigationManager navigationManager, ForumUserInfo forumUser, Uri requestUri, string rawUrl) { - topic.Content.Body = ReplaceBody(topic.Content.Body, mainSettings, requestUri); + topic.Content.Body = ReplaceBody(topic.Content.Body, moduleSettings, requestUri); template = ResourceStringTokenReplacer.ReplaceResourceTokens(template); var tokenReplacer = new TokenReplacer(portalSettings, forumUser, topic, requestUri, rawUrl) { AccessingUser = forumUser.UserInfo, }; @@ -435,7 +435,7 @@ internal static StringBuilder ReplaceTopicTokens(StringBuilder template, TopicIn return template; } - private static string ReplaceBody(string body, SettingsInfo mainSettings, Uri uri) + private static string ReplaceBody(string body, DotNetNuke.Modules.ActiveForums.ModuleSettings moduleSettings, Uri uri) { if (!string.IsNullOrEmpty(body)) { @@ -453,7 +453,7 @@ private static string ReplaceBody(string body, SettingsInfo mainSettings, Uri ur } body = Utilities.StripExecCode(body); - if (mainSettings.AutoLinkEnabled) + if (moduleSettings.AutoLinkEnabled) { body = Utilities.AutoLinks(body, uri.Host); } @@ -472,7 +472,7 @@ private static string ReplaceBody(string body, SettingsInfo mainSettings, Uri ur return body; } - internal static StringBuilder ReplacePostTokens(StringBuilder template, IPostInfo post, PortalSettings portalSettings, SettingsInfo mainSettings, INavigationManager navigationManager, ForumUserInfo forumUser, Uri requestUri, string rawUrl) + internal static StringBuilder ReplacePostTokens(StringBuilder template, IPostInfo post, PortalSettings portalSettings, DotNetNuke.Modules.ActiveForums.ModuleSettings moduleSettings, INavigationManager navigationManager, ForumUserInfo forumUser, Uri requestUri, string rawUrl) { /* if likes not allowed for forum, remove like-related tokens */ if (!post.Forum.FeatureSettings.AllowLikes) @@ -490,7 +490,7 @@ internal static StringBuilder ReplacePostTokens(StringBuilder template, IPostInf template.Replace("[POSTINFO]", sPostInfo); } - post.Content.Body = ReplaceBody(post.Content.Body, mainSettings, requestUri); + post.Content.Body = ReplaceBody(post.Content.Body, moduleSettings, requestUri); template = ResourceStringTokenReplacer.ReplaceResourceTokens(template); var tokenReplacer = new TokenReplacer(portalSettings, forumUser, post, requestUri, rawUrl) { AccessingUser = forumUser.UserInfo, }; @@ -500,7 +500,7 @@ internal static StringBuilder ReplacePostTokens(StringBuilder template, IPostInf return template; } - internal static StringBuilder ReplaceLikeTokens(StringBuilder template, LikeInfo like, PortalSettings portalSettings, SettingsInfo mainSettings, INavigationManager navigationManager, ForumUserInfo forumUser, Uri requestUri, string rawUrl) + internal static StringBuilder ReplaceLikeTokens(StringBuilder template, LikeInfo like, PortalSettings portalSettings, DotNetNuke.Modules.ActiveForums.ModuleSettings moduleSettings, INavigationManager navigationManager, ForumUserInfo forumUser, Uri requestUri, string rawUrl) { /* if likes not allowed for forum, remove like-related tokens */ if (!like.Forum.FeatureSettings.AllowLikes) @@ -781,7 +781,7 @@ internal static StringBuilder MapLegacyForumGroupTokenSynonyms(StringBuilder tem return template; } - internal static StringBuilder MapLegacyUserTokenSynonyms(StringBuilder template, PortalSettings portalSettings, SettingsInfo mainSettings, string language) + internal static StringBuilder MapLegacyUserTokenSynonyms(StringBuilder template, PortalSettings portalSettings, DotNetNuke.Modules.ActiveForums.ModuleSettings moduleSettings, string language) { template = ReplaceTokenSynonym(template, "[SENDERUSERNAME]", "[USER:USERNAME]"); template = ReplaceTokenSynonym(template, "[SENDERFIRSTNAME]", "[USER:FIRSTNAME]"); @@ -851,12 +851,12 @@ internal static StringBuilder MapLegacyUserTokenSynonyms(StringBuilder template, template = ReplaceLegacyTokenWithFormatString(template, portalSettings, language, "[AF:BUTTON:EDITUSER]", "[FORUMUSER:EDITLINK", "[EDITUSERLINK]"); - if (mainSettings.PMType == PMTypes.Disabled) + if (moduleSettings.PMType == PMTypes.Disabled) { template.Replace("[AF:PROFILE:PMLINK]", string.Empty); template.Replace("[AF:PROFILE:PMURL]", string.Empty); } - else if (mainSettings.PMType == PMTypes.Core) + else if (moduleSettings.PMType == PMTypes.Core) { template = ReplaceLegacyTokenWithFormatString(template, portalSettings, language, "[AF:PROFILE:PMLINK]", "[FORUMUSER:PMLINK", "[USERPMLINK]"); template.Replace("[AF:PROFILE:PMURL]", string.Empty); @@ -865,7 +865,7 @@ internal static StringBuilder MapLegacyUserTokenSynonyms(StringBuilder template, return template; } - internal static StringBuilder MapLegacyAuthorTokenSynonyms(StringBuilder template, PortalSettings portalSettings, SettingsInfo mainSettings, string language) + internal static StringBuilder MapLegacyAuthorTokenSynonyms(StringBuilder template, PortalSettings portalSettings, DotNetNuke.Modules.ActiveForums.ModuleSettings moduleSettings, string language) { template = ReplaceTokenSynonym(template, "[SENDERUSERNAME]", "[FORUMAUTHOR:USERNAME]"); template = ReplaceTokenSynonym(template, "[SENDERFIRSTNAME]", "[FORUMAUTHOR:FIRSTNAME]"); @@ -935,12 +935,12 @@ internal static StringBuilder MapLegacyAuthorTokenSynonyms(StringBuilder templat template = ReplaceLegacyTokenWithFormatString(template, portalSettings, language, "[AF:BUTTON:EDITUSER]", "[FORUMAUTHOR:EDITLINK", "[EDITAUTHORLINK]"); - if (mainSettings.PMType == PMTypes.Disabled) + if (moduleSettings.PMType == PMTypes.Disabled) { template.Replace("[AF:PROFILE:PMLINK]", string.Empty); template.Replace("[AF:PROFILE:PMURL]", string.Empty); } - else if (mainSettings.PMType == PMTypes.Core) + else if (moduleSettings.PMType == PMTypes.Core) { template = ReplaceLegacyTokenWithFormatString(template, portalSettings, language, "[AF:PROFILE:PMLINK]", "[FORUMAUTHOR:PMLINK", "[AUTHORPMLINK]"); template.Replace("[AF:PROFILE:PMURL]", string.Empty); diff --git a/Dnn.CommunityForums/class/ActiveAdminBase.cs b/Dnn.CommunityForums/class/ActiveAdminBase.cs index ed67882fc..34f78a734 100644 --- a/Dnn.CommunityForums/class/ActiveAdminBase.cs +++ b/Dnn.CommunityForums/class/ActiveAdminBase.cs @@ -73,11 +73,11 @@ protected string GetSharedResource(string key) return Utilities.GetSharedResource(key, true); } - public SettingsInfo MainSettings + public ModuleSettings MainSettings { get { - return new SettingsInfo { ModuleId = this.ModuleId, MainSettings = new ModuleController().GetModule(moduleID: this.ModuleId).ModuleSettings }; + return new ModuleSettings { ModuleId = this.ModuleId, MainSettings = new ModuleController().GetModule(moduleID: this.ModuleId).ModuleSettings }; } } diff --git a/Dnn.CommunityForums/class/Cache.cs b/Dnn.CommunityForums/class/Cache.cs index 86533faba..8d8370cee 100644 --- a/Dnn.CommunityForums/class/Cache.cs +++ b/Dnn.CommunityForums/class/Cache.cs @@ -366,42 +366,16 @@ internal static Hashtable GetSettings(int moduleId, string settingsKey, string c var ht = new Hashtable(); if (useCache) { - object obj = SettingsCacheRetrieve(moduleId, cacheKey); - if (obj == null) + ht = (Hashtable)SettingsCacheRetrieve(moduleId, cacheKey); + if (ht == null) { - IDataReader dr = DataProvider.Instance().Settings_List(moduleId, settingsKey); - while (dr.Read()) - { - if (!ht.ContainsKey(dr["SettingName"].ToString())) - { - ht.Add(dr["SettingName"].ToString(), string.Empty); - } - - ht[dr["SettingName"].ToString()] = dr["SettingValue"].ToString(); - } - - dr.Close(); + ht = new DotNetNuke.Modules.ActiveForums.Controllers.SettingsController().GetSettingsHashTableForModuleIdSettingsKey(moduleId, settingsKey); SettingsCacheStore(moduleId, cacheKey, ht); } - else - { - ht = (Hashtable)obj; - } } else { - IDataReader dr = DataProvider.Instance().Settings_List(moduleId, settingsKey); - while (dr.Read()) - { - if (!ht.ContainsKey(dr["SettingName"].ToString())) - { - ht.Add(dr["SettingName"].ToString(), string.Empty); - } - - ht[dr["SettingName"].ToString()] = dr["SettingValue"].ToString(); - } - - dr.Close(); + ht = new DotNetNuke.Modules.ActiveForums.Controllers.SettingsController().GetSettingsHashTableForModuleIdSettingsKey(moduleId, settingsKey); } return ht; diff --git a/Dnn.CommunityForums/class/DataProvider.cs b/Dnn.CommunityForums/class/DataProvider.cs index 6917411e1..f26d67ff0 100644 --- a/Dnn.CommunityForums/class/DataProvider.cs +++ b/Dnn.CommunityForums/class/DataProvider.cs @@ -210,14 +210,19 @@ private static void CreateProvider() #endregion #region Settings + [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. No Longer Used.")] public abstract IDataReader Settings_List(int moduleId, string groupKey); + [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. No Longer Used.")] public abstract IDataReader Settings_ListAll(int moduleId); + [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. No Longer Used.")] public abstract string Settings_Get(int moduleId, string groupKey, string settingName); + [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. No Longer Used.")] public abstract void Settings_Delete(int moduleId, string groupKey, string settingName); + [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. No Longer Used.")] public abstract void Settings_Save(int moduleId, string groupKey, string settingName, string settingValue); #endregion diff --git a/Dnn.CommunityForums/class/ForumBase.cs b/Dnn.CommunityForums/class/ForumBase.cs index ca03831fa..13b598c61 100644 --- a/Dnn.CommunityForums/class/ForumBase.cs +++ b/Dnn.CommunityForums/class/ForumBase.cs @@ -56,7 +56,7 @@ public XmlDocument ForumData public ControlsConfig ControlConfig { get; set; } - public string ThemePath => this.Page.ResolveUrl(this.MainSettings.ThemeLocation); + public string ThemePath => this.Page.ResolveUrl(this.ModuleSettings.ThemeLocation); public string ForumIds { get; set; } = string.Empty; diff --git a/Dnn.CommunityForums/class/ForumsConfig.cs b/Dnn.CommunityForums/class/ForumsConfig.cs index 4fb5a0056..c9216192b 100644 --- a/Dnn.CommunityForums/class/ForumsConfig.cs +++ b/Dnn.CommunityForums/class/ForumsConfig.cs @@ -565,7 +565,7 @@ internal static void Upgrade_EmailNotificationSubjectTokens_080200() } templateInfo.Subject = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyEmailNotificationTokenSynonyms(new StringBuilder(templateInfo.Subject), portalSettings, portalSettings.DefaultLanguage).ToString(); - Settings.SaveSetting(module.ModuleID, $"M:{module.ModuleID}", ForumSettingKeys.EmailNotificationSubjectTemplate, templateInfo.Subject); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(module.ModuleID, $"M:{module.ModuleID}", ForumSettingKeys.EmailNotificationSubjectTemplate, templateInfo.Subject); DotNetNuke.Modules.ActiveForums.DataCache.ClearAllCache(module.ModuleID); } catch (Exception ex) @@ -664,47 +664,47 @@ internal static void Install_Upgrade_ForumDefaultSettingsAndSecurity(int portalI string sKey = $"M:{moduleId}"; DotNetNuke.Entities.Modules.ModuleController.Instance.UpdateModuleSetting(moduleId, SettingKeys.DefaultSettingsKey, sKey); - if (string.IsNullOrEmpty(SettingsBase.GetModuleSettings(moduleId).ForumFeatureSettings.EmailNotificationSubjectTemplate)) + if (string.IsNullOrEmpty(SettingsBase.GetModuleSettings(moduleId).DefaultFeatureSettings.EmailNotificationSubjectTemplate)) { - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.EmailNotificationSubjectTemplate, "[FORUMAUTHOR:DISPLAYNAME] [POSTEDORREPLIEDTO] [SUBSCRIBEDFORUMORTOPICSUBJECTFORUMNAME] on [PORTAL:PORTALNAME]"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.EmailNotificationSubjectTemplate, "[FORUMAUTHOR:DISPLAYNAME] [POSTEDORREPLIEDTO] [SUBSCRIBEDFORUMORTOPICSUBJECTFORUMNAME] on [PORTAL:PORTALNAME]"); } - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.EmailAddress, string.Empty); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.UseFilter, "true"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.AllowPostIcon, "false"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.AllowLikes, "true"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.AllowEmoticons, "false"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.AllowScript, "false"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.IndexContent, "true"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.AllowRSS, "true"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.AllowAttach, "true"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.AttachCount, "3"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.AttachMaxSize, "1000"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.AttachTypeAllowed, "txt,tiff,pdf,xls,xlsx,doc,docx,ppt,pptx"); - - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.AttachMaxHeight, "450"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.AttachMaxWidth, "450"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.AttachAllowBrowseSite, "true"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.MaxAttachHeight, "800"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.MaxAttachWidth, "800"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.AttachInsertAllowed, "false"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.ConvertingToJpegAllowed, "false"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.AllowHTML, "true"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.EditorType, ((int)EditorTypes.HTMLEDITORPROVIDER).ToString()); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.EditorMobile, ((int)EditorTypes.HTMLEDITORPROVIDER).ToString()); - - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.EditorHeight, "350"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.EditorWidth, "99%"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.EditorToolbar, "bold,italic,underline,quote"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.EditorStyle, "2"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.IsModerated, "false"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.DefaultTrustLevel, "0"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.AutoTrustLevel, "0"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.ModApproveNotify, "0"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.ModRejectNotify, "0"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.ModMoveNotify, "0"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.ModDeleteNotify, "0"); - Settings.SaveSetting(moduleId, sKey, ForumSettingKeys.ModAlertNotify, "0"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.EmailAddress, string.Empty); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.UseFilter, "true"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.AllowPostIcon, "false"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.AllowLikes, "true"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.AllowEmoticons, "false"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.AllowScript, "false"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.IndexContent, "true"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.AllowRSS, "true"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.AllowAttach, "true"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.AttachCount, "3"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.AttachMaxSize, "1000"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.AttachTypeAllowed, "txt,tiff,pdf,xls,xlsx,doc,docx,ppt,pptx"); + + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.AttachMaxHeight, "450"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.AttachMaxWidth, "450"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.AttachAllowBrowseSite, "true"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.MaxAttachHeight, "800"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.MaxAttachWidth, "800"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.AttachInsertAllowed, "false"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.ConvertingToJpegAllowed, "false"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.AllowHTML, "true"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.EditorType, ((int)EditorTypes.HTMLEDITORPROVIDER).ToString()); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.EditorMobile, ((int)EditorTypes.HTMLEDITORPROVIDER).ToString()); + + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.EditorHeight, "350"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.EditorWidth, "99%"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.EditorToolbar, "bold,italic,underline,quote"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.EditorStyle, "2"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.IsModerated, "false"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.DefaultTrustLevel, "0"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.AutoTrustLevel, "0"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.ModApproveNotify, "0"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.ModRejectNotify, "0"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.ModMoveNotify, "0"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.ModDeleteNotify, "0"); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(moduleId, sKey, ForumSettingKeys.ModAlertNotify, "0"); DotNetNuke.Modules.ActiveForums.DataCache.ClearAllCache(moduleId); } diff --git a/Dnn.CommunityForums/class/ModuleSettings.cs b/Dnn.CommunityForums/class/ModuleSettings.cs new file mode 100644 index 000000000..99f801d17 --- /dev/null +++ b/Dnn.CommunityForums/class/ModuleSettings.cs @@ -0,0 +1,209 @@ +// Copyright (c) by DNN Community +// +// DNN Community licenses this file to you under the MIT license. +// +// See the LICENSE file in the project root for more information. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +namespace DotNetNuke.Modules.ActiveForums +{ + using System; + using System.Collections; + using System.Reflection; + + using DotNetNuke.Modules.ActiveForums.Entities; + + public class ModuleSettings + { + private DotNetNuke.Modules.ActiveForums.Entities.FeatureSettings defaultFeatureSettings; + + public int ModuleId { get; set; } + + public Hashtable MainSettings { get; set; } + + public ModuleSettings() + { + this.MainSettings = new Hashtable(); + } + + public ModuleSettings(int moduleId) + { + this.MainSettings = new Hashtable(); + this.ModuleId = moduleId; + } + + public int PageSize => this.MainSettings.GetInt(SettingKeys.PageSize, 20); + + public string UserNameDisplay => this.MainSettings.GetString(SettingKeys.UserNameDisplay, "USERNAME"); + + public bool EnablePoints => this.MainSettings.GetBoolean(SettingKeys.EnablePoints); + + public int TopicPointValue => this.MainSettings.GetInt(SettingKeys.TopicPointValue, 1); + + public int ReplyPointValue => this.MainSettings.GetInt(SettingKeys.ReplyPointValue, 1); + + public int AnswerPointValue => this.MainSettings.GetInt(SettingKeys.AnswerPointValue, 1); + + public int MarkAsAnswerPointValue => this.MainSettings.GetInt(SettingKeys.MarkAnswerPointValue, 1); + + public int ModPointValue => this.MainSettings.GetInt(SettingKeys.ModPointValue, 1); + + public int AvatarHeight => this.MainSettings.GetInt(SettingKeys.AvatarHeight, 80); + + public int AvatarWidth => this.MainSettings.GetInt(SettingKeys.AvatarWidth, 80); + + public bool AvatarRefreshEnabled => this.MainSettings.GetString(SettingKeys.AvatarRefresh) == Globals.AvatarRefreshGravatar; + + public string AvatarRefreshType => this.MainSettings.GetString(SettingKeys.AvatarRefresh); + + public int AllowSignatures => this.MainSettings.GetInt(SettingKeys.AllowSignatures); + + public string DateFormatString => this.MainSettings.GetString(SettingKeys.DateFormatString, "M/d/yyyy"); + + public string TimeFormatString => this.MainSettings.GetString(SettingKeys.TimeFormatString, "h:mm tt"); + + [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. Not Used.")] + public int TimeZoneOffset => this.MainSettings.GetInt(SettingKeys.TimeZoneOffset); + + public bool UsersOnlineEnabled => this.MainSettings.GetBoolean(SettingKeys.UsersOnlineEnabled); + + public string MemberListMode => "Enabled"; + + [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. Not Used.")] + public int ForumTemplateID => throw new NotImplementedException(); + + public DateTime InstallDate => Utilities.SafeConvertDateTime(this.MainSettings[SettingKeys.InstallDate], Utilities.NullDate()); + + public bool IsInstalled => this.MainSettings.GetBoolean(SettingKeys.IsInstalled); + + public PMTypes PMType + { + get + { + PMTypes parsedValue; + return Enum.TryParse(this.MainSettings.GetString(SettingKeys.PMType), true, out parsedValue) + ? parsedValue + : PMTypes.Disabled; + } + } + + public int PMTabId => this.MainSettings.GetInt(SettingKeys.PMTabId, -1); + + public bool DisableAccountTab => this.MainSettings.GetBoolean(SettingKeys.DisableAccountTab); + + public string Theme + { + get + { + var result = this.MainSettings.GetString(SettingKeys.Theme); + return string.IsNullOrWhiteSpace(result) ? "_legacy" : result; + } + } + + public string ThemeLocation => string.Concat(Globals.ThemesPath, this.Theme, "/"); + + public string TemplatePath => string.Concat(this.ThemeLocation, "templates/"); + + public bool FullText => this.MainSettings.GetBoolean(SettingKeys.FullText); + + public string AllowSubTypes => this.MainSettings.GetString(SettingKeys.AllowSubTypes, string.Empty); + + [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. Not Used.")] + public bool MailQueue => true; + + public bool CacheTemplates => this.MainSettings.GetBoolean(SettingKeys.CacheTemplates, defaultValue: true); + + public int FloodInterval => this.MainSettings.GetInt(SettingKeys.FloodInterval, 5); + + public int EditInterval => this.MainSettings.GetInt(SettingKeys.EditInterval); + + public DotNetNuke.Modules.ActiveForums.Enums.DeleteBehavior DeleteBehavior + { + get + { + DotNetNuke.Modules.ActiveForums.Enums.DeleteBehavior parsedValue; + + return Enum.TryParse(this.MainSettings.GetString(SettingKeys.DeleteBehavior), true, out parsedValue) + ? parsedValue + : DotNetNuke.Modules.ActiveForums.Enums.DeleteBehavior.Recycle; + } + } + + public ProfileVisibilities ProfileVisibility + { + get + { + ProfileVisibilities parsedValue; + + return Enum.TryParse(this.MainSettings.GetString(SettingKeys.ProfileVisibility), true, + out parsedValue) + ? parsedValue + : ProfileVisibilities.Disabled; + } + } + + public bool UseShortUrls => this.MainSettings.GetBoolean(SettingKeys.UseShortUrls); + + public bool UseSkinBreadCrumb => this.MainSettings.GetBoolean(SettingKeys.UseSkinBreadCrumb); + + public bool AutoLinkEnabled => this.MainSettings.GetBoolean(SettingKeys.EnableAutoLink, true); + + public bool URLRewriteEnabled => this.MainSettings.GetBoolean(SettingKeys.EnableURLRewriter); + + public string PrefixURLBase => this.MainSettings.GetString(SettingKeys.PrefixURLBase, string.Empty); + + public string PrefixURLOther => !this.URLRewriteEnabled + ? string.Empty + : this.MainSettings.GetString(SettingKeys.PrefixURLOther, "other"); + + public string PrefixURLTag => !this.URLRewriteEnabled + ? string.Empty + : this.MainSettings.GetString(SettingKeys.PrefixURLTags, "tag"); + + public string PrefixURLCategory => !this.URLRewriteEnabled + ? string.Empty + : this.MainSettings.GetString(SettingKeys.PrefixURLCategories, "category"); + + public string PrefixURLLikes => !this.URLRewriteEnabled + ? string.Empty + : this.MainSettings.GetString(SettingKeys.PrefixURLLikes, Views.Likes); + + public int DefaultPermissionId => this.MainSettings.GetInt(SettingKeys.DefaultPermissionId); + + public string DefaultSettingsKey => this.MainSettings.GetString(SettingKeys.DefaultSettingsKey) ?? $"M:{this.ModuleId}"; + + public FeatureSettings DefaultFeatureSettings + { + get => this.defaultFeatureSettings ?? (this.defaultFeatureSettings = new DotNetNuke.Modules.ActiveForums.Entities.FeatureSettings(moduleId: this.ModuleId, settingsKey: this.DefaultSettingsKey)); + set => this.defaultFeatureSettings = value; + } + } + + public class SettingsInfo + { + [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. Not Used.")] + public static Hashtable GeneralSettings(int moduleId, string groupKey) => throw new NotImplementedException(); + + [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. Not Used.")] + public static string GetSetting(int moduleId, string groupKey, string settingName) => throw new NotImplementedException(); + + [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. Not Used.")] + public static bool SaveSetting(int moduleId, string settingKey, string settingName, string settingValue) => throw new NotImplementedException(); + + [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. Not Used.")] + public static bool DeleteSetting(int moduleId, string groupKey, string settingName) => throw new NotImplementedException(); + } +} diff --git a/Dnn.CommunityForums/class/Settings.cs b/Dnn.CommunityForums/class/Settings.cs deleted file mode 100644 index 33dc1ff6e..000000000 --- a/Dnn.CommunityForums/class/Settings.cs +++ /dev/null @@ -1,375 +0,0 @@ -// Copyright (c) by DNN Community -// -// DNN Community licenses this file to you under the MIT license. -// -// See the LICENSE file in the project root for more information. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and -// to permit persons to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or substantial portions -// of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF -// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -namespace DotNetNuke.Modules.ActiveForums -{ - using System; - using System.Collections; - - using DotNetNuke.Modules.ActiveForums.Entities; - - #region SettingsInfo - - public class SettingsInfo - { - public int ModuleId { get; set; } - - private DotNetNuke.Modules.ActiveForums.Entities.FeatureSettings featureSettings; - - public Hashtable MainSettings { get; set; } - - public SettingsInfo() - { - this.MainSettings = new Hashtable(); - } - - public SettingsInfo(int moduleId) - { - this.MainSettings = new Hashtable(); - this.ModuleId = moduleId; - } - - public int PageSize - { - get { return this.MainSettings.GetInt(SettingKeys.PageSize, 20); } - } - - public string UserNameDisplay - { - get { return this.MainSettings.GetString(SettingKeys.UserNameDisplay, "USERNAME"); } - } - - public bool EnablePoints - { - get { return this.MainSettings.GetBoolean(SettingKeys.EnablePoints); } - } - - public int TopicPointValue - { - get { return this.MainSettings.GetInt(SettingKeys.TopicPointValue, 1); } - } - - public int ReplyPointValue - { - get { return this.MainSettings.GetInt(SettingKeys.ReplyPointValue, 1); } - } - - public int AnswerPointValue - { - get { return this.MainSettings.GetInt(SettingKeys.AnswerPointValue, 1); } - } - - public int MarkAsAnswerPointValue - { - get { return this.MainSettings.GetInt(SettingKeys.MarkAnswerPointValue, 1); } - } - - public int ModPointValue - { - get { return this.MainSettings.GetInt(SettingKeys.ModPointValue, 1); } - } - - public int AvatarHeight - { - get { return this.MainSettings.GetInt(SettingKeys.AvatarHeight, 80); } - } - - public int AvatarWidth - { - get { return this.MainSettings.GetInt(SettingKeys.AvatarWidth, 80); } - } - - public bool AvatarRefreshEnabled - { - get { return this.MainSettings.GetString(SettingKeys.AvatarRefresh) == Globals.AvatarRefreshGravatar; } - } - - public string AvatarRefreshType - { - get { return this.MainSettings.GetString(SettingKeys.AvatarRefresh); } - } - - public int AllowSignatures - { - get { return this.MainSettings.GetInt(SettingKeys.AllowSignatures); } - } - - public string DateFormatString - { - get { return this.MainSettings.GetString(SettingKeys.DateFormatString, "M/d/yyyy"); } - } - - public string TimeFormatString - { - get { return this.MainSettings.GetString(SettingKeys.TimeFormatString, "h:mm tt"); } - } - - [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. Not Used.")] - public int TimeZoneOffset - { - get { return this.MainSettings.GetInt(SettingKeys.TimeZoneOffset); } - } - - public bool UsersOnlineEnabled - { - get { return this.MainSettings.GetBoolean(SettingKeys.UsersOnlineEnabled); } - } - - public string MemberListMode - { - get - { - return "Enabled"; - } - } - - [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. Not Used.")] - public int ForumTemplateID => throw new NotImplementedException(); - - public DateTime InstallDate - { - get { return Utilities.SafeConvertDateTime(this.MainSettings[SettingKeys.InstallDate], Utilities.NullDate()); } - } - - public bool IsInstalled - { - get { return this.MainSettings.GetBoolean(SettingKeys.IsInstalled); } - } - - public PMTypes PMType - { - get - { - PMTypes parsedValue; - return Enum.TryParse(this.MainSettings.GetString(SettingKeys.PMType), true, out parsedValue) - ? parsedValue - : PMTypes.Disabled; - } - } - - public int PMTabId - { - get { return this.MainSettings.GetInt(SettingKeys.PMTabId, -1); } - } - - public bool DisableAccountTab - { - get { return this.MainSettings.GetBoolean(SettingKeys.DisableAccountTab); } - } - - public string Theme - { - get - { - var result = this.MainSettings.GetString(SettingKeys.Theme); - return string.IsNullOrWhiteSpace(result) ? "_legacy" : result; - } - } - - public string ThemeLocation => string.Concat(Globals.ThemesPath, this.Theme, "/"); - - public string TemplatePath => string.Concat(this.ThemeLocation, "templates/"); - - public bool FullText - { - get { return this.MainSettings.GetBoolean(SettingKeys.FullText); } - } - - public string AllowSubTypes - { - get { return this.MainSettings.GetString(SettingKeys.AllowSubTypes, string.Empty); } - } - - [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. Not Used.")] - public bool MailQueue => true; - - public bool CacheTemplates - { - get { return this.MainSettings.GetBoolean(SettingKeys.CacheTemplates, defaultValue: true); } - } - - public int FloodInterval - { - get { return this.MainSettings.GetInt(SettingKeys.FloodInterval, 5); } - } - - public int EditInterval - { - get { return this.MainSettings.GetInt(SettingKeys.EditInterval); } - } - - public DotNetNuke.Modules.ActiveForums.Enums.DeleteBehavior DeleteBehavior - { - get - { - DotNetNuke.Modules.ActiveForums.Enums.DeleteBehavior parsedValue; - - return Enum.TryParse(this.MainSettings.GetString(SettingKeys.DeleteBehavior), true, out parsedValue) - ? parsedValue - : DotNetNuke.Modules.ActiveForums.Enums.DeleteBehavior.Recycle; - } - } - - public ProfileVisibilities ProfileVisibility - { - get - { - ProfileVisibilities parsedValue; - - return Enum.TryParse(this.MainSettings.GetString(SettingKeys.ProfileVisibility), true, - out parsedValue) - ? parsedValue - : ProfileVisibilities.Disabled; - } - } - - public bool UseShortUrls - { - get { return this.MainSettings.GetBoolean(SettingKeys.UseShortUrls); } - } - - public bool UseSkinBreadCrumb - { - get { return this.MainSettings.GetBoolean(SettingKeys.UseSkinBreadCrumb); } - } - - public bool AutoLinkEnabled - { - get { return this.MainSettings.GetBoolean(SettingKeys.EnableAutoLink, true); } - } - - public bool URLRewriteEnabled - { - get { return this.MainSettings.GetBoolean(SettingKeys.EnableURLRewriter); } - } - - public string PrefixURLBase - { - get { return this.MainSettings.GetString(SettingKeys.PrefixURLBase, string.Empty); } - } - - public string PrefixURLOther - { - get - { - return !this.URLRewriteEnabled - ? string.Empty - : this.MainSettings.GetString(SettingKeys.PrefixURLOther, "other"); - } - } - - public string PrefixURLTag - { - get - { - return !this.URLRewriteEnabled - ? string.Empty - : this.MainSettings.GetString(SettingKeys.PrefixURLTags, "tag"); - } - } - - public string PrefixURLCategory - { - get - { - return !this.URLRewriteEnabled - ? string.Empty - : this.MainSettings.GetString(SettingKeys.PrefixURLCategories, "category"); - } - } - - public string PrefixURLLikes - { - get - { - return !this.URLRewriteEnabled - ? string.Empty - : this.MainSettings.GetString(SettingKeys.PrefixURLLikes, Views.Likes); - } - } - - public int DefaultPermissionId - { - get { return this.MainSettings.GetInt(SettingKeys.DefaultPermissionId); } - } - - public string DefaultSettingsKey - { - get - { - return this.MainSettings.GetString(SettingKeys.DefaultSettingsKey) ?? $"M:{this.ModuleId}"; - } - } - - public FeatureSettings ForumFeatureSettings - { - get => this.featureSettings ?? (this.featureSettings = this.LoadFeatureSettings()); - set => this.featureSettings = value; - } - - internal FeatureSettings LoadFeatureSettings() - { - return new DotNetNuke.Modules.ActiveForums.Entities.FeatureSettings(moduleId: this.ModuleId, settingsKey: this.DefaultSettingsKey); - } - } - - #endregion - - public class Settings - { - public static Hashtable GeneralSettings(int moduleId, string groupKey) - { - var ht = new Hashtable(); - var dr = DataProvider.Instance().Settings_List(moduleId, groupKey); - while (dr.Read()) - { - ht.Add(dr.GetString("SettingName"), dr.GetString("SettingValue")); - } - - dr.Close(); - return ht; - } - - public static string GetSetting(int moduleId, string groupKey, string settingName) - { - try - { - return DataProvider.Instance().Settings_Get(moduleId, groupKey, settingName); - } - catch (Exception) - { - return string.Empty; - } - } - - public static bool SaveSetting(int moduleId, string groupKey, string settingName, string settingValue) - { - try - { - DataProvider.Instance().Settings_Save(moduleId, groupKey, settingName, settingValue); - return true; - } - catch (Exception ex) - { - return false; - } - } - } -} diff --git a/Dnn.CommunityForums/class/SettingsBase.cs b/Dnn.CommunityForums/class/SettingsBase.cs index 9c86fe124..32cc68118 100644 --- a/Dnn.CommunityForums/class/SettingsBase.cs +++ b/Dnn.CommunityForums/class/SettingsBase.cs @@ -28,15 +28,8 @@ namespace DotNetNuke.Modules.ActiveForums public class SettingsBase : PortalModuleBase { - #region Private Members private int forumModuleId = -1; - private string loadView = string.Empty; - private string imagePath = string.Empty; - private string @params = string.Empty; - private int forumTabId = -1; - #endregion - #region Public Properties internal DotNetNuke.Modules.ActiveForums.Entities.ForumUserInfo ForumUser => new DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController(this.ForumModuleId).GetByUserId(this.PortalId, this.UserId); internal string UserForumsList => DotNetNuke.Modules.ActiveForums.Controllers.ForumController.GetForumsForUser(this.PortalId, this.ForumModuleId, this.ForumUser); @@ -45,12 +38,9 @@ public int ForumModuleId { get { - if (this.forumModuleId > 0) - { - return this.forumModuleId; - } - - return DotNetNuke.Modules.ActiveForums.Utilities.GetForumModuleId(this.ModuleId, this.TabId); + return this.forumModuleId > 0 + ? this.forumModuleId + : DotNetNuke.Modules.ActiveForums.Utilities.GetForumModuleId(this.ModuleId, this.TabId); } set @@ -59,31 +49,9 @@ public int ForumModuleId } } - public int ForumTabId - { - get - { - return this.forumTabId; - } - - set - { - this.forumTabId = value; - } - } - - public string Params - { - get - { - return this.@params; - } + public int ForumTabId { get; set; } = -1; - set - { - this.@params = value; - } - } + public string Params { get; set; } = string.Empty; public int PageId { @@ -119,15 +87,12 @@ public int PageId public bool ShowToolbar { get; set; } = true; - #endregion [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. No longer used.")] public UserController UserController => throw new NotImplementedException(); [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. No longer used.")] public ForumsDB ForumsDB => throw new NotImplementedException(); - #region Public Properties - User Preferences - [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. No longer used.")] public CurrentUserTypes CurrentUserType => this.ForumUser.CurrentUserType; @@ -135,31 +100,9 @@ public int PageId public bool UserIsMod => this.ForumUser.GetIsMod(this.ForumModuleId); [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. No longer used.")] - public string UserDefaultSort - { - get - { - if (this.UserId != -1) - { - return this.ForumUser.PrefDefaultSort; - } + public string UserDefaultSort => this.UserId != -1 ? this.ForumUser.PrefDefaultSort : "ASC"; - return "ASC"; - } - } - - public int UserDefaultPageSize - { - get - { - if (this.UserId != -1) - { - return this.ForumUser.PrefPageSize; - } - - return this.MainSettings.PageSize; - } - } + public int UserDefaultPageSize => this.UserId != -1 ? this.ForumUser.PrefPageSize : this.ModuleSettings.PageSize; [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. No longer used.")] public bool UserPrefHideSigs @@ -183,83 +126,31 @@ public bool UserPrefHideSigs } [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. No longer used.")] - public bool UserPrefHideAvatars - { - get - { - if (this.UserId != -1) - { - return this.ForumUser.PrefBlockAvatars; - } - - return false; - } - } + public bool UserPrefHideAvatars => this.UserId != -1 ? this.ForumUser.PrefBlockAvatars : false; [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. No longer used.")] - public bool UserPrefJumpLastPost - { - get - { - if (this.UserId != -1) - { - return this.ForumUser.PrefJumpLastPost; - } - - return false; - } - } + public bool UserPrefJumpLastPost => this.UserId != -1 ? this.ForumUser.PrefJumpLastPost : false; [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. No longer used.")] - public bool UserPrefShowReplies - { - get - { - if (this.UserId != -1) - { - return this.ForumUser.PrefDefaultShowReplies; - } - - return false; - } - } + public bool UserPrefShowReplies => this.UserId != -1 ? this.ForumUser.PrefDefaultShowReplies : false; - public bool UserPrefTopicSubscribe - { - get - { - if (this.UserId != -1) - { - return this.ForumUser.PrefTopicSubscribe; - } + public bool UserPrefTopicSubscribe => this.UserId != -1 ? this.ForumUser.PrefTopicSubscribe : false; - return false; - } - } - #endregion + public Framework.CDefault BasePage => (Framework.CDefault)this.Page; - #region Public ReadOnly Properties - public Framework.CDefault BasePage + public static DotNetNuke.Modules.ActiveForums.ModuleSettings GetModuleSettings(int moduleId) { - get - { - return (Framework.CDefault)this.Page; - } - } - - public static SettingsInfo GetModuleSettings(int moduleId) - { - SettingsInfo objSettings = (SettingsInfo)DataCache.SettingsCacheRetrieve(moduleId, string.Format(CacheKeys.MainSettings, moduleId)); + DotNetNuke.Modules.ActiveForums.ModuleSettings objSettings = (ModuleSettings)DataCache.SettingsCacheRetrieve(moduleId, string.Format(CacheKeys.MainSettings, moduleId)); if (objSettings == null && moduleId > 0) { - objSettings = new SettingsInfo { ModuleId = moduleId, MainSettings = new DotNetNuke.Entities.Modules.ModuleController().GetModule(moduleId).ModuleSettings }; + objSettings = new DotNetNuke.Modules.ActiveForums.ModuleSettings { ModuleId = moduleId, MainSettings = new DotNetNuke.Entities.Modules.ModuleController().GetModule(moduleId).ModuleSettings }; DataCache.SettingsCacheStore(moduleId, string.Format(CacheKeys.MainSettings, moduleId), objSettings); } return objSettings; } - public SettingsInfo MainSettings + public DotNetNuke.Modules.ActiveForums.ModuleSettings ModuleSettings { get { @@ -268,13 +159,7 @@ public SettingsInfo MainSettings } } - public string ImagePath - { - get - { - return this.Page.ResolveUrl(string.Concat(this.MainSettings.ThemeLocation, "/images")); - } - } + public string ImagePath => this.Page.ResolveUrl(string.Concat(this.ModuleSettings.ThemeLocation, "/images")); public string GetViewType { @@ -285,55 +170,23 @@ public string GetViewType return this.Request.Params[ParamKeys.ViewType].ToUpperInvariant(); } - if (this.Request.Params["view"] != null) - { - return this.Request.Params["view"].ToUpperInvariant(); - } - - return null; + return this.Request.Params["view"] != null ? this.Request.Params["view"].ToUpperInvariant() : null; } } - public TimeSpan TimeZoneOffset - { - /* AF now stores datetime in UTC, so this method returns timezoneoffset for current user if available or from portal settings as fallback */ - get - { - return Utilities.GetTimeZoneOffsetForUser(this.UserInfo); - } - } - - #endregion + // Forums stores datetime in UTC, so this method returns timezoneoffset for current user if available or from portal settings as fallback + public TimeSpan TimeZoneOffset => Utilities.GetTimeZoneOffsetForUser(this.UserInfo); - #region Protected Methods [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. Not Used.")] - protected DateTime GetUserDate(DateTime displayDate) - { - return displayDate.AddMinutes(this.TimeZoneOffset.TotalMinutes); - } + protected DateTime GetUserDate(DateTime displayDate) => displayDate.AddMinutes(this.TimeZoneOffset.TotalMinutes); - #endregion + public string NavigateUrl(int tabId) => Utilities.NavigateURL(tabId); - #region Public Methods - public string NavigateUrl(int tabId) - { - return Utilities.NavigateURL(tabId); - } + public string NavigateUrl(int tabId, string controlKey, params string[] additionalParameters) => Utilities.NavigateURL(tabId, controlKey, additionalParameters); - public string NavigateUrl(int tabId, string controlKey, params string[] additionalParameters) - { - return Utilities.NavigateURL(tabId, controlKey, additionalParameters); - } - - public void RenderMessage(string title, string message) - { - this.RenderMessage(Utilities.GetSharedResource(title), message, string.Empty, null); - } + public void RenderMessage(string title, string message) => this.RenderMessage(Utilities.GetSharedResource(title), message, string.Empty, null); - public void RenderMessage(string message, string errorMsg, Exception ex) - { - this.RenderMessage(Utilities.GetSharedResource("[RESX:Error]"), message, errorMsg, ex); - } + public void RenderMessage(string message, string errorMsg, Exception ex) => this.RenderMessage(Utilities.GetSharedResource("[RESX:Error]"), message, errorMsg, ex); public void RenderMessage(string title, string message, string errorMsg, Exception ex) { @@ -383,6 +236,5 @@ protected override void OnLoad(EventArgs e) ServicesFramework.Instance.RequestAjaxAntiForgerySupport(); } - #endregion } } diff --git a/Dnn.CommunityForums/class/TemplateUtils.cs b/Dnn.CommunityForums/class/TemplateUtils.cs index d38aa9624..43d052a5a 100644 --- a/Dnn.CommunityForums/class/TemplateUtils.cs +++ b/Dnn.CommunityForums/class/TemplateUtils.cs @@ -241,7 +241,7 @@ private static string ParseProfileInfo(int moduleId, DotNetNuke.Modules.ActiveFo var myTemplate = Convert.ToString(DataCache.SettingsCacheRetrieve(moduleId, cacheKey)); if (string.IsNullOrEmpty(myTemplate)) { - myTemplate = DotNetNuke.Modules.ActiveForums.Controllers.TemplateController.Template_Get(moduleId, Enums.TemplateType.ProfileInfo, SettingsBase.GetModuleSettings(moduleId).ForumFeatureSettings.TemplateFileNameSuffix); + myTemplate = DotNetNuke.Modules.ActiveForums.Controllers.TemplateController.Template_Get(moduleId, Enums.TemplateType.ProfileInfo, SettingsBase.GetModuleSettings(moduleId).DefaultFeatureSettings.TemplateFileNameSuffix); if (cacheKey != string.Empty) { DataCache.SettingsCacheStore(moduleId, cacheKey, myTemplate); diff --git a/Dnn.CommunityForums/class/Utilities.cs b/Dnn.CommunityForums/class/Utilities.cs index 3bdb0bfee..f95aad739 100644 --- a/Dnn.CommunityForums/class/Utilities.cs +++ b/Dnn.CommunityForums/class/Utilities.cs @@ -115,7 +115,7 @@ internal static string BuildToolbar(int portalId, int forumModuleId, int forumTa string sToolbar = SettingsBase.GetModuleSettings(moduleId).CacheTemplates ? Convert.ToString(DataCache.SettingsCacheRetrieve(moduleId, cacheKey)) : string.Empty; if (string.IsNullOrEmpty(sToolbar)) { - sToolbar = DotNetNuke.Modules.ActiveForums.Controllers.TemplateController.Template_Get(forumModuleId, Enums.TemplateType.ToolBar, SettingsBase.GetModuleSettings(moduleId).ForumFeatureSettings.TemplateFileNameSuffix); + sToolbar = DotNetNuke.Modules.ActiveForums.Controllers.TemplateController.Template_Get(forumModuleId, Enums.TemplateType.ToolBar, SettingsBase.GetModuleSettings(moduleId).DefaultFeatureSettings.TemplateFileNameSuffix); sToolbar = Utilities.ParseToolBar(template: sToolbar, portalId: portalId, forumTabId: forumTabId, forumModuleId: forumModuleId, tabId: tabId, moduleId: moduleId, forumUser: forumUser, requestUri: requestUri, rawUrl: rawUrl); if (SettingsBase.GetModuleSettings(moduleId).CacheTemplates) { diff --git a/Dnn.CommunityForums/components/Common/HandlerBase.cs b/Dnn.CommunityForums/components/Common/HandlerBase.cs index b6328a550..3ba9e5578 100644 --- a/Dnn.CommunityForums/components/Common/HandlerBase.cs +++ b/Dnn.CommunityForums/components/Common/HandlerBase.cs @@ -44,7 +44,7 @@ internal enum OutputCodes : int private int _groupid = -1; private int _upid = -1; private DotNetNuke.Entities.Portals.PortalSettings _ps; - private SettingsInfo _mainSettings; + private ModuleSettings _mainSettings; private bool _AdminRequired = false; public bool AdminRequired @@ -137,7 +137,7 @@ public bool IsDebug } } - public SettingsInfo MainSettings + public ModuleSettings MainSettings { get { diff --git a/Dnn.CommunityForums/components/Data/Common.cs b/Dnn.CommunityForums/components/Data/Common.cs index 5fbfd8860..eed0b26e9 100644 --- a/Dnn.CommunityForums/components/Data/Common.cs +++ b/Dnn.CommunityForums/components/Data/Common.cs @@ -174,7 +174,7 @@ public bool CheckForumURL(int portalId, int moduleId, string vanityName, int for { try { - SettingsInfo _mainSettings = SettingsBase.GetModuleSettings(moduleId); + ModuleSettings _mainSettings = SettingsBase.GetModuleSettings(moduleId); DotNetNuke.Modules.ActiveForums.Entities.ForumGroupInfo fg = new DotNetNuke.Modules.ActiveForums.Controllers.ForumGroupController().GetById(forumGroupId, moduleId); if (!string.IsNullOrEmpty(fg.PrefixURL)) { @@ -213,7 +213,7 @@ public bool CheckGroupURL(int portalId, int moduleId, string vanityName, int for { try { - SettingsInfo _mainSettings = SettingsBase.GetModuleSettings(moduleId); + ModuleSettings _mainSettings = SettingsBase.GetModuleSettings(moduleId); if (!string.IsNullOrEmpty(_mainSettings.PrefixURLBase)) { vanityName = _mainSettings.PrefixURLBase + "/" + vanityName; diff --git a/Dnn.CommunityForums/components/Extensions/ReWriter.cs b/Dnn.CommunityForums/components/Extensions/ReWriter.cs index 07281a08b..f6355fbcb 100644 --- a/Dnn.CommunityForums/components/Extensions/ReWriter.cs +++ b/Dnn.CommunityForums/components/Extensions/ReWriter.cs @@ -40,7 +40,7 @@ public class ForumsReWriter : IHttpModule private int contentId = -1; private int userId = -1; private int archived = 0; - private SettingsInfo mainSettings = null; + private ModuleSettings mainSettings = null; private int urlType = 0; // 0=default, 1= views, 2 = category, 3 = tag private int otherId = -1; private int categoryId = -1; @@ -307,7 +307,7 @@ public void OnBeginRequest(object s, EventArgs e) if (this.moduleId > 0) { - this.mainSettings = new SettingsInfo { ModuleId = this.moduleId, MainSettings = DotNetNuke.Entities.Modules.ModuleController.Instance.GetModule(moduleId: this.moduleId, tabId: DotNetNuke.Common.Utilities.Null.NullInteger, ignoreCache: false).ModuleSettings }; + this.mainSettings = new ModuleSettings { ModuleId = this.moduleId, MainSettings = DotNetNuke.Entities.Modules.ModuleController.Instance.GetModule(moduleId: this.moduleId, tabId: DotNetNuke.Common.Utilities.Null.NullInteger, ignoreCache: false).ModuleSettings }; } if (this.mainSettings == null) diff --git a/Dnn.CommunityForums/components/Helpers/UpgradeModuleSettings.cs b/Dnn.CommunityForums/components/Helpers/UpgradeModuleSettings.cs index 7b520ea91..5624e2ce0 100644 --- a/Dnn.CommunityForums/components/Helpers/UpgradeModuleSettings.cs +++ b/Dnn.CommunityForums/components/Helpers/UpgradeModuleSettings.cs @@ -21,8 +21,10 @@ namespace DotNetNuke.Modules.ActiveForums.Helpers { using System; + using System.Collections; using System.Xml; + using DotNetNuke.Collections; using DotNetNuke.Common.Utilities; using DotNetNuke.Data; using DotNetNuke.Entities.Modules; @@ -47,16 +49,18 @@ internal static void MoveSettings_070011() { if (!SettingsBase.GetModuleSettings(module.ModuleID).IsInstalled) { - MoveSettingsForModuleInstanceToTabModuleInstance(module.ModuleID, tabModuleId: module.TabModuleID); + MoveSettingsForModuleInstanceToTabModuleInstance_070011(module.ModuleID, tabModuleId: module.TabModuleID); } } } } } - internal static void MoveSettingsForModuleInstanceToTabModuleInstance(int forumModuleId, int tabModuleId) + internal static void MoveSettingsForModuleInstanceToTabModuleInstance_070011(int forumModuleId, int tabModuleId) { - var currSettings = new SettingsInfo { ModuleId = forumModuleId, MainSettings = Settings.GeneralSettings(forumModuleId, "GEN") }; + var ht = new Hashtable(); + new DotNetNuke.Modules.ActiveForums.Controllers.SettingsController().GetSettingsForModuleIdSettingsKey(forumModuleId, "GEN").ForEach(s => ht.Add(s.SettingName, s.SettingValue)); + var currSettings = new ModuleSettings { ModuleId = forumModuleId, MainSettings = ht }; DotNetNuke.Entities.Modules.ModuleController.Instance.UpdateModuleSetting(tabModuleId, SettingKeys.PageSize, currSettings.PageSize.ToString()); DotNetNuke.Entities.Modules.ModuleController.Instance.UpdateModuleSetting(tabModuleId, SettingKeys.UserNameDisplay, currSettings.UserNameDisplay); diff --git a/Dnn.CommunityForums/components/Topics/TopicsController.cs b/Dnn.CommunityForums/components/Topics/TopicsController.cs index b0f38a840..1c51c1623 100644 --- a/Dnn.CommunityForums/components/Topics/TopicsController.cs +++ b/Dnn.CommunityForums/components/Topics/TopicsController.cs @@ -84,7 +84,7 @@ public int Topics_SaveToForum(int forumId, int topicId, int portalId, int module public override IList GetModifiedSearchDocuments(ModuleInfo moduleInfo, DateTime beginDateUtc) { - var ms = new SettingsInfo { ModuleId = moduleInfo.ModuleID, MainSettings = moduleInfo.ModuleSettings }; + var ms = new ModuleSettings { ModuleId = moduleInfo.ModuleID, MainSettings = moduleInfo.ModuleSettings }; /* if not using soft deletes, remove and rebuild entire index; note that this "internals" method is suggested by blog post (https://www.dnnsoftware.com/community-blog/cid/154913/integrating-with-search-introducing-modulesearchbase#Comment106) and also is used by the Community Links module (https://github.com/DNNCommunity/DNN.Links/blob/development/Components/FeatureController.cs) diff --git a/Dnn.CommunityForums/controls/admin_manageforums_forumeditor.ascx.cs b/Dnn.CommunityForums/controls/admin_manageforums_forumeditor.ascx.cs index 18a2a6283..04ac77ee0 100644 --- a/Dnn.CommunityForums/controls/admin_manageforums_forumeditor.ascx.cs +++ b/Dnn.CommunityForums/controls/admin_manageforums_forumeditor.ascx.cs @@ -26,8 +26,6 @@ namespace DotNetNuke.Modules.ActiveForums using System.Web.UI.WebControls; using DotNetNuke.Security.Roles; - using AFSettings = DotNetNuke.Modules.ActiveForums.Settings; - public partial class admin_manageforums_forumeditor : ActiveAdminBase { public string imgOn; @@ -497,50 +495,50 @@ private void cbEditorAction_Callback(object sender, Controls.CallBackEventArgs e private void SaveSettings(string sKey, string[] parameters) { - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.TopicsTemplateId, parameters[2]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.TopicTemplateId, parameters[3]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.EmailAddress, parameters[4]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.UseFilter, parameters[5]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AllowPostIcon, parameters[6]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AllowEmoticons, parameters[7]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AllowScript, parameters[8]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.IndexContent, parameters[9]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AllowRSS, parameters[10]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AllowAttach, parameters[11]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AttachCount, parameters[12]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AttachMaxSize, parameters[13]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AttachTypeAllowed, parameters[14]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.EditorMobile, parameters[15]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AllowLikes, parameters[16]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.ReplyPostCount, parameters[17]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AttachAllowBrowseSite, parameters[18]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AttachInsertAllowed, parameters[19]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.MaxAttachWidth, parameters[20]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.MaxAttachHeight, parameters[21]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.ConvertingToJpegAllowed, parameters[22]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AllowHTML, parameters[23]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.EditorType, parameters[24]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.EditorHeight, parameters[25]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.EditorWidth, parameters[26]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.CreatePostCount, parameters[27]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AutoSubscribeNewTopicsOnly, parameters[28]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.EditorPermittedUsers, parameters[29]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.TopicFormId, parameters[30]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.ReplyFormId, parameters[31]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AutoSubscribeRoles, parameters[32]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.ProfileTemplateId, parameters[33]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.IsModerated, parameters[34]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.DefaultTrustLevel, parameters[35]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AutoTrustLevel, parameters[36]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.ModApproveNotify, parameters[37]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.ModRejectNotify, parameters[38]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.ModMoveNotify, parameters[39]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.ModDeleteNotify, parameters[40]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.ModAlertNotify, parameters[41]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AutoSubscribeEnabled, parameters[42]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.QuickReplyFormId, parameters[43]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.EmailNotificationSubjectTemplate, parameters[44]); - AFSettings.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.TemplateFileNameSuffix, parameters[45]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.TopicsTemplateId, parameters[2]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.TopicTemplateId, parameters[3]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.EmailAddress, parameters[4]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.UseFilter, parameters[5]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AllowPostIcon, parameters[6]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AllowEmoticons, parameters[7]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AllowScript, parameters[8]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.IndexContent, parameters[9]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AllowRSS, parameters[10]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AllowAttach, parameters[11]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AttachCount, parameters[12]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AttachMaxSize, parameters[13]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AttachTypeAllowed, parameters[14]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.EditorMobile, parameters[15]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AllowLikes, parameters[16]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.ReplyPostCount, parameters[17]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AttachAllowBrowseSite, parameters[18]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AttachInsertAllowed, parameters[19]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.MaxAttachWidth, parameters[20]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.MaxAttachHeight, parameters[21]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.ConvertingToJpegAllowed, parameters[22]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AllowHTML, parameters[23]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.EditorType, parameters[24]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.EditorHeight, parameters[25]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.EditorWidth, parameters[26]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.CreatePostCount, parameters[27]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AutoSubscribeNewTopicsOnly, parameters[28]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.EditorPermittedUsers, parameters[29]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.TopicFormId, parameters[30]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.ReplyFormId, parameters[31]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AutoSubscribeRoles, parameters[32]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.ProfileTemplateId, parameters[33]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.IsModerated, parameters[34]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.DefaultTrustLevel, parameters[35]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AutoTrustLevel, parameters[36]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.ModApproveNotify, parameters[37]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.ModRejectNotify, parameters[38]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.ModMoveNotify, parameters[39]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.ModDeleteNotify, parameters[40]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.ModAlertNotify, parameters[41]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.AutoSubscribeEnabled, parameters[42]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.QuickReplyFormId, parameters[43]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.EmailNotificationSubjectTemplate, parameters[44]); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(this.ModuleId, sKey, ForumSettingKeys.TemplateFileNameSuffix, parameters[45]); } private void LoadForum(int forumId) @@ -653,7 +651,7 @@ private void LoadDefaults(int groupId) this.trGroups.Visible = false; this.reqGroups.Enabled = false; - this.LoadFeatureSettings(this.MainSettings.ForumFeatureSettings); + this.LoadFeatureSettings(this.MainSettings.DefaultFeatureSettings); } private void LoadFeatureSettings(DotNetNuke.Modules.ActiveForums.Entities.FeatureSettings featureSettings) diff --git a/Dnn.CommunityForums/controls/admin_manageforums_home.ascx.cs b/Dnn.CommunityForums/controls/admin_manageforums_home.ascx.cs index f46aa0f08..07a1bc412 100644 --- a/Dnn.CommunityForums/controls/admin_manageforums_home.ascx.cs +++ b/Dnn.CommunityForums/controls/admin_manageforums_home.ascx.cs @@ -84,7 +84,7 @@ private void BindForums() { inheritance = "\"""; } - else if (group.FeatureSettings.EqualSettings(SettingsBase.GetModuleSettings(this.ModuleId).ForumFeatureSettings)) + else if (group.FeatureSettings.EqualSettings(SettingsBase.GetModuleSettings(this.ModuleId).DefaultFeatureSettings)) { inheritance = "\"""; } diff --git a/Dnn.CommunityForums/controls/admin_templates.ascx.cs b/Dnn.CommunityForums/controls/admin_templates.ascx.cs index 7c4d51a78..5c7fb5dfc 100644 --- a/Dnn.CommunityForums/controls/admin_templates.ascx.cs +++ b/Dnn.CommunityForums/controls/admin_templates.ascx.cs @@ -35,7 +35,7 @@ protected override void OnInit(EventArgs e) protected override void OnLoad(EventArgs e) { base.OnLoad(e); - SettingsInfo moduleSettings = SettingsBase.GetModuleSettings(this.ModuleId); + ModuleSettings moduleSettings = SettingsBase.GetModuleSettings(this.ModuleId); this.txtThemeName.Text = moduleSettings.Theme; this.txtTemplateFolder.Text = this.Server.MapPath(moduleSettings.TemplatePath); } diff --git a/Dnn.CommunityForums/controls/af_grid.ascx.cs b/Dnn.CommunityForums/controls/af_grid.ascx.cs index 233f3894c..b70d6fe9f 100644 --- a/Dnn.CommunityForums/controls/af_grid.ascx.cs +++ b/Dnn.CommunityForums/controls/af_grid.ascx.cs @@ -53,7 +53,7 @@ public partial class af_grid : ForumBase protected override void OnInit(EventArgs e) { base.OnInit(e); - string template = DotNetNuke.Modules.ActiveForums.Controllers.TemplateController.Template_Get(this.ForumModuleId, Enums.TemplateType.TopicResults, SettingsBase.GetModuleSettings(this.ForumModuleId).ForumFeatureSettings.TemplateFileNameSuffix); + string template = DotNetNuke.Modules.ActiveForums.Controllers.TemplateController.Template_Get(this.ForumModuleId, Enums.TemplateType.TopicResults, SettingsBase.GetModuleSettings(this.ForumModuleId).DefaultFeatureSettings.TemplateFileNameSuffix); try { @@ -120,7 +120,7 @@ private void TopicRepeaterOnItemDataBound(object sender, RepeaterItemEventArgs r var topic = new DotNetNuke.Modules.ActiveForums.Controllers.TopicController(this.ForumModuleId).GetById(topicId); if (topic != null) { - itemTemplate = Utilities.DecodeBrackets(DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceTopicTokens(new StringBuilder(itemTemplate), topic, this.PortalSettings, this.MainSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl).ToString()); + itemTemplate = Utilities.DecodeBrackets(DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceTopicTokens(new StringBuilder(itemTemplate), topic, this.PortalSettings, this.ModuleSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl).ToString()); ((LiteralControl)repeaterItemEventArgs.Item.Controls[0]).Text = itemTemplate; } } @@ -147,7 +147,7 @@ private void RepeaterOnItemCreated(object sender, RepeaterItemEventArgs repeater private void BindPosts(string sort = "ASC") { - this.pageSize = (this.UserId > 0) ? this.UserDefaultPageSize : this.MainSettings.PageSize; + this.pageSize = (this.UserId > 0) ? this.UserDefaultPageSize : this.ModuleSettings.PageSize; if (this.pageSize < 5) { @@ -315,7 +315,7 @@ private void BindPosts(string sort = "ASC") break; } - if (this.MainSettings.UseSkinBreadCrumb) + if (this.ModuleSettings.UseSkinBreadCrumb) { Environment.UpdateBreadCrumb(this.Page.Controls, $"{this.lblHeader.Text}"); } @@ -432,16 +432,16 @@ private void BuildPager(PagerNav pager) pager.PageMode = Modules.ActiveForums.Controls.PagerNav.Mode.Links; - if (this.MainSettings.URLRewriteEnabled) + if (this.ModuleSettings.URLRewriteEnabled) { - if (!string.IsNullOrEmpty(this.MainSettings.PrefixURLBase)) + if (!string.IsNullOrEmpty(this.ModuleSettings.PrefixURLBase)) { - pager.BaseURL = "/" + this.MainSettings.PrefixURLBase; + pager.BaseURL = "/" + this.ModuleSettings.PrefixURLBase; } - if (!string.IsNullOrEmpty(this.MainSettings.PrefixURLOther)) + if (!string.IsNullOrEmpty(this.ModuleSettings.PrefixURLOther)) { - pager.BaseURL += "/" + this.MainSettings.PrefixURLOther; + pager.BaseURL += "/" + this.ModuleSettings.PrefixURLOther; } pager.BaseURL += "/" + this.Request.Params[ParamKeys.GridType] + "/"; @@ -454,7 +454,7 @@ private void BuildPager(PagerNav pager) public string GetArrowPath() { - string theme = this.Page.ResolveUrl(this.MainSettings.ThemeLocation + "/images/miniarrow_down.png"); + string theme = this.Page.ResolveUrl(this.ModuleSettings.ThemeLocation + "/images/miniarrow_down.png"); return theme; } diff --git a/Dnn.CommunityForums/controls/af_likes.ascx.cs b/Dnn.CommunityForums/controls/af_likes.ascx.cs index d6dd07a55..cfd1c7fbc 100644 --- a/Dnn.CommunityForums/controls/af_likes.ascx.cs +++ b/Dnn.CommunityForums/controls/af_likes.ascx.cs @@ -84,7 +84,7 @@ protected override void OnInit(EventArgs e) base.OnInit(e); this.post = new DotNetNuke.Modules.ActiveForums.Controllers.ContentController().GetById(this.ContentId, this.ForumModuleId).Post; - string template = DotNetNuke.Modules.ActiveForums.Controllers.TemplateController.Template_Get(this.ForumModuleId, Enums.TemplateType.Likes, this.post.Forum.FeatureSettings.TemplateFileNameSuffix ?? SettingsBase.GetModuleSettings(this.ForumModuleId).ForumFeatureSettings.TemplateFileNameSuffix); + string template = DotNetNuke.Modules.ActiveForums.Controllers.TemplateController.Template_Get(this.ForumModuleId, Enums.TemplateType.Likes, this.post.Forum.FeatureSettings.TemplateFileNameSuffix ?? SettingsBase.GetModuleSettings(this.ForumModuleId).DefaultFeatureSettings.TemplateFileNameSuffix); try { @@ -136,7 +136,7 @@ protected override void OnLoad(EventArgs e) { if (this.post != null) { - template = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplacePostTokens(new StringBuilder(template), this.post, this.PortalSettings, this.MainSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl).ToString(); + template = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplacePostTokens(new StringBuilder(template), this.post, this.PortalSettings, this.ModuleSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl).ToString(); if (control.GetType().FullName == "System.Web.UI.LiteralControl") { ((System.Web.UI.LiteralControl)control).Text = template; @@ -193,7 +193,7 @@ private void LikeRepeaterOnItemDataBound(object sender, RepeaterItemEventArgs re if (this.post != null) { - itemTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplacePostTokens(new StringBuilder(itemTemplate), this.post, this.PortalSettings, this.MainSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl).ToString(); + itemTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplacePostTokens(new StringBuilder(itemTemplate), this.post, this.PortalSettings, this.ModuleSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl).ToString(); if (control.GetType().FullName == "System.Web.UI.LiteralControl") { @@ -236,7 +236,7 @@ private void LikeRepeaterOnItemDataBound(object sender, RepeaterItemEventArgs re { if (like != null) { - itemTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceLikeTokens(new StringBuilder(itemTemplate), like, this.PortalSettings, this.MainSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl).ToString(); + itemTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceLikeTokens(new StringBuilder(itemTemplate), like, this.PortalSettings, this.ModuleSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl).ToString(); if (control.GetType().FullName == "System.Web.UI.LiteralControl") { ((System.Web.UI.LiteralControl)control).Text = itemTemplate; @@ -258,7 +258,7 @@ private void LikeRepeaterOnItemDataBound(object sender, RepeaterItemEventArgs re private void BindLikes() { - this.pageSize = (this.UserId > 0) ? this.UserDefaultPageSize : this.MainSettings.PageSize; + this.pageSize = (this.UserId > 0) ? this.UserDefaultPageSize : this.ModuleSettings.PageSize; if (this.pageSize < 5) { @@ -346,13 +346,13 @@ private void BuildPager(PagerNav pager) pager.CurrentPage = this.PageId; pager.TabID = this.TabId; pager.ForumID = this.ForumId; - pager.UseShortUrls = this.MainSettings.UseShortUrls; + pager.UseShortUrls = this.ModuleSettings.UseShortUrls; pager.ContentId = this.ContentId; pager.PageText = Utilities.GetSharedResource("[RESX:Page]"); pager.OfText = Utilities.GetSharedResource("[RESX:PageOf]"); pager.View = Views.Likes; pager.PageMode = PagerNav.Mode.Links; - pager.BaseURL = URL.ForumLink(this.TabId, this.post.Forum) + this.post.Topic.TopicUrl + "/" + this.MainSettings.PrefixURLLikes + "/" + this.ContentId; + pager.BaseURL = URL.ForumLink(this.TabId, this.post.Forum) + this.post.Topic.TopicUrl + "/" + this.ModuleSettings.PrefixURLLikes + "/" + this.ContentId; pager.Params = this.Parameters.ToArray(); } diff --git a/Dnn.CommunityForums/controls/af_members.ascx.cs b/Dnn.CommunityForums/controls/af_members.ascx.cs index 2c63f865a..4701f0d8c 100644 --- a/Dnn.CommunityForums/controls/af_members.ascx.cs +++ b/Dnn.CommunityForums/controls/af_members.ascx.cs @@ -29,7 +29,7 @@ protected override void OnLoad(EventArgs e) base.OnLoad(e); this.lblHeader.Text = Utilities.GetSharedResource("[RESX:MemberDirectory]"); - string sMode = this.MainSettings.MemberListMode; + string sMode = this.ModuleSettings.MemberListMode; if (!this.UserInfo.IsSuperUser) { if (sMode == "DISABLED") diff --git a/Dnn.CommunityForums/controls/af_modtopics.ascx.cs b/Dnn.CommunityForums/controls/af_modtopics.ascx.cs index 0d66182ec..0792b3bcf 100644 --- a/Dnn.CommunityForums/controls/af_modtopics.ascx.cs +++ b/Dnn.CommunityForums/controls/af_modtopics.ascx.cs @@ -70,7 +70,7 @@ protected override void OnLoad(EventArgs e) private void cbMod_Callback(object sender, Modules.ActiveForums.Controls.CallBackEventArgs e) { - SettingsInfo ms = SettingsBase.GetModuleSettings(this.ForumModuleId); + ModuleSettings ms = SettingsBase.GetModuleSettings(this.ForumModuleId); DotNetNuke.Modules.ActiveForums.Entities.ForumInfo fi = null; if (e.Parameters.Length > 0) { diff --git a/Dnn.CommunityForums/controls/af_post.ascx.cs b/Dnn.CommunityForums/controls/af_post.ascx.cs index ce237359e..36ef464af 100644 --- a/Dnn.CommunityForums/controls/af_post.ascx.cs +++ b/Dnn.CommunityForums/controls/af_post.ascx.cs @@ -117,7 +117,7 @@ protected override void OnInit(EventArgs e) this.ForumUser.TrustLevel = -1; } this.userIsTrusted = Utilities.IsTrusted((int)this.ForumInfo.FeatureSettings.DefaultTrustValue, this.ForumUser.TrustLevel, this.canTrust, this.ForumInfo.FeatureSettings.AutoTrustLevel, this.ForumUser.PostCount); - this.themePath = this.Page.ResolveUrl(this.MainSettings.ThemeLocation); + this.themePath = this.Page.ResolveUrl(this.ModuleSettings.ThemeLocation); this.Spinner = this.Page.ResolveUrl(this.themePath + "/images/loading.gif"); this.isApproved = !this.ForumInfo.FeatureSettings.IsModerated || this.userIsTrusted || this.canModApprove; @@ -282,9 +282,9 @@ private void ctlForm_Click(object sender, EventArgs e) this.Context.ApplicationInstance.CompleteRequest(); } - if (!Utilities.HasFloodIntervalPassed(floodInterval: this.MainSettings.FloodInterval, forumUser: this.ForumUser, forumInfo: this.ForumInfo)) + if (!Utilities.HasFloodIntervalPassed(floodInterval: this.ModuleSettings.FloodInterval, forumUser: this.ForumUser, forumInfo: this.ForumInfo)) { - this.plhMessage.Controls.Add(new InfoMessage { Message = "
    " + string.Format(this.GetSharedResource("[RESX:Error:FloodControl]"), this.MainSettings.FloodInterval) + "
    " }); + this.plhMessage.Controls.Add(new InfoMessage { Message = "
    " + string.Format(this.GetSharedResource("[RESX:Error:FloodControl]"), this.ModuleSettings.FloodInterval) + "
    " }); return; } if (!this.Page.IsValid || !Utilities.InputIsValid(this.ctlForm.Body.Trim()) || !Utilities.InputIsValid(this.ctlForm.Subject)) @@ -381,7 +381,7 @@ private void LoadTopic() { var im = new InfoMessage { - Message = "
    " + string.Format(this.GetSharedResource("[RESX:Message:EditIntervalNotReached]"), this.MainSettings.EditInterval) + "
    ", + Message = "
    " + string.Format(this.GetSharedResource("[RESX:Message:EditIntervalNotReached]"), this.ModuleSettings.EditInterval) + "
    ", }; this.plhMessage.Controls.Add(im); this.plhContent.Controls.Clear(); @@ -467,7 +467,7 @@ private void LoadReply() { var im = new Controls.InfoMessage { - Message = "
    " + string.Format(this.GetSharedResource("[RESX:Message:EditIntervalNotReached]"), this.MainSettings.EditInterval.ToString()) + "
    ", + Message = "
    " + string.Format(this.GetSharedResource("[RESX:Message:EditIntervalNotReached]"), this.ModuleSettings.EditInterval.ToString()) + "
    ", }; this.plhMessage.Controls.Add(im); this.plhContent.Controls.Clear(); @@ -503,7 +503,7 @@ private void PrepareTopic() template = template.Replace("[RESX:CreateNewTopic]", "[RESX:EditingExistingTopic]"); } - if (this.MainSettings.UseSkinBreadCrumb) + if (this.ModuleSettings.UseSkinBreadCrumb) { var sCrumb = "" + this.ForumInfo.GroupName + "|"; sCrumb += "" + this.ForumInfo.ForumName + ""; @@ -534,7 +534,7 @@ private void PrepareReply() string template = DotNetNuke.Modules.ActiveForums.Controllers.TemplateController.Template_Get(this.ForumModuleId, Enums.TemplateType.ReplyEditor, this.ForumInfo.FeatureSettings.TemplateFileNameSuffix); #region "Backward compatilbility -- remove in v10.00.00" - template = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyAuthorTokenSynonyms(new StringBuilder(template), this.PortalSettings, this.MainSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale).ToString(); + template = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyAuthorTokenSynonyms(new StringBuilder(template), this.PortalSettings, this.ModuleSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale).ToString(); template = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyPostTokenSynonyms(new StringBuilder(template), this.PortalSettings, this.ForumUser.UserInfo?.Profile?.PreferredLocale).ToString(); #endregion "Backward compatilbility -- remove in v10.00.00" @@ -543,7 +543,7 @@ private void PrepareReply() template = template.Replace("[RESX:ReplyToTopic]", "[RESX:EditingExistingReply]"); } - if (this.MainSettings.UseSkinBreadCrumb) + if (this.ModuleSettings.UseSkinBreadCrumb) { template = template.Replace("
    [AF:LINK:FORUMMAIN] > [AF:LINK:FORUMGROUP] > [AF:LINK:FORUMNAME]
    ", string.Empty); } @@ -614,7 +614,7 @@ private void PrepareReply() if (post != null) { var sPostedBy = Utilities.GetSharedResource("[RESX:PostedBy]") + " {0} {1} {2}"; - sPostedBy = string.Format(sPostedBy, DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.GetDisplayName(this.PortalSettings, this.MainSettings, false, false, post.Author.AuthorId, post.Author.Username, post.Author.FirstName, post.Author.LastName, post.Author.DisplayName), Utilities.GetSharedResource("On.Text"), Utilities.GetUserFormattedDateTime(post.Content.DateCreated, this.PortalId, this.UserId)); + sPostedBy = string.Format(sPostedBy, DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.GetDisplayName(this.PortalSettings, this.ModuleSettings, false, false, post.Author.AuthorId, post.Author.Username, post.Author.FirstName, post.Author.LastName, post.Author.DisplayName), Utilities.GetSharedResource("On.Text"), Utilities.GetUserFormattedDateTime(post.Content.DateCreated, this.PortalId, this.UserId)); var body = post.Content.Body; if (this.allowHTML && this.editorType != EditorTypes.TEXTBOX) { @@ -682,7 +682,7 @@ private void SaveTopic() if (this.Request.IsAuthenticated) { authorId = this.UserInfo.UserID; - switch (this.MainSettings.UserNameDisplay.ToUpperInvariant()) + switch (this.ModuleSettings.UserNameDisplay.ToUpperInvariant()) { case "USERNAME": authorName = this.UserInfo.Username.Trim(' '); @@ -936,7 +936,7 @@ private void SaveReply() if (this.Request.IsAuthenticated) { authorId = this.UserInfo.UserID; - switch (this.MainSettings.UserNameDisplay.ToUpperInvariant()) + switch (this.ModuleSettings.UserNameDisplay.ToUpperInvariant()) { case "USERNAME": authorName = this.UserInfo.Username.Trim(' '); diff --git a/Dnn.CommunityForums/controls/af_profile.ascx.cs b/Dnn.CommunityForums/controls/af_profile.ascx.cs index ed9e936fb..4388735e7 100644 --- a/Dnn.CommunityForums/controls/af_profile.ascx.cs +++ b/Dnn.CommunityForums/controls/af_profile.ascx.cs @@ -38,18 +38,18 @@ protected override void OnLoad(EventArgs e) DotNetNuke.Entities.Users.UserInfo ui = DotNetNuke.Entities.Users.UserController.Instance.GetUser(this.PortalId, tUid); if (ui != null) { - sDisplayName = DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.GetDisplayName(this.PortalSettings, this.MainSettings, false, false, ui.UserID, ui.Username, ui.FirstName, ui.LastName, ui.DisplayName); + sDisplayName = DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.GetDisplayName(this.PortalSettings, this.ModuleSettings, false, false, ui.UserID, ui.Username, ui.FirstName, ui.LastName, ui.DisplayName); } } } else { tUid = this.UserId; - sDisplayName = DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.GetDisplayName(this.PortalSettings, this.MainSettings, false, false, this.UserId, this.UserInfo.Username, this.UserInfo.FirstName, this.UserInfo.LastName, this.UserInfo.DisplayName); + sDisplayName = DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.GetDisplayName(this.PortalSettings, this.ModuleSettings, false, false, this.UserId, this.UserInfo.Username, this.UserInfo.FirstName, this.UserInfo.LastName, this.UserInfo.DisplayName); } this.lblHeader.Text = string.Format(Utilities.GetSharedResource("[RESX:ProfileForUser]"), sDisplayName); - if (this.MainSettings.UseSkinBreadCrumb) + if (this.ModuleSettings.UseSkinBreadCrumb) { Environment.UpdateBreadCrumb(this.Page.Controls, "" + this.lblHeader.Text + ""); } diff --git a/Dnn.CommunityForums/controls/af_quickreply.ascx.cs b/Dnn.CommunityForums/controls/af_quickreply.ascx.cs index 16e052bfc..0cb483752 100644 --- a/Dnn.CommunityForums/controls/af_quickreply.ascx.cs +++ b/Dnn.CommunityForums/controls/af_quickreply.ascx.cs @@ -218,7 +218,7 @@ private void SaveQuickReply() if (!Utilities.HasFloodIntervalPassed(floodInterval: this.ForumInfo.MainSettings.FloodInterval, forumUser: this.ForumUser, forumInfo: forumInfo)) { Controls.InfoMessage im = new Controls.InfoMessage(); - im.Message = "
    " + string.Format(Utilities.GetSharedResource("[RESX:Error:FloodControl]"), this.MainSettings.FloodInterval) + "
    "; + im.Message = "
    " + string.Format(Utilities.GetSharedResource("[RESX:Error:FloodControl]"), this.ModuleSettings.FloodInterval) + "
    "; this.plhMessage.Controls.Add(im); return; } @@ -259,7 +259,7 @@ private void SaveQuickReply() string sUsername = string.Empty; if (this.Request.IsAuthenticated) { - switch (this.MainSettings.UserNameDisplay.ToUpperInvariant()) + switch (this.ModuleSettings.UserNameDisplay.ToUpperInvariant()) { case "USERNAME": sUsername = this.UserInfo.Username.Trim(' '); diff --git a/Dnn.CommunityForums/controls/af_recycle_bin.ascx.cs b/Dnn.CommunityForums/controls/af_recycle_bin.ascx.cs index 747528ba4..8af2b7496 100644 --- a/Dnn.CommunityForums/controls/af_recycle_bin.ascx.cs +++ b/Dnn.CommunityForums/controls/af_recycle_bin.ascx.cs @@ -125,7 +125,7 @@ protected override void OnLoad(EventArgs e) base.OnLoad(e); try { - int _pageSize = this.MainSettings.PageSize; + int _pageSize = this.ModuleSettings.PageSize; if (this.UserInfo.UserID > 0) { _pageSize = this.UserDefaultPageSize; diff --git a/Dnn.CommunityForums/controls/af_search.ascx.cs b/Dnn.CommunityForums/controls/af_search.ascx.cs index e60f3883e..ac408880d 100644 --- a/Dnn.CommunityForums/controls/af_search.ascx.cs +++ b/Dnn.CommunityForums/controls/af_search.ascx.cs @@ -79,7 +79,7 @@ public partial class af_search : ForumBase protected override void OnInit(EventArgs e) { base.OnInit(e); - string template = DotNetNuke.Modules.ActiveForums.Controllers.TemplateController.Template_Get(this.ForumModuleId, Enums.TemplateType.SearchResults, SettingsBase.GetModuleSettings(this.ForumModuleId).ForumFeatureSettings.TemplateFileNameSuffix); + string template = DotNetNuke.Modules.ActiveForums.Controllers.TemplateController.Template_Get(this.ForumModuleId, Enums.TemplateType.SearchResults, SettingsBase.GetModuleSettings(this.ForumModuleId).DefaultFeatureSettings.TemplateFileNameSuffix); try { @@ -181,7 +181,7 @@ private void TopicRepeaterOnItemDataBound(object sender, RepeaterItemEventArgs r var topic = new DotNetNuke.Modules.ActiveForums.Controllers.TopicController(this.ForumModuleId).GetById(topicId); if (topic != null) { - itemTemplate = Utilities.DecodeBrackets(DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceTopicTokens(new StringBuilder(itemTemplate), topic, this.PortalSettings, this.MainSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl).ToString()); + itemTemplate = Utilities.DecodeBrackets(DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceTopicTokens(new StringBuilder(itemTemplate), topic, this.PortalSettings, this.ModuleSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl).ToString()); ((LiteralControl)repeaterItemEventArgs.Item.Controls[0]).Text = itemTemplate; } } @@ -243,7 +243,7 @@ private void PostRepeaterOnItemDataBound(object sender, RepeaterItemEventArgs re if (!string.IsNullOrEmpty(itemTemplate) && itemTemplate.Contains("[")) { - itemTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplacePostTokens(new StringBuilder(itemTemplate), post, this.PortalSettings, this.MainSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl).ToString(); + itemTemplate = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplacePostTokens(new StringBuilder(itemTemplate), post, this.PortalSettings, this.ModuleSettings, new Services.URLNavigator().NavigationManager(), this.ForumUser, this.Request.Url, this.Request.RawUrl).ToString(); if (control.GetType().FullName == "System.Web.UI.LiteralControl") { ((System.Web.UI.LiteralControl)control).Text = itemTemplate; @@ -528,7 +528,7 @@ private List Parameters private void BindPosts() { - this.pageSize = (this.UserId > 0) ? this.UserDefaultPageSize : this.MainSettings.PageSize; + this.pageSize = (this.UserId > 0) ? this.UserDefaultPageSize : this.ModuleSettings.PageSize; if (this.pageSize < 5) { @@ -565,7 +565,7 @@ private void BindPosts() const int maxCacheHours = 1; - var ds = DataProvider.Instance().Search(this.PortalId, this.ModuleId, this.UserId, this.SearchId, this.rowIndex, this.pageSize, this.SearchText, this.SearchType, this.SearchColumns, this.SearchDays, this.AuthorUserId, this.AuthorUsername, forumsToSearch, this.Tags, this.ResultType, this.Sort, maxCacheHours, this.MainSettings.FullText); + var ds = DataProvider.Instance().Search(this.PortalId, this.ModuleId, this.UserId, this.SearchId, this.rowIndex, this.pageSize, this.SearchText, this.SearchType, this.SearchColumns, this.SearchDays, this.AuthorUserId, this.AuthorUsername, forumsToSearch, this.Tags, this.ResultType, this.Sort, maxCacheHours, this.ModuleSettings.FullText); var dtSummary = (ds != null) ? ds.Tables[0] : null; diff --git a/Dnn.CommunityForums/controls/af_sendto.ascx.cs b/Dnn.CommunityForums/controls/af_sendto.ascx.cs index 7e4b086af..f24f33ec7 100644 --- a/Dnn.CommunityForums/controls/af_sendto.ascx.cs +++ b/Dnn.CommunityForums/controls/af_sendto.ascx.cs @@ -58,21 +58,21 @@ protected override void OnLoad(EventArgs e) this.txtRecipSubject.Text = subjectDefault; string messageDefault = this.GetSharedResource("[RESX:EmailMessageDefault]"); string sURL = this.NavigateUrl(this.TabId, string.Empty, new string[] { ParamKeys.ForumId + "=" + this.ForumId, ParamKeys.ViewType + "=" + Views.Topic, ParamKeys.TopicId + "=" + this.TopicId }); - if (this.MainSettings.UseShortUrls) + if (this.ModuleSettings.UseShortUrls) { sURL = this.NavigateUrl(this.TabId, string.Empty, new string[] { ParamKeys.TopicId + "=" + this.TopicId }); } messageDefault = messageDefault.Replace("[TOPICLINK]", sURL); - messageDefault = messageDefault.Replace("[DISPLAYNAME]", $"{DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.GetDisplayName(portalSettings: this.PortalSettings, mainSettings: this.MainSettings, isMod: false, isAdmin: false, userId: this.UserId, username: this.UserInfo.Username, firstName: this.UserInfo.FirstName, lastName: this.UserInfo.LastName, displayName: this.UserInfo.DisplayName)}"); + messageDefault = messageDefault.Replace("[DISPLAYNAME]", $"{DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.GetDisplayName(portalSettings: this.PortalSettings, mainSettings: this.ModuleSettings, isMod: false, isAdmin: false, userId: this.UserId, username: this.UserInfo.Username, firstName: this.UserInfo.FirstName, lastName: this.UserInfo.LastName, displayName: this.UserInfo.DisplayName)}"); this.txtMessage.Text = messageDefault; } } - if (this.MainSettings.UseSkinBreadCrumb) + if (this.ModuleSettings.UseSkinBreadCrumb) { string sCrumb = "" + this.ForumInfo.GroupName + "|"; - if (this.MainSettings.UseShortUrls) + if (this.ModuleSettings.UseShortUrls) { sCrumb += "" + this.ForumInfo.ForumName + ""; sCrumb += "|" + topicSubject + ""; diff --git a/Dnn.CommunityForums/controls/af_usersonline.ascx.cs b/Dnn.CommunityForums/controls/af_usersonline.ascx.cs index 35248c26b..dd68294ce 100644 --- a/Dnn.CommunityForums/controls/af_usersonline.ascx.cs +++ b/Dnn.CommunityForums/controls/af_usersonline.ascx.cs @@ -54,7 +54,7 @@ protected override void OnLoad(EventArgs e) private void BindUsersOnline() { var user = new DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController(this.ForumModuleId).GetByUserId(this.PortalId, this.UserInfo.UserID); - string sOnlineList = new DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController(this.ForumModuleId).GetUsersOnline(this.PortalSettings, this.MainSettings, this.ForumModuleId, user); + string sOnlineList = new DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController(this.ForumModuleId).GetUsersOnline(this.PortalSettings, this.ModuleSettings, this.ForumModuleId, user); IDataReader dr = DataProvider.Instance().Profiles_GetStats(this.PortalId, 2); int anonCount = 0; int memCount = 0; diff --git a/Dnn.CommunityForums/controls/profile_mypreferences.ascx.cs b/Dnn.CommunityForums/controls/profile_mypreferences.ascx.cs index 38240bd31..cd5de99b4 100644 --- a/Dnn.CommunityForums/controls/profile_mypreferences.ascx.cs +++ b/Dnn.CommunityForums/controls/profile_mypreferences.ascx.cs @@ -79,13 +79,13 @@ private void btnSave_Click(object sender, System.EventArgs e) upi.LikeNotificationsEnabled = this.chkLikesNotificationsEnabled.Checked; upi.PinNotificationsEnabled = this.chkPinNotificationsEnabled.Checked; upi.EnableNotificationsForOwnContent = this.chkEnableNotificationsForOwnContent.Checked; - if (this.MainSettings.AllowSignatures == 1 || this.MainSettings.AllowSignatures == 0) + if (this.ModuleSettings.AllowSignatures == 1 || this.ModuleSettings.AllowSignatures == 0) { upi.Signature = Utilities.XSSFilter(this.txtSignature.Text, true); upi.Signature = Utilities.StripHTMLTag(upi.Signature); upi.Signature = System.Net.WebUtility.HtmlEncode(upi.Signature); } - else if (this.MainSettings.AllowSignatures == 2) + else if (this.ModuleSettings.AllowSignatures == 2) { upi.Signature = Utilities.XSSFilter(this.txtSignature.Text, false); } diff --git a/Dnn.CommunityForums/feeds.aspx.cs b/Dnn.CommunityForums/feeds.aspx.cs index 9b6ac6f8b..6f4fb2389 100644 --- a/Dnn.CommunityForums/feeds.aspx.cs +++ b/Dnn.CommunityForums/feeds.aspx.cs @@ -188,7 +188,7 @@ private string BuildRSS(int portalId, int tabId, int moduleId, int intPosts, int private string BuildItem(DataRow dr, int postTabID, int indent, bool includeBody, int portalId) { - SettingsInfo mainSettings = SettingsBase.GetModuleSettings(this.moduleID); + ModuleSettings mainSettings = SettingsBase.GetModuleSettings(this.moduleID); StringBuilder sb = new StringBuilder(1024); string[] @params = { ParamKeys.ForumId + "=" + dr["ForumID"].ToString(), ParamKeys.TopicId + "=" + dr["TopicId"].ToString(), ParamKeys.ViewType + "=" + Views.Topic }; string uRL = DotNetNuke.Modules.ActiveForums.Utilities.NavigateURL(postTabID, string.Empty, @params); diff --git a/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider b/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider new file mode 100644 index 000000000..236089c0a --- /dev/null +++ b/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider @@ -0,0 +1,1057 @@ +SET NOCOUNT ON +GO +/* issue 1582 - begin - settings table overhaul */ + + +/* drop old activeforums_Settings indexes and replace with new indexes */ + +IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'{databaseOwner}{objectQualifier}activeforums_Settings') AND name = N'idx_{objectQualifier}activeforums_Settings_Opt1') +DROP INDEX [idx_{objectQualifier}activeforums_Settings_Opt1] ON {databaseOwner}{objectQualifier}activeforums_Settings +GO +IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'{databaseOwner}{objectQualifier}activeforums_Settings') AND name = N'idx_{objectQualifier}activeforums_Settings_Opt2') +DROP INDEX [idx_{objectQualifier}activeforums_Settings_Opt2] ON {databaseOwner}{objectQualifier}activeforums_Settings +GO + +IF (OBJECT_ID(N'{databaseOwner}[PK_{objectQualifier}activeforums_Settings]', 'PK') IS NOT NULL) +BEGIN + ALTER TABLE {databaseOwner}[{objectQualifier}activeforums_Settings] DROP CONSTRAINT [PK_{objectQualifier}activeforums_Settings] +END +GO + +IF NOT EXISTS(SELECT * FROM SYS.COLUMNS WHERE Name = N'SettingsId' and Object_ID = Object_ID(N'{databaseOwner}[{objectQualifier}activeforums_Settings]')) +BEGIN + ALTER TABLE {databaseOwner}[{objectQualifier}activeforums_Settings] + ADD SettingsId INT IDENTITY(1,1) +END +GO + +ALTER TABLE {databaseOwner}[{objectQualifier}activeforums_Settings] + ADD CONSTRAINT [PK_{objectQualifier}activeforums_Settings] PRIMARY KEY CLUSTERED ( [SettingsId] ASC ) + WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) + +GO + + +IF EXISTS(SELECT * FROM sys.columns WHERE [name] = N'GroupKey' AND [object_id] = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Settings]')) +exec sp_rename '{databaseOwner}{objectQualifier}activeforums_Settings.GroupKey', 'SettingsKey', 'COLUMN' +GO + + +IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'{databaseOwner}{objectQualifier}activeforums_Settings') AND name = N'IX_{objectQualifier}activeforums_Settings_Opt1') +DROP INDEX [IX_{objectQualifier}activeforums_Settings_Opt1] + ON {databaseOwner}[{objectQualifier}activeforums_Settings]; +GO + +CREATE UNIQUE NONCLUSTERED INDEX [IX_{objectQualifier}activeforums_Settings_Opt1] + ON {databaseOwner}[{objectQualifier}activeforums_Settings] + ( + [ModuleId] ASC, + [SettingsKey] ASC, + [SettingName] ASC + ) + INCLUDE([SettingValue]); +GO + +/* activeforums_Groups_Delete */ +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Groups_Delete]') AND type in (N'P', N'PC')) +DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Groups_Delete] +GO +CREATE PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Groups_Delete] +@ModuleId int, +@ForumGroupId int +AS +DECLARE @GroupSettingsKey nvarchar(25) +SET @GroupSettingsKey = (SELECT GroupSettingsKey FROM {databaseOwner}{objectQualifier}activeforums_Groups WHERE ForumGroupId = @ForumGroupId AND ModuleId = @ModuleId) + +/*DELETE REPLY ATTACHMENTS*/ +DELETE FROM {databaseOwner}{objectQualifier}activeforums_Attachments + WHERE AttachId IN ( + SELECT ca.AttachId FROM {databaseOwner}{objectQualifier}activeforums_Content_Attachments as ca + INNER JOIN {databaseOwner}{objectQualifier}activeforums_Content as c on c.ContentId = ca.ContentId + INNER JOIN {databaseOwner}{objectQualifier}activeforums_Replies as r on c.ContentId = r.ContentId + INNER JOIN {databaseOwner}{objectQualifier}activeforums_ForumTopics as ft on ft.TopicId = r.TopicId + INNER JOIN {databaseOwner}{objectQualifier}activeforums_Forums as f on f.ForumId = ft.ForumId + INNER JOIN {databaseOwner}{objectQualifier}activeforums_Groups as g on g.ForumGroupId = f.ForumGroupId + WHERE g.ForumGroupId = @ForumGroupId) +/*DELETE TOPIC ATTACHMENTS*/ +DELETE FROM {databaseOwner}{objectQualifier}activeforums_Attachments + WHERE AttachId IN ( + SELECT ca.AttachId FROM {databaseOwner}{objectQualifier}activeforums_Content_Attachments as ca + INNER JOIN {databaseOwner}{objectQualifier}activeforums_Content as c on c.ContentId = ca.ContentId + INNER JOIN {databaseOwner}{objectQualifier}activeforums_Topics as t on c.ContentId = t.ContentId + INNER JOIN {databaseOwner}{objectQualifier}activeforums_ForumTopics as ft on ft.TopicId = t.TopicId + INNER JOIN {databaseOwner}{objectQualifier}activeforums_Forums as f on f.ForumId = ft.ForumId + INNER JOIN {databaseOwner}{objectQualifier}activeforums_Groups as g on g.ForumGroupId = f.ForumGroupId + WHERE g.ForumGroupId = @ForumGroupId) + +/*DELETE REPLY CONTENT */ +DELETE FROM {databaseOwner}{objectQualifier}activeforums_Content WHERE ContentId IN ( + Select r.ContentId FROM {databaseOwner}{objectQualifier}activeforums_Replies as r + INNER JOIN {databaseOwner}{objectQualifier}activeforums_ForumTopics as ft on ft.TopicId = r.TopicId + INNER JOIN {databaseOwner}{objectQualifier}activeforums_Forums as f on f.ForumId = ft.ForumId + INNER JOIN {databaseOwner}{objectQualifier}activeforums_Groups as g on g.ForumGroupId = f.ForumGroupId + WHERE g.ForumGroupId = @ForumGroupId) + +/*DELETE REPLIES */ +DELETE FROM {databaseOwner}{objectQualifier}activeforums_Replies + WHERE TopicId IN ( + SELECT ft.TopicId FROM {databaseOwner}{objectQualifier}activeforums_ForumTopics as ft + INNER JOIN {databaseOwner}{objectQualifier}activeforums_Forums as f ON f.ForumId = ft.ForumID + WHERE f.ForumGroupId = @ForumGroupId) + +/*DELETE TOPIC CONTENT */ +DELETE FROM {databaseOwner}{objectQualifier}activeforums_Content WHERE ContentId IN ( + Select t.ContentId FROM {databaseOwner}{objectQualifier}activeforums_Topics as t + INNER JOIN {databaseOwner}{objectQualifier}activeforums_ForumTopics as ft on ft.TopicId = t.TopicId + INNER JOIN {databaseOwner}{objectQualifier}activeforums_Forums as f on f.ForumId = ft.ForumId + INNER JOIN {databaseOwner}{objectQualifier}activeforums_Groups as g on g.ForumGroupId = f.ForumGroupId + WHERE g.ForumGroupId = @ForumGroupId) +/*DELETE TOPICS*/ +DELETE FROM {databaseOwner}{objectQualifier}activeforums_Topics WHERE TopicId IN ( + SELECT ft.TopicId FROM {databaseOwner}{objectQualifier}activeforums_ForumTopics as ft INNER JOIN + {databaseOwner}{objectQualifier}activeforums_Forums as f on f.ForumId = ft.ForumId + WHERE f.ForumGroupId = @ForumGroupId) + +/*DELETE FORUM TRACKING*/ +DELETE FROM {databaseOwner}{objectQualifier}activeforums_Forums_Tracking + WHERE ForumId IN ( + SELECT ForumId FROM {databaseOwner}{objectQualifier}activeforums_Forums WHERE ForumGroupId = @ForumGroupId) +/*DELETE FORUM SETTINGS */ +DELETE FROM {databaseOwner}{objectQualifier}activeforums_Settings + WHERE ModuleId = @ModuleId AND SettingsKey IN ( + SELECT ForumSettingsKey FROM {databaseOwner}{objectQualifier}activeforums_Forums WHERE ForumGroupId = @ForumGroupId) +/*DELETE FORUM SUBSCRIPTIONS */ +DELETE FROM {databaseOwner}{objectQualifier}activeforums_Subscriptions + WHERE ForumId IN ( + SELECT ForumId FROM {databaseOwner}{objectQualifier}activeforums_Forums WHERE ForumGroupId = @ForumGroupId) +/*DELETE TOPICS CATEGORIES */ +DELETE FROM {databaseOwner}{objectQualifier}activeforums_Topics_Categories + WHERE TopicId IN ( + SELECT ft.TopicId FROM {databaseOwner}{objectQualifier}activeforums_ForumTopics as ft INNER JOIN {databaseOwner}{objectQualifier}activeforums_Forums as f on f.ForumId = ft.ForumId WHERE f.ForumGroupId = @ForumGroupId) +/*DELETE TOPICS TAGS */ +DELETE FROM {databaseOwner}{objectQualifier}activeforums_Topics_Tags + WHERE TopicId IN ( + SELECT ft.TopicId FROM {databaseOwner}{objectQualifier}activeforums_ForumTopics as ft INNER JOIN {databaseOwner}{objectQualifier}activeforums_Forums as f on f.ForumId = ft.ForumId WHERE f.ForumGroupId = @ForumGroupId) +/*DELETE TOPICS TRACKING */ +DELETE FROM {databaseOwner}{objectQualifier}activeforums_Topics_Tracking + WHERE TopicId IN ( + SELECT ft.TopicId FROM {databaseOwner}{objectQualifier}activeforums_ForumTopics as ft INNER JOIN {databaseOwner}{objectQualifier}activeforums_Forums as f on f.ForumId = ft.ForumId WHERE f.ForumGroupId = @ForumGroupId) +/*DELETE TOPICS RATINGS */ +DELETE FROM {databaseOwner}{objectQualifier}activeforums_Topics_Ratings + WHERE TopicId IN ( + SELECT ft.TopicId FROM {databaseOwner}{objectQualifier}activeforums_ForumTopics as ft INNER JOIN {databaseOwner}{objectQualifier}activeforums_Forums as f on f.ForumId = ft.ForumId WHERE f.ForumGroupId = @ForumGroupId) +/*DELETE FORUMTOPICS TABLE */ +DELETE FROM {databaseOwner}{objectQualifier}activeforums_ForumTopics + WHERE ForumId IN ( + SELECT f.ForumId FROM {databaseOwner}{objectQualifier}activeforums_Forums as f WHERE f.ForumGroupId = @ForumGroupId) +/*DELETE FORUMS */ +DELETE FROM {databaseOwner}{objectQualifier}activeforums_Forums WHERE ForumGroupId = @ForumGroupId + + +DELETE FROM {databaseOwner}{objectQualifier}activeforums_Settings WHERE SettingsKey = @GroupSettingsKey AND ModuleId = @ModuleId + +DELETE FROM {databaseOwner}{objectQualifier}activeforums_Groups WHERE ForumGroupId = @ForumGroupId AND ModuleId = @ModuleId +GO + + + +/* activeforums_UI_ForumView */ +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_UI_ForumView]') AND type in (N'P', N'PC')) +DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_UI_ForumView] +GO +CREATE PROCEDURE {databaseOwner}[{objectQualifier}activeforums_UI_ForumView] +@PortalId int, +@ModuleId int, +@UserId int, +@IsSuperUser bit = 0, +@ParentForumId int = -1, +@ForumIds nvarchar(2000) = '' +AS +IF @ParentForumId = -1 +BEGIN +SELECT G.ForumGroupId, G.ModuleId, G.GroupName, F.ForumId, F.ForumName, F.ForumDesc, F.Active AS ForumActive, F.Hidden AS ForumHidden, F.TotalTopics, + F.TotalReplies, F.ParentForumId, G.SortOrder AS GroupSort, + F.SortOrder AS ForumSort, G.Active AS GroupActive, G.Hidden AS GroupHidden, + F.LastTopicId, + F.LastReplyId, + IsNull(c.Subject,'') as LastPostSubject, + IsNull(c.AuthorName,'') as LastPostAuthorName, + IsNull(c.AuthorId,-1) as LastPostAuthorId, + IsNull(c.DateCreated,'') as LastPostDate, + ISNULL(g.PrefixURL,'') as GroupPrefixURL, + ISNULL(f.PrefixURL, '') as PrefixURL, + LastRead = IsNull((SELECT LastAccessDate FROM {databaseOwner}{objectQualifier}activeforums_Forums_Tracking WHERE UserId = @UserId AND ForumId = F.ForumId),''), + "AllowRSS" = (SELECT SettingValue FROM {databaseOwner}{objectQualifier}activeforums_Settings WHERE ModuleId = F.ModuleId AND SettingsKey = F.ForumSettingsKey AND SettingName = 'ALLOWRSS'), + P.*, + ISNULL(t.URL,'') as TopicURL, + COALESCE((SELECT COUNT(*) + FROM {databaseOwner}{objectQualifier}activeforums_Subscriptions + WHERE (ForumId = F.ForumId) AND (TopicId = 0)) , 0) AS ForumSubscriberCount + FROM + {databaseOwner}{objectQualifier}activeforums_Groups AS G INNER JOIN + {databaseOwner}{objectQualifier}activeforums_Forums AS F ON G.ForumGroupId = F.ForumGroupId INNER JOIN + {databaseOwner}{objectQualifier}activeforums_Permissions as p ON f.PermissionsId = p.PermissionsId INNER JOIN + {databaseOwner}{objectQualifier}activeforums_Functions_Split(@ForumIds,';') as ft ON ft.id = f.ForumId LEFT OUTER JOIN + {databaseOwner}{objectQualifier}activeforums_Topics as t ON t.TopicId = f.LastTopicId LEFT OUTER JOIN + {databaseOwner}{objectQualifier}activeforums_Content as c ON c.ContentId = t.ContentId + WHERE G.ModuleId = @ModuleId AND (G.Active = 1 AND F.Active = 1) AND (@ParentForumId = -1 OR (@ParentForumId > 0 AND F.ParentForumId = @ParentForumId)) + ORDER BY GroupSort, ForumSort +END +ELSE +BEGIN +SELECT G.ForumGroupId, G.ModuleId, G.GroupName, F.ForumId, F.ForumName, F.ForumDesc, F.Active AS ForumActive, F.Hidden AS ForumHidden, F.TotalTopics, + F.TotalReplies, F.ParentForumId, G.SortOrder AS GroupSort, F.SortOrder AS ForumSort, G.Active AS GroupActive, G.Hidden AS GroupHidden, + F.LastTopicId, + F.LastReplyId, + IsNull(c.Subject,'') as LastPostSubject, + IsNull(c.AuthorName,'') as LastPostAuthorName, + IsNull(c.AuthorId,-1) as LastPostAuthorId, + IsNull(c.DateCreated,'') as LastPostDate, + ISNULL(g.PrefixURL,'') as GroupPrefixURL, + ISNULL(f.PrefixURL, '') as PrefixURL, + ISNULL(t.URL, '') as TopicURL, + COALESCE((SELECT COUNT(*) + FROM {databaseOwner}{objectQualifier}activeforums_Subscriptions + WHERE (ForumId = F.ForumId) AND (TopicId = 0)) , 0) AS ForumSubscriberCount, + LastRead = IsNull((SELECT LastAccessDate FROM {databaseOwner}{objectQualifier}activeforums_Forums_Tracking WHERE UserId = @UserId AND ForumId = F.ForumId),''), + "AllowRSS" = (SELECT SettingValue FROM {databaseOwner}{objectQualifier}activeforums_Settings WHERE ModuleId = F.ModuleId AND SettingsKey = F.ForumSettingsKey AND SettingName = 'ALLOWRSS'), + P.* + FROM + {databaseOwner}{objectQualifier}activeforums_Groups AS G INNER JOIN + {databaseOwner}{objectQualifier}activeforums_Forums AS F ON G.ForumGroupId = F.ForumGroupId INNER JOIN + {databaseOwner}{objectQualifier}activeforums_Permissions as p ON f.PermissionsId = p.PermissionsId LEFT OUTER JOIN + {databaseOwner}{objectQualifier}activeforums_Topics as t ON t.TopicId = f.LastTopicId LEFT OUTER JOIN + {databaseOwner}{objectQualifier}activeforums_Content as c ON c.ContentId = t.ContentId + + WHERE G.ModuleId = @ModuleId AND (G.Active = 1 AND F.Active = 1) AND (@ParentForumId = -1 OR (@ParentForumId > 0 AND F.ParentForumId = @ParentForumId)) + ORDER BY GroupSort, ForumSort +END +If @UserId > 0 AND @ParentForumId =-1 + BEGIN + SELECT TopicCount, ReplyCount, ViewCount, AnswerCount, RewardPoints, DateLastActivity, + DateLastPost, SignatureDisabled, TrustLevel, AdminWatch, AttachDisabled, PrefDefaultSort, PrefDefaultShowReplies, + PrefJumpLastPost, PrefTopicSubscribe, PrefSubscriptionType, PrefEmailFormat, PrefBlockAvatars, PrefBlockSignatures, PrefPageSize + + FROM {databaseOwner}{objectQualifier}activeforums_UserProfiles WHERE UserId = @UserId AND PortalId = @PortalId + END + + +GO + + +/* activeforums_UI_TopicView -- remove LastPostId */ +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_UI_TopicView]') AND type in (N'P', N'PC')) +DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_UI_TopicView] +GO +CREATE PROCEDURE {databaseOwner}{objectQualifier}activeforums_UI_TopicView +@PortalId int, +@ModuleId int, +@ForumId int, +@TopicId int, +@UserId int, +@RowIndex int, +@MaxRows int, +@IsSuperUser bit = 0, +@Sort varchar(10) = 'ASC' +AS +--Forum/Group/Topic Info +DECLARE @LastPostId int +DECLARE @ReplyCount int +SET @ReplyCount = (Select Count(ReplyId) from {databaseOwner}{objectQualifier}activeforums_Replies WHERE TopicId = @TopicId AND IsDeleted = 0 AND IsApproved = 1) +DECLARE @Tags nvarchar(1000) +SET @Tags= RTRIM(IsNull({databaseOwner}{objectQualifier}activeforums_Topics_GetTags(@TopicId),'')) +BEGIN +SELECT + v.ForumGroupId, + v.ModuleId, + v.GroupName, + v.GroupActive, + v.GroupHidden, + v.ForumId, + v.ParentForumId, + v.ForumName, + v.ForumDesc, + v.ForumActive, + v.ForumHidden, + v.TotalTopics, + ISNULL(v.TotalReplies, 0) AS TotalReplies, + v.GroupSettingsKey, + v.ForumSettingsKey, + TopicTemplateId = IsNull((SELECT SettingValue FROM {databaseOwner}{objectQualifier}activeforums_Settings WHERE SettingName = 'TOPICTEMPLATEID' and SettingsKey = v.ForumSettingsKey),0), + + IsNull((SELECT SettingValue + FROM {databaseOwner}{objectQualifier}activeforums_Settings AS {objectQualifier}activeforums_Settings_1 + WHERE (SettingName = 'ALLOWRSS') AND (SettingsKey = v.ForumSettingsKey)),0) AS AllowRSS, + IsNull((SELECT SettingValue + FROM {databaseOwner}{objectQualifier}activeforums_Settings AS {objectQualifier}activeforums_Settings_3 + WHERE (SettingName = 'ALLOWHTML') AND (SettingsKey = v.ForumSettingsKey)),0) AS AllowHTML, + IsNull((SELECT SettingValue + FROM {databaseOwner}{objectQualifier}activeforums_Settings AS activeforums_Settings_3 + WHERE (SettingName = 'ALLOWLIKES') AND (SettingsKey = v.ForumSettingsKey)),0) AS AllowLikes, + IsNull((SELECT SettingValue + FROM {databaseOwner}{objectQualifier}activeforums_Settings AS {objectQualifier}activeforums_Settings_2 + WHERE (SettingName = 'ALLOWSCRIPT') AND (SettingsKey = v.ForumSettingsKey)),0) AS AllowScript, + IsNull((SELECT SettingValue + FROM {databaseOwner}{objectQualifier}activeforums_Settings + WHERE (SettingName = 'ALLOWTAGS') AND (SettingsKey = v.ForumSettingsKey)),0) AS AllowTags, + FT.TopicId, + (SELECT ISNULL(AVG(Rating), 0) AS Expr1 + FROM {databaseOwner}{objectQualifier}activeforums_Topics_Ratings + WHERE (TopicId = @TopicId)) AS TopicRating, + CASE WHEN FT.LastReplyId is NULL THEN IsNull(T.DateCreated,'') ELSE IsNull(R.DateCreated,'') END AS LastPostDate, + CASE WHEN FT.LastReplyId is NULL THEN IsNull(T.AuthorId,'') ELSE IsNull(R.AuthorId,'') END AS LastPostAuthorId, + CASE WHEN FT.LastReplyId is NULL THEN IsNull(T.AuthorName,'') ELSE IsNull(R.AuthorName,'') END AS LastPostAuthorName, + CASE WHEN FT.LastReplyId is NULL THEN IsNull(T.UserName,'') ELSE IsNull(R.Username,'') END AS LastPostUserName, + CASE WHEN FT.LastReplyId is NULL THEN IsNull(T.FirstName,'') ELSE IsNull(R.FirstName,'') END AS LastPostFirstName, + CASE WHEN FT.LastReplyId is NULL THEN IsNull(T.LastName,'') ELSE IsNull(R.LastName,'') END AS LastPostLastName, + CASE WHEN FT.LastReplyId is NULL THEN IsNull(T.DisplayName,'') ELSE IsNull(R.DisplayName,'') END AS LastPostDisplayName, + T.Subject, T.Summary, T.Body, T.AuthorId, T.AuthorName, T.Username, T.FirstName, T.LastName, + T.DisplayName, T.DateCreated, T.DateUpdated, T.ViewCount, @ReplyCount as ReplyCount, T.IsPinned, T.IsLocked, T.StatusId, T.TopicIcon, T.TopicType, @Tags as Tags,ISNULL(t.TopicData,'') as TopicData, + {databaseOwner}{objectQualifier}activeforums_Poll.PollID, + aft.NextTopic, + aft.PrevTopic, + t.URL, + T.AuthorName as TopicAuthor, + aft.IsAnnounce, aft.AnnounceStart, aft.AnnounceEnd, aft.IsApproved, aft.IsDeleted, aft.IsRejected, aft.IsArchived, aft.IsLocked, aft.IsPinned, aft.TopicIcon, aft.TopicType, aft.Priority, + aft.ContentId, C.IPAddress, + COALESCE((SELECT COUNT(*) + FROM {databaseOwner}{objectQualifier}activeforums_Subscriptions + WHERE (ForumId = @ForumId) AND (TopicId = @TopicId)), 0) AS TopicSubscriberCount, + COALESCE((SELECT COUNT(*) + FROM {databaseOwner}{objectQualifier}activeforums_Subscriptions + WHERE (ForumId = @ForumId) AND (TopicId = 0)), 0) AS ForumSubscriberCount +FROM + {databaseOwner}{objectQualifier}activeforums_Topics aft INNER JOIN + {databaseOwner}{objectQualifier}activeforums_ForumTopics AS FT ON aft.TopicId = FT.TopicId INNER JOIN + {databaseOwner}{objectQualifier}vw_activeforums_GroupForum AS v ON FT.ForumId = v.ForumId INNER JOIN + {databaseOwner}{objectQualifier}vw_activeforums_ForumTopics AS T ON FT.TopicId = T.TopicId LEFT OUTER JOIN + {databaseOwner}{objectQualifier}vw_activeforums_ForumReplies AS R ON FT.LastReplyId = R.ReplyId AND FT.LastReplyId IS NOT NULL LEFT OUTER JOIN + {databaseOwner}{objectQualifier}activeforums_Poll ON T.TopicId = {databaseOwner}{objectQualifier}activeforums_Poll.TopicId + LEFT OUTER JOIN {databaseOwner}{objectQualifier}activeforums_Content AS C ON C.ContentId = aft.ContentId +WHERE (v.ForumActive = 1) AND (v.ModuleId = @ModuleId) AND (v.ForumId = @ForumId) AND (FT.TopicId = @TopicId) +END +--Forum Security +BEGIN + Select p.* from {databaseOwner}{objectQualifier}activeforums_Permissions as p INNER JOIN {databaseOwner}{objectQualifier}activeforums_Forums as f ON f.PermissionsId = p.PermissionsId WHERE f.ForumId = @ForumId + +END +--Get Topic and Replies + SELECT ForumId, TopicId, ReplyId, [Subject], Summary, AuthorId, StatusId, AuthorName, UserName, FirstName, LastName, + DisplayName, DateCreated, DateUpdated, Body, TopicCount, ReplyCount, ViewCount, AnswerCount, + RewardPoints, UserDateCreated, DateLastActivity, UserCaption, [Signature], SignatureDisabled, + UserPostCount, UserTotalPoints,IPAddress,AvatarDisabled,MemberSince, + ContentId,IsUserOnline,ReplyToId, UserRoles = {databaseOwner}{objectQualifier}activeforums_UserProfiles_GetUserRoles(AuthorId, @PortalID, GETUTCDATE(),0),IsApproved, + @Tags as Tags + + FROM +( + SELECT T.ForumId, T.TopicId, T.ReplyId, T.Subject, T.Summary, T.AuthorId, T.StatusId, IsNull(T.AuthorName,'anon') as AuthorName, IsNull(T.Username,IsNull(T.AuthorName,'anon')) as Username, + IsNull(T.FirstName,'') as FirstName, IsNull(T.LastName,'') as LastName, + IsNull(T.DisplayName,T.AuthorName) as DisplayName, + T.DateCreated, T.DateUpdated, C.Body, IsNull(P.TopicCount,0) as TopicCount, IsNull(P.ReplyCount,0) as ReplyCount, + IsNull(P.ViewCount,0) as ViewCount, IsNull(P.AnswerCount,0) as AnswerCount, IsNull(P.RewardPoints,0) as RewardPoints, + IsNull(P.DateCreated,'') AS UserDateCreated, IsNull(P.DateLastActivity,'') as DateLastActivity, + IsNull(P.UserCaption,'') as UserCaption, IsNull(P.Signature,'') as [Signature], IsNull(P.SignatureDisabled,0) as SignatureDisabled, + UserPostCount = (IsNull(P.TopicCount,0) + IsNull(P.ReplyCount,0)), + UserTotalPoints = (IsNull(P.TopicCount,0) + IsNull(P.ReplyCount,0) + IsNull(P.AnswerCount,0) + IsNull(P.RewardPoints,0)), + C.IPAddress, IsNull(P.AvatarDisabled,0) as AvatarDisabled, + IsNull(P.DateCreated,'') as MemberSince, + C.ContentId, IsUserOnline = (CASE WHEN DATEDIFF(mi,p.DateLastActivity,GETUTCDATE()) <=1 THEN 1 ELSE 0 END),T.ReplyToId, + 1 AS IsApproved /* only approved content is returned from vw_activeforums_TopicView */, + ROW_NUMBER() OVER (Order By + CASE + WHEN @Sort = 'DESC' THEN T.DateCreated END DESC, + CASE + WHEN @Sort = 'ASC' THEN T.DateCreated END ASC + ) as RowRank + FROM {databaseOwner}{objectQualifier}vw_activeforums_TopicView AS T INNER JOIN + {databaseOwner}{objectQualifier}activeforums_Content AS C ON T.ContentId = C.ContentId LEFT OUTER JOIN + {databaseOwner}{objectQualifier}activeforums_UserProfiles AS P ON C.AuthorId = P.UserId AND P.PortalId = @PortalId + WHERE (T.TopicId = @TopicId) +) + AS TopicWithRowNumbers + WHERE RowRank > @RowIndex AND RowRank <= (@RowIndex + @MaxRows) + +--Get Attachments +SELECT A.AttachId, A.ContentId, A.UserID, A.[FileName], A.ContentType, A.FileSize, A.FileID +FROM {databaseOwner}{objectQualifier}activeforums_Attachments AS A inner join + {databaseOwner}{objectQualifier}vw_activeforums_TopicView AS T ON A.ContentId = T.ContentId +WHERE (T.TopicId = @TopicId AND (A.AllowDownload = 1 OR A.AllowDownload IS NULL)) + +--Update View Count +UPDATE {databaseOwner}{objectQualifier}activeforums_Topics SET ViewCount = (ViewCount+1) WHERE TopicId = @TopicId +If @UserId > 0 +BEGIN +SELECT @LastPostId = IsNull(LastReplyId,0) FROM {databaseOwner}{objectQualifier}activeforums_ForumTopics WHERE ForumId = @ForumId AND TopicId = @TopicId +exec {databaseOwner}{objectQualifier}activeforums_Forums_Tracking_UpdateUser @ModuleId, @UserId, @ForumId +SET @LastPostId = IsNull(@LastPostId,0) +exec {databaseOwner}{objectQualifier}activeforums_Topics_Tracking_UpdateUser @ForumId, @TopicId, @LastPostId, @UserId +exec {databaseOwner}{objectQualifier}activeforums_UserProfiles_UpdateActivity @PortalId, @UserId +END + +GO + + +/*activeforums_UI_TopicsView */ +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[activeforums_UI_TopicsView]') AND type in (N'P', N'PC')) +DROP PROCEDURE [dbo].[activeforums_UI_TopicsView] +GO +CREATE PROCEDURE [dbo].[activeforums_UI_TopicsView] +@PortalId int, +@ModuleId int, +@ForumId int, +@UserId int, +@RowIndex int = 0, +@MaxRows int = 20, +@IsSuperUser bit = 0, +@SortColumn nvarchar(25) = 'ReplyCreated' +AS +--Forum/Group Info +DECLARE @PrefixURL nvarchar(255) +DECLARE @GroupPrefix nvarchar(255) +SET @GroupPrefix = (SELECT g.PrefixURL from [dbo].activeforums_Groups as g INNER JOIN [dbo].activeforums_Forums as f ON f.ForumGroupId = g.ForumGroupId WHERE f.ForumId=@ForumId) +SET @PrefixURL = (SELECT PRefixURL from [dbo].activeforums_Forums WHERE ForumId = @ForumId) +IF @PrefixURL <> '' OR @PrefixURL IS NOT NULL + SET @PrefixURL = '/' + @PrefixURL + '/' +IF @GroupPrefix <> '' OR @GroupPrefix IS NOT NULL + SET @PrefixURL = '/' + @GroupPrefix + @PrefixURL +BEGIN + SELECT v.ForumName, v.GroupName, v.ForumGroupId, v.ForumDesc, + TopicsTemplateId = IsNull((SELECT SettingValue FROM [dbo].activeforums_Settings WHERE ModuleId = @ModuleId AND SettingName = 'TOPICSTEMPLATEID' and SettingsKey = v.ForumSettingsKey),0), + AllowRSS = IsNull((SELECT SettingValue FROM [dbo].activeforums_Settings WHERE ModuleId = @ModuleId AND SettingName = 'ALLOWRSS' and SettingsKey = v.ForumSettingsKey),0), + TopicRowCount = IsNull((SELECT Count(t.TopicId) FROM [dbo].activeforums_Topics as t inner join [dbo].activeforums_ForumTopics as ft on t.topicid = ft.topicid WHERE ft.ForumId = @ForumId AND t.IsApproved = 1 and t.IsDeleted = 0),0), + IsSubscribedForum = IsNull((SELECT ID FROM [dbo].activeforums_Subscriptions WHERE ModuleId = @ModuleId AND ForumId = @ForumId AND TopicId = 0 AND UserId = @UserId),0), + COALESCE((SELECT COUNT(*) + FROM [dbo].activeforums_Subscriptions + WHERE (ModuleId = @ModuleId) AND (ForumId = @ForumId) AND (TopicId = 0)), 0) AS ForumSubscriberCount + + FROM [dbo].vw_activeforums_GroupForum as v WHERE v.ForumActive = 1 AND v.ModuleId = @ModuleId AND v.ForumId = @ForumId +END +--Forum Security +BEGIN + Select p.* from [dbo].activeforums_Permissions as p INNER JOIN [dbo].activeforums_Forums as f ON f.PermissionsId = p.PermissionsId WHERE f.ModuleId = @ModuleId AND f.ForumId = @ForumId + +END +--Get Sub Forums + exec [dbo].activeforums_UI_ForumView @PortalId, @ModuleId,@UserId,@IsSuperUser, @ForumId + +--Get Topics + +SELECT + ForumId, + LastReplyId, + TopicId, + ContentId, + TopicContentId, + ViewCount, + ReplyCount, + IsLocked, + IsPinned, + IsApproved, + IsDeleted, + IsRejected, + IsArchived, + TopicIcon, + StatusId, + IsAnnounce, + AnnounceStart, + AnnounceEnd, + TopicType, + Priority, + [Subject], + Summary, + AuthorId, + AuthorName, + Body, + DateCreated, + AuthorUserName, + AuthorFirstName, + AuthorLastName, + AuthorDisplayName, + LastReplyContentId, + LastReplySubject, + LastReplySummary, + LastReplyAuthorId, + LastReplyAuthorName, + LastReplyUserName, + LastReplyFirstName, + LastReplyLastName, + LastReplyDisplayName, + LastReplyDate, + TopicRating, + UserLastReplyRead, + UserLastTopicRead, + TopicURL, + TopicData, + FullURL, + TopicSubscriberCount, + ForumSubscriberCount + FROM ( + +SELECT + f.ForumId, + IsNull(f.LastReplyId,0) as LastReplyId, + t.TopicId, + CASE WHEN rc.ContentId IS NULL THEN c.ContentId ELSE rc.ContentId END as ContentId, + t.ContentId as TopicContentId, + t.ViewCount, + t.ReplyCount, + t.IsLocked, + t.IsPinned, + t.IsApproved, + t.IsDeleted, + t.IsRejected, + t.IsArchived, + IsNull(t.TopicIcon,'') as TopicIcon, + t.StatusId, + t.IsAnnounce, + t.AnnounceStart, + t.AnnounceEnd, + t.TopicType, + t.Priority, + c.Subject, + IsNull(c.Summary,'') as Summary, + IsNull(c.AuthorId,-1) as AuthorId, + IsNull(c.AuthorName,'') as AuthorName, + c.Body, + c.DateCreated, + IsNull(u.Username,'') as AuthorUserName, + IsNull(u.FirstName,'') as AuthorFirstName, + IsNull(u.LastName,'') as AuthorLastName, + IsNull(u.DisplayName,'') as AuthorDisplayName, + CASE WHEN rc.ContentId IS NULL THEN c.ContentId ELSE rc.ContentId END as LastReplyContentId, + CASE WHEN rc.Subject IS NULL THEN c.Subject ELSE rc.Subject END as LastReplySubject, + CASE WHEN rc.Summary IS NULL THEN IsNull(c.Summary,'') ELSE rc.Summary END as LastReplySummary, + CASE WHEN rc.AuthorId IS NULL THEN c.AuthorId ELSE rc.AuthorId END as LastReplyAuthorId, + CASE WHEN rc.AuthorName IS NULL THEN IsNull(c.AuthorName,'') ELSE rc.AuthorName END as LastReplyAuthorName, + CASE WHEN ru.Username IS NULL THEN IsNull(u.UserName,'') ELSE ru.UserName END as LastReplyUserName, + CASE WHEN ru.FirstName IS NULL THEN IsNULL(u.FirstName,'') ELSE ru.FirstName END as LastReplyFirstName, + CASE WHEN ru.LastName IS NULL THEN IsNull(u.LastName,'') ELSE ru.LastName END as LastReplyLastName, + CASE WHEN ru.DisplayName IS NULL THEN IsNull(IsNull(u.DisplayName,rc.AuthorName),'') ELSE ru.DisplayName END as LastReplyDisplayName, + CASE WHEN rc.DateCreated IS NULL THEN c.DateCreated ELSE rc.DateCreated END as LastReplyDate, + CASE WHEN FT.MaxReplyRead > TT.LastReplyId OR TT.LastReplyID IS NULL THEN ISNULL(FT.MaxReplyRead,0) ELSE TT.LastReplyId END AS UserLastReplyRead, + CASE WHEN FT.MaxTopicRead > TT.TopicId OR TT.TopicId IS NULL THEN ISNULL(FT.MaxTopicRead,0) ELSE TT.TopicId END AS UserLastTopicRead, + t.URL as TopicURL, + IsNull(t.TopicData,'') as TopicData, + CASE WHEN ISNULL(t.URL,'') <> '' THEN @PrefixURL + t.URL ELSE '' END as FullURL, + (SELECT ISNULL(AVG(Rating), 0) AS Expr1 + FROM [dbo].activeforums_Topics_Ratings + WHERE (TopicId = T.TopicId)) AS TopicRating, + ROW_NUMBER() OVER (ORDER BY T.IsPinned DESC, T.Priority DESC, + CASE + WHEN @SortColumn = 'ReplyCreated' THEN + CASE WHEN rc.DateCreated IS NULL THEN c.DateCreated ELSE rc.DateCreated END + WHEN @SortColumn = 'TopicCreated' THEN + c.DateCreated + END DESC) as RowRank, + COALESCE((SELECT COUNT(*) + FROM [dbo].activeforums_Subscriptions + WHERE (ModuleId = @ModuleId) AND (ForumId = @ForumId) AND (TopicId = T.TopicId)), 0) AS TopicSubscriberCount, + COALESCE((SELECT COUNT(*) + FROM [dbo].activeforums_Subscriptions + WHERE (ModuleId = @ModuleId) AND (ForumId = @ForumId) AND (TopicId = 0)), 0) AS ForumSubscriberCount + + FROM [dbo].activeforums_ForumTopics AS f INNER JOIN + [dbo].activeforums_Topics as t on f.TopicId = t.TopicId INNER JOIN + [dbo].activeforums_Content as c on t.ContentId = c.ContentId LEFT OUTER JOIN + [dbo].Users as u on c.AuthorId = u.UserId LEFT OUTER JOIN + [dbo].activeforums_Replies as r on f.LastReplyId = r.ReplyId LEFT OUTER JOIN + [dbo].activeforums_Content as rc on r.ContentId = rc.ContentId LEFT OUTER JOIN + [dbo].Users as ru on rc.AuthorId = ru.UserId LEFT OUTER JOIN + [dbo].activeforums_Topics_Tracking AS TT ON T.TopicId = TT.TopicId AND TT.UserId = @UserId LEFT OUTER JOIN + [dbo].activeforums_Forums_Tracking as FT ON f.ForumId = FT.ForumId AND FT.UserId = @UserId + + WHERE (f.ForumId = @ForumId AND t.IsApproved = 1 AND t.IsDeleted = 0) + ) AS TopicsWithRowNumbers + WHERE RowRank > @RowIndex AND RowRank <= (@RowIndex + @MaxRows) + IF @RowIndex = 0 + BEGIN + SELECT + f.ForumId, + IsNull(f.LastReplyId,0) as LastReplyId, + t.TopicId, + CASE WHEN rc.ContentId IS NULL THEN c.ContentId ELSE rc.ContentId END as ContentId, + t.ContentId AS TopicContentId, + t.ViewCount, + t.ReplyCount, + t.IsLocked, + t.IsPinned, + t.IsApproved, + t.IsDeleted, + t.IsRejected, + t.IsArchived, + IsNull(t.TopicIcon,'') as TopicIcon, + t.StatusId, + t.IsAnnounce, + t.AnnounceStart, + t.AnnounceEnd, + t.TopicType, + t.Priority, + c.Subject, + IsNull(c.Summary,'') as Summary, + IsNull(c.AuthorId,-1) as AuthorId, + IsNull(c.AuthorName,'') as AuthorName, + c.Body, + c.DateCreated, + IsNull(u.Username,'') as AuthorUserName, + IsNull(u.FirstName,'') as AuthorFirstName, + IsNull(u.LastName,'') as AuthorLastName, + IsNull(u.DisplayName,'') as AuthorDisplayName, + CASE WHEN rc.ContentId IS NULL THEN c.ContentId ELSE rc.ContentId END as LastReplyContentId, + CASE WHEN rc.Subject IS NULL THEN c.Subject ELSE rc.Subject END as LastReplySubject, + CASE WHEN rc.Summary IS NULL THEN IsNull(c.Summary,'') ELSE rc.Summary END as LastReplySummary, + CASE WHEN rc.AuthorId IS NULL THEN c.AuthorId ELSE rc.AuthorId END as LastReplyAuthorId, + CASE WHEN rc.AuthorName IS NULL THEN IsNull(c.AuthorName,'') ELSE rc.AuthorName END as LastReplyAuthorName, + CASE WHEN ru.Username IS NULL THEN IsNull(u.UserName,'') ELSE ru.UserName END as LastReplyUserName, + CASE WHEN ru.FirstName IS NULL THEN IsNULL(u.FirstName,'') ELSE ru.FirstName END as LastReplyFirstName, + CASE WHEN ru.LastName IS NULL THEN IsNull(u.LastName,'') ELSE ru.LastName END as LastReplyLastName, + CASE WHEN ru.DisplayName IS NULL THEN IsNull(IsNull(u.DisplayName,rc.AuthorName),'') ELSE ru.DisplayName END as LastReplyDisplayName, + CASE WHEN rc.DateCreated IS NULL THEN c.DateCreated ELSE rc.DateCreated END as LastReplyDate, + CASE WHEN FT.MaxReplyRead > TT.LastReplyId OR TT.LastReplyID IS NULL THEN ISNULL(FT.MaxReplyRead,0) ELSE TT.LastReplyId END AS UserLastReplyRead, + CASE WHEN FT.MaxTopicRead > TT.TopicId OR TT.TopicId IS NULL THEN ISNULL(FT.MaxTopicRead,0) ELSE TT.TopicId END AS UserLastTopicRead, + t.URL as TopicURL, + IsNull(t.TopicData,'') as TopicData, + CASE WHEN ISNULL(t.URL,'') <> '' THEN @PrefixURL + t.URL ELSE '' END as FullURL, + (SELECT ISNULL(AVG(Rating), 0) AS Expr1 + FROM [dbo].activeforums_Topics_Ratings + WHERE (TopicId = T.TopicId)) AS TopicRating, + ROW_NUMBER() OVER (ORDER BY T.IsPinned DESC, + CASE + WHEN rc.DateCreated IS NULL THEN c.DateCreated ELSE rc.DateCreated END DESC + ) as RowRank, + COALESCE((SELECT COUNT(*) + FROM [dbo].activeforums_Subscriptions + WHERE (ModuleId = @ModuleId) AND (ForumId = @ForumId) AND (TopicId = T.TopicId)), 0) AS TopicSubscriberCount, + COALESCE((SELECT COUNT(*) + FROM [dbo].activeforums_Subscriptions + WHERE (ModuleId = @ModuleId) AND (ForumId = @ForumId) AND (TopicId = 0)), 0) AS ForumSubscriberCount + + FROM [dbo].activeforums_ForumTopics AS f INNER JOIN + [dbo].activeforums_Topics as t on f.TopicId = t.TopicId INNER JOIN + [dbo].activeforums_Content as c on t.ContentId = c.ContentId LEFT OUTER JOIN + [dbo].Users as u on c.AuthorId = u.UserId LEFT OUTER JOIN + [dbo].activeforums_Replies as r on f.LastReplyId = r.ReplyId LEFT OUTER JOIN + [dbo].activeforums_Content as rc on r.ContentId = rc.ContentId LEFT OUTER JOIN + [dbo].Users as ru on rc.AuthorId = ru.UserId LEFT OUTER JOIN + [dbo].activeforums_Topics_Tracking AS TT ON T.TopicId = TT.TopicId AND TT.UserId = @UserId LEFT OUTER JOIN + [dbo].activeforums_Forums_Tracking as FT ON f.ForumId = FT.ForumId AND FT.UserId = @UserId + + WHERE (f.ForumId = @ForumId AND t.IsApproved = 1 AND t.IsDeleted = 0 AND T.IsAnnounce = 1 AND T.AnnounceStart <= GETUTCDATE() AND T.AnnounceEnd >= GETUTCDATE()) + ORDER BY T.IsPinned DESC, c.DateCreated DESC, rc.DateCreated DESC + END +BEGIN +If @UserId > 0 + BEGIN + exec [dbo].activeforums_Forums_Tracking_UpdateUser @ModuleId, @UserId, @ForumId + exec [dbo].activeforums_UserProfiles_UpdateActivity @PortalId, @UserId + END +END + +GO + +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Subscriptions_Subscribers]') AND type in (N'P', N'PC')) +DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Subscriptions_Subscribers] +GO + +CREATE PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Subscriptions_Subscribers](@PortalId int, @ForumId int, @TopicId int, @SubType int) +AS + +DECLARE @CanSubscribe nvarchar(256) +SET @CanSubscribe = ( + SELECT p.CanSubscribe + FROM {databaseOwner}{objectQualifier}activeforums_Forums as f + INNER JOIN {databaseOwner}{objectQualifier}activeforums_Permissions as p + ON p.PermissionsId = f.PermissionsId + WHERE f.ForumId = @ForumId + ) + +DECLARE @subs TABLE (userid int, email nvarchar(255), topicsubscriber bit) + +/* get topic subscribers who are not superusers so need to check against roles allowed to be subscribers */ +INSERT INTO @subs + (userid, email, topicsubscriber) + (SELECT s.UserId, u.Email, 1 AS topicsubscriber + FROM {databaseOwner}{objectQualifier}activeforums_Subscriptions AS s + INNER JOIN {databaseOwner}{objectQualifier}activeforums_Forums AS f + ON f.ForumId = s.ForumId + INNER JOIN {databaseOwner}{objectQualifier}Users AS u + ON u.UserID = s.UserId + AND u.IsSuperUser = 0 + AND u.IsDeleted = 0 + INNER JOIN {databaseOwner}{objectQualifier}UserPortals AS up + ON up.UserId = u.UserID + AND up.PortalId = @PortalId + AND up.IsDeleted = 0 + AND up.Authorised = 1 + INNER JOIN {databaseOwner}{objectQualifier}UserRoles AS ur + ON ur.UserID = u.UserID + AND ( + (ur.EffectiveDate IS NULL AND ur.ExpiryDate >= GETDATE()) /* DNN platform user roles still use native GETDATE() not GETUTCDATE() */ + OR (ur.EffectiveDate IS NULL AND ur.ExpiryDate IS NULL) + OR (ur.EffectiveDate <= GETDATE() AND ur.ExpiryDate IS NULL) + OR (ur.EffectiveDate <= GETDATE() AND ur.ExpiryDate >= GETDATE()) + ) + INNER JOIN {databaseOwner}{objectQualifier}activeforums_Functions_Split(@CanSubscribe,';') AS r + ON r.ID = ur.RoleId + WHERE (s.Mode = @SubType) + AND (s.TopicId = @TopicId) + AND (NOT EXISTS (SELECT * FROM @subs WHERE userid = s.UserId)) + ) + +/* get forum subscribers who are not superusers so need to check against roles allowed to be subscribers */ +INSERT INTO @subs + (userid, email, topicsubscriber) + (SELECT s.UserId, u.Email, 0 AS topicsubscriber + FROM {databaseOwner}{objectQualifier}activeforums_Subscriptions AS s + INNER JOIN {databaseOwner}{objectQualifier}activeforums_Forums AS f + ON f.ForumId = s.ForumId + INNER JOIN {databaseOwner}{objectQualifier}Users AS u + ON u.UserID = s.UserId + AND u.IsSuperUser = 0 + AND u.IsDeleted = 0 + INNER JOIN {databaseOwner}{objectQualifier}UserPortals AS up + ON up.UserId = u.UserID + AND up.PortalId = @PortalId + AND up.IsDeleted = 0 + AND up.Authorised = 1 + INNER JOIN {databaseOwner}{objectQualifier}UserRoles AS ur + ON ur.UserID = u.UserID + AND ( + (ur.EffectiveDate IS NULL AND ur.ExpiryDate >= GETDATE()) /* DNN platform user roles still use native GETDATE() not GETUTCDATE() */ + OR (ur.EffectiveDate IS NULL AND ur.ExpiryDate IS NULL) + OR (ur.EffectiveDate <= GETDATE() AND ur.ExpiryDate IS NULL) + OR (ur.EffectiveDate <= GETDATE() AND ur.ExpiryDate >= GETDATE()) + ) + INNER JOIN {databaseOwner}{objectQualifier}activeforums_Functions_Split(@CanSubscribe,';') AS r + ON r.ID = ur.RoleId + WHERE (s.Mode = @SubType) + AND (S.ForumId = @ForumId AND S.TopicId = 0) + AND (NOT EXISTS (SELECT * FROM @subs WHERE userid = s.UserId)) + ) + + +/* get topic subscribers who are superusers */ +INSERT INTO @subs + (userid, email, topicsubscriber) + (SELECT s.UserId, u.Email, 1 AS topicsubscriber + FROM {databaseOwner}{objectQualifier}activeforums_Subscriptions AS s + INNER JOIN {databaseOwner}{objectQualifier}activeforums_Forums AS f + ON f.ForumId = s.ForumId + INNER JOIN {databaseOwner}{objectQualifier}Users AS u + ON u.UserID = s.UserId + AND u.IsSuperUser = 1 + AND u.IsDeleted = 0 + INNER JOIN {databaseOwner}{objectQualifier}UserPortals AS up + ON up.UserId = u.UserID + AND up.PortalId = @PortalId + AND up.IsDeleted = 0 + AND up.Authorised = 1 + WHERE (s.Mode = @SubType) + AND (s.TopicId = @TopicId) + AND (NOT EXISTS (SELECT * FROM @subs WHERE userid = s.UserId)) + ) + +/* get forum subscribers who are superusers */ +INSERT INTO @subs + (userid, email, topicsubscriber) + (SELECT s.UserId, u.Email, 0 AS topicsubscriber + FROM {databaseOwner}{objectQualifier}activeforums_Subscriptions AS s + INNER JOIN {databaseOwner}{objectQualifier}activeforums_Forums AS f + ON f.ForumId = s.ForumId + INNER JOIN {databaseOwner}{objectQualifier}Users AS u + ON u.UserID = s.UserId + AND u.IsSuperUser = 1 + AND u.IsDeleted = 0 + INNER JOIN {databaseOwner}{objectQualifier}UserPortals AS up + ON up.UserId = u.UserID + AND up.PortalId = @PortalId + AND up.IsDeleted = 0 + AND up.Authorised = 1 + WHERE (s.Mode = @SubType) + AND (S.ForumId = @ForumId AND S.TopicId = 0) + AND (NOT EXISTS (SELECT * FROM @subs WHERE userid = s.UserId)) + ) + +/* get auto subscriptions based on roles */ +DECLARE @AutoSubscribe bit +DECLARE @AutoSubscribeRoles nvarchar(255) +DECLARE @TopicsOnly bit +DECLARE @IsNewTopic bit +SET @AutoSubscribe = IsNull((SELECT SettingValue FROM {databaseOwner}{objectQualifier}activeforums_Settings as S INNER JOIN {databaseOwner}{objectQualifier}activeforums_Forums as F ON F.ForumSettingsKey = S.SettingsKey WHERE S.SettingName = 'AUTOSUBSCRIBEENABLED' AND F.ForumId = @ForumId),0) +SET @AutoSubscribeRoles = IsNull((SELECT SettingValue FROM {databaseOwner}{objectQualifier}activeforums_Settings as S INNER JOIN {databaseOwner}{objectQualifier}activeforums_Forums as F ON F.ForumSettingsKey = S.SettingsKey WHERE S.SettingName = 'AUTOSUBSCRIBEROLES' AND F.ForumId = @ForumId),'') +SET @TopicsOnly = IsNull((SELECT SettingValue FROM {databaseOwner}{objectQualifier}activeforums_Settings as S INNER JOIN {databaseOwner}{objectQualifier}activeforums_Forums as F ON F.ForumSettingsKey = S.SettingsKey WHERE S.SettingName = 'AUTOSUBSCRIBENEWTOPICSONLY' AND F.ForumId = @ForumId),0) +SET @IsNewTopic = 0 +IF (SELECT ReplyCount FROM {databaseOwner}{objectQualifier}activeforums_Topics WHERE TopicId = @TopicId) > 0 + SET @IsNewTopic = 1 + +If (@TopicsOnly = 1 AND @IsNewTopic = 0) OR (@TopicsOnly = 0) + BEGIN + IF @AutoSubscribe = 1 AND @AutoSubscribeRoles <> '' + BEGIN + + INSERT INTO @subs + (userid, email, topicsubscriber) + (SELECT u.UserID, u.Email, 0 AS topicsubscriber /*auto subscribers are never topic-specific subscribers */ + FROM {databaseOwner}{objectQualifier}Users AS u + INNER JOIN {databaseOwner}{objectQualifier}UserPortals AS up + ON up.UserId = u.UserID + AND up.PortalId = @PortalId + AND up.IsDeleted = 0 + AND up.Authorised = 1 + INNER JOIN {databaseOwner}{objectQualifier}UserRoles AS ur + ON ur.UserID = u.UserID + AND ( + (ur.EffectiveDate IS NULL AND ur.ExpiryDate >= GETDATE()) /* DNN platform user roles still use native GETDATE() not GETUTCDATE() */ + OR (ur.EffectiveDate IS NULL AND ur.ExpiryDate IS NULL) + OR (ur.EffectiveDate <= GETDATE() AND ur.ExpiryDate IS NULL) + OR (ur.EffectiveDate <= GETDATE() AND ur.ExpiryDate >= GETDATE()) + ) + INNER JOIN {databaseOwner}{objectQualifier}activeforums_Functions_Split(@AutoSubscribeRoles,';') AS r + ON r.ID = ur.RoleId + WHERE (u.IsDeleted = 0) + AND (NOT EXISTS (SELECT * FROM @subs WHERE userid = u.UserID)) + ) + + END + END + +/* return the results */ +SELECT DISTINCT userid, email, topicsubscriber FROM @subs +GO + + + +/* activeforums_Forums_List */ +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Forums_List]') AND type in (N'P', N'PC')) +DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Forums_List] +GO +CREATE PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Forums_List] +@ModuleId int, +@ForumGroupId int, +@ParentForumId int, +@FillLastPost bit +AS +IF @ForumGroupId = -1 AND @ParentForumId = -1 AND @FillLastPost = 0 + --Return all Forums +SELECT IsNull(F.ForumId,-1) as ForumId, G.ModuleId, G.ForumGroupId, IsNull(F.ParentForumId,'-1') as ParentForumId, IsNull(F.ForumName,'') as ForumName, F.ForumDesc, F.SortOrder, F.Active, F.Hidden, F.TotalTopics, + F.TotalReplies, F.LastTopicId, F.LastReplyId, F.ForumSettingsKey, G.GroupName, ISNULL(P.ForumName, '') AS ParentForumName, + TopicsTemplateId = IsNull((SELECT SettingValue FROM {databaseOwner}{objectQualifier}activeforums_Settings WHERE SettingName = 'TOPICSTEMPLATEID' and SettingsKey = F.ForumSettingsKey),0), + TopicTemplateId = IsNull((SELECT SettingValue FROM {databaseOwner}{objectQualifier}activeforums_Settings WHERE SettingName = 'TOPICTEMPLATEID' and SettingsKey = F.ForumSettingsKey),0) +FROM {databaseOwner}{objectQualifier}activeforums_Forums AS F RIGHT OUTER JOIN + {databaseOwner}{objectQualifier}activeforums_Groups AS G ON F.ForumGroupId = G.ForumGroupId LEFT OUTER JOIN + {databaseOwner}{objectQualifier}activeforums_Forums AS P ON F.ParentForumId = P.ForumId +WHERE (G.ModuleId = @ModuleId) +ORDER BY G.SortOrder, F.SortOrder + +ELSE + IF @ForumGroupId > 0 AND @ParentForumId = -1 AND @FillLastPost = 0 + --Return Forums in Group + SELECT F.ForumId, F.ModuleId, F.ForumGroupId, F.ParentForumId, F.ForumName, F.ForumDesc, F.SortOrder, F.Active, F.Hidden, F.TotalTopics, + F.TotalReplies, F.LastTopicId, F.LastReplyId, F.ForumSettingsKey, G.GroupName, ISNULL(P.ForumName, '') AS ParentForumName, + TopicsTemplateId = IsNull((SELECT SettingValue FROM {databaseOwner}{objectQualifier}activeforums_Settings WHERE SettingName = 'TOPICSTEMPLATEID' and SettingsKey = F.ForumSettingsKey),0), + TopicTemplateId = IsNull((SELECT SettingValue FROM {databaseOwner}{objectQualifier}activeforums_Settings WHERE SettingName = 'TOPICTEMPLATEID' and SettingsKey = F.ForumSettingsKey),0) + FROM {databaseOwner}{objectQualifier}activeforums_Forums AS F INNER JOIN + {databaseOwner}{objectQualifier}activeforums_Groups AS G ON F.ForumGroupId = G.ForumGroupId LEFT OUTER JOIN + {databaseOwner}{objectQualifier}activeforums_Forums AS P ON F.ParentForumId = P.ForumId + WHERE F.ModuleId = @ModuleId AND F.ForumGroupId = @ForumGroupId + ORDER By F.SortOrder + ELSE + If @ForumGroupId > 0 AND @ParentForumId > 0 AND @FillLastPost = 0 + --Return Sub Forums + + SELECT F.ForumId, F.ModuleId, F.ForumGroupId, F.ParentForumId, F.ForumName, F.ForumDesc, F.SortOrder, F.Active, F.Hidden, F.TotalTopics, + F.TotalReplies, F.LastTopicId, F.LastReplyId, F.ForumSettingsKey, G.GroupName, ISNULL(P.ForumName, '') AS ParentForumName, + TopicsTemplateId = IsNull((SELECT SettingValue FROM {databaseOwner}{objectQualifier}activeforums_Settings WHERE SettingName = 'TOPICSTEMPLATEID' and SettingsKey = F.ForumSettingsKey),0), + TopicTemplateId = IsNull((SELECT SettingValue FROM {databaseOwner}{objectQualifier}activeforums_Settings WHERE SettingName = 'TOPICTEMPLATEID' and SettingsKey = F.ForumSettingsKey),0) + FROM {databaseOwner}{objectQualifier}activeforums_Forums AS F INNER JOIN + {databaseOwner}{objectQualifier}activeforums_Groups AS G ON F.ForumGroupId = G.ForumGroupId LEFT OUTER JOIN + {databaseOwner}{objectQualifier}activeforums_Forums AS P ON F.ParentForumId = P.ForumId + WHERE F.ModuleId = @ModuleId AND F.ParentForumId = @ParentForumId + ORDER By G.SortOrder, F.SortOrder + ELSE + ---Returns Forums In Group with Last Post Info +SELECT F.ForumId, F.ModuleId, F.ForumGroupId, F.ParentForumId, F.ForumName, F.ForumDesc, F.SortOrder, F.Active, F.Hidden, F.TotalTopics, + F.TotalReplies, F.LastTopicId, F.LastReplyId, F.ForumSettingsKey, G.GroupName, ISNULL(P.ForumName, '') AS ParentForumName, ISNULL(U.FirstName, '') + AS LastPostFirstName, ISNULL(U.LastName, '') AS LastPostLastName, ISNULL(C.AuthorId, - 1) AS LastPostUserId, ISNULL(C.AuthorName, '') AS LastPostUserName, + C.Subject AS LastPostSubject, C.DateCreated AS LastPostDateTime, + TopicsTemplateId = IsNull((SELECT SettingValue FROM {databaseOwner}{objectQualifier}activeforums_Settings WHERE SettingName = 'TOPICSTEMPLATEID' and SettingsKey = F.ForumSettingsKey),0), + TopicTemplateId = IsNull((SELECT SettingValue FROM {databaseOwner}{objectQualifier}activeforums_Settings WHERE SettingName = 'TOPICTEMPLATEID' and SettingsKey = F.ForumSettingsKey),0) +FROM {databaseOwner}{objectQualifier}activeforums_Content AS C INNER JOIN + {databaseOwner}{objectQualifier}activeforums_Topics AS T ON C.ContentId = T.ContentId INNER JOIN + {databaseOwner}{objectQualifier}activeforums_UserProfiles AS UD INNER JOIN + {databaseOwner}{objectQualifier}Users AS U ON UD.UserID = U.UserID ON C.AuthorId = UD.UserID RIGHT OUTER JOIN + {databaseOwner}{objectQualifier}activeforums_Forums AS F INNER JOIN + {databaseOwner}{objectQualifier}activeforums_Groups AS G ON F.ForumGroupId = G.ForumGroupId ON T.TopicId = F.LastTopicId LEFT OUTER JOIN + {databaseOwner}{objectQualifier}activeforums_Forums AS P ON F.ParentForumId = P.ForumId +WHERE (F.ModuleId = @ModuleId) AND (F.ForumGroupId = @ForumGroupId) +ORDER BY G.SortOrder, F.SortOrder +GO + +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_MC_Forums]') AND type in (N'P', N'PC')) +DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_MC_Forums] +GO +CREATE PROCEDURE {databaseOwner}[{objectQualifier}activeforums_MC_Forums] +AS +DECLARE @SettingName nvarchar(100) +DECLARE @SettingValue nvarchar(100) +SET @SettingName = 'MCENABLED' +SET @SettingValue = 'true' +DECLARE @MailForums table (forumid int) +INSERT INTO @MailForums(forumid) +Select f.ForumId From {databaseOwner}{objectQualifier}activeforums_Forums as F + INNER JOIN {databaseOwner}{objectQualifier}Modules as M ON F.ModuleId = M.ModuleId + INNER JOIN {databaseOwner}{objectQualifier}activeforums_Settings as S ON S.SettingsKey = F.ForumSettingsKey +WHERE M.IsDeleted = 0 AND F.Active = 1 AND S.SettingValue = @SettingValue + +SELECT *, TM.TabId from {databaseOwner}{objectQualifier}activeforums_Forums as F INNER JOIN @MailForums as M ON M.forumid = F.ForumId + INNER JOIN {databaseOwner}{objectQualifier}TabModules as TM ON F.ModuleId = TM.ModuleId +GO + + + +/* activeforums_Forum_ConfigCleanUp */ +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}{objectQualifier}activeforums_Forum_ConfigCleanUp') AND type in (N'P', N'PC')) +DROP PROCEDURE {databaseOwner}{objectQualifier}activeforums_Forum_ConfigCleanUp +GO +CREATE PROCEDURE {databaseOwner}{objectQualifier}activeforums_Forum_ConfigCleanUp +@ModuleId int, +@ForumSettingsKey nvarchar(25) +AS +DELETE FROM {databaseOwner}{objectQualifier}activeforums_Settings WHERE SettingsKey = @ForumSettingsKey AND ModuleId = @ModuleId +GO + + + +/* begin: activeforums_Search_GetSearchItemsFromBegDate */ +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Search_GetSearchItemsFromBegDate]') AND type in (N'P', N'PC')) +DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Search_GetSearchItemsFromBegDate] +GO + +CREATE PROCEDURE {databaseOwner}{objectQualifier}activeforums_Search_GetSearchItemsFromBegDate(@ModuleId int, @beginDateUtc datetime) +AS +SELECT F.ForumGroupId, FT.ForumId, X.TopicId, X.ReplyId, X.ContentId, X.DateCreated, X.DateUpdated, X.Summary, X.Subject, X.AuthorId, X.Body , X.IsDeleted, X.IsApproved, +RTRIM(IsNull([dbo].activeforums_Topics_GetTags(X.TopicId),'')) AS Tags, X.TopicURL, F.PrefixURL AS ForumUrlPrefix, G.PrefixURL AS ForumGroupUrlPrefix +FROM +( +SELECT +T.TopicId, -1 AS ReplyId, C.ContentId, C.DateCreated, C.DateUpdated, C.Summary, C.Subject, C.AuthorId, C.Body, T.IsDeleted, T.IsApproved, T.URL AS TopicUrl +FROM {databaseOwner}{objectQualifier}activeforums_Topics T +INNER JOIN {databaseOwner}{objectQualifier}activeforums_Content C ON C.ContentId = T.ContentId +WHERE C.DateUpdated BETWEEN @beginDateUtc AND GETUTCDATE() +UNION +SELECT +R.TopicId, R.ReplyId, C.ContentId, C.DateCreated, C.DateUpdated, C.Summary, C.Subject, C.AuthorId, C.Body, R.IsDeleted, R.IsApproved, T.URL AS TopicUrl +FROM {databaseOwner}{objectQualifier}activeforums_Replies R +INNER JOIN {databaseOwner}{objectQualifier}activeforums_Content C ON C.ContentId = R.ContentId +LEFT OUTER JOIN {databaseOwner}{objectQualifier}activeforums_Topics T ON T.TopicId = R.TopicId +WHERE C.DateUpdated BETWEEN @beginDateUtc AND GETUTCDATE() +) X +INNER JOIN {databaseOwner}{objectQualifier}activeforums_Topics T ON T.TopicId = X.TopicId +INNER JOIN {databaseOwner}{objectQualifier}activeforums_ForumTopics FT ON FT.TopicId = T.TopicId +INNER JOIN {databaseOwner}{objectQualifier}activeforums_Forums F ON F.ForumId = FT.ForumId +INNER JOIN {databaseOwner}{objectQualifier}activeforums_Groups G ON G.ForumGroupId = F.ForumGroupId +INNER JOIN {databaseOwner}{objectQualifier}activeforums_settings S ON S.SettingsKey = F.ForumSettingsKey AND S.SettingName = 'INDEXCONTENT' +WHERE F.Active = 1 AND S.SettingValue = 'true' AND F.ModuleId = @ModuleId +GO + + +/* activeforums_Settings_Delete */ +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Settings_Delete]') AND type in (N'P', N'PC')) +DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Settings_Delete] +GO +CREATE PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Settings_Delete] +( + @ModuleId int, + @SettingsKey nvarchar(25), + @SettingName nvarchar(50) +) +AS +DELETE FROM {databaseOwner}[{objectQualifier}activeforums_Settings] WHERE ModuleId = @ModuleId AND SettingName = @SettingName AND SettingsKey = @SettingsKey +GO + +/* activeforums_Settings_Save */ +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Settings_Save]') AND type in (N'P', N'PC')) +DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Settings_Save] +GO +CREATE PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Settings_Save] +( + @ModuleId int, + @SettingsKey nvarchar(25), + @SettingName nvarchar(50), + @SettingValue nvarchar(2000) +) +AS +If EXISTS(SELECT SettingName FROM {databaseOwner}[{objectQualifier}activeforums_Settings] WHERE ModuleId = @ModuleId AND SettingName = @SettingName AND SettingsKey = @SettingsKey) + BEGIN + UPDATE {databaseOwner}[{objectQualifier}activeforums_Settings] + SET SettingValue = @SettingValue + WHERE ModuleId = @ModuleId AND SettingName = @SettingName AND SettingsKey = @SettingsKey + END +ELSE + INSERT INTO {databaseOwner}[{objectQualifier}activeforums_Settings] + (ModuleId, SettingsKey, SettingName, SettingValue) + VALUES + (@ModuleId, @SettingsKey, @SettingName, @SettingValue) + +GO + +/* activeforums_Settings_Delete */ +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Settings_Get]') AND type in (N'P', N'PC')) +DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Settings_Get] +GO +CREATE PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Settings_Get] +( + @ModuleId int, + @SettingsKey nvarchar(25), + @SettingName nvarchar(50) +) +AS +SELECT SettingValue FROM {databaseOwner}[{objectQualifier}activeforums_Settings] WHERE ModuleId = @ModuleId AND SettingName = @SettingName AND SettingsKey = @SettingsKey +GO + +/* activeforums_Settings_List */ +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Settings_List]') AND type in (N'P', N'PC')) +DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Settings_List] +GO +CREATE PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Settings_List] +( + @ModuleId int, + @SettingsKey nvarchar(25) +) +AS +SELECT SettingName, SettingValue FROM {databaseOwner}{objectQualifier}activeforums_Settings +WHERE ModuleId = @ModuleId AND SettingsKey = @SettingsKey +GO + + +/* activeforums_Settings_ListAll */ +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Settings_ListAll]') AND type in (N'P', N'PC')) +DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Settings_ListAll] +GO +CREATE PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Settings_ListAll] + @ModuleId INT + +AS +SELECT SettingName , + SettingValue, + SettingsKey +FROM {databaseOwner}{objectQualifier}activeforums_Settings +WHERE ModuleId = @ModuleId +GO + + + +/*drop activeforums_ForumsList*/ +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_ForumsList]') AND type in (N'P', N'PC')) +DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_ForumsList] +GO + +/* drop activeforums_SettingsTable */ +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_SettingsTable]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT')) +DROP FUNCTION {databaseOwner}[{objectQualifier}activeforums_SettingsTable] +GO + + +/* issue 1582 - end - settings table overhaul */ + +/* --------------------- */ diff --git a/Dnn.CommunityForums/sql/Uninstall.SqlDataProvider b/Dnn.CommunityForums/sql/Uninstall.SqlDataProvider index eccf8e190..3d8f14183 100644 --- a/Dnn.CommunityForums/sql/Uninstall.SqlDataProvider +++ b/Dnn.CommunityForums/sql/Uninstall.SqlDataProvider @@ -492,11 +492,11 @@ GO IF EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}vw_activeforums_TopicRatings]')) DROP VIEW {databaseOwner}[{objectQualifier}vw_activeforums_TopicRatings] GO -IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'{databaseOwner}{objectQualifier}activeforums_Settings') AND name = N'idx_{objectQualifier}activeforums_Settings_Opt1') -DROP INDEX [idx_{objectQualifier}activeforums_Settings_Opt1] ON {databaseOwner}{objectQualifier}activeforums_Settings +IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'{databaseOwner}{objectQualifier}activeforums_Settings') AND name = N'IX_{objectQualifier}activeforums_Settings_Opt1') +DROP INDEX [IX_{objectQualifier}activeforums_Settings_Opt1] ON {databaseOwner}{objectQualifier}activeforums_Settings GO -IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'{databaseOwner}{objectQualifier}activeforums_Settings') AND name = N'idx_{objectQualifier}activeforums_Settings_Opt2') -DROP INDEX [idx_{objectQualifier}activeforums_Settings_Opt2] ON {databaseOwner}{objectQualifier}activeforums_Settings +IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'{databaseOwner}{objectQualifier}activeforums_Settings') AND name = N'IX_{objectQualifier}activeforums_Settings_Opt2') +DROP INDEX [IX_{objectQualifier}activeforums_Settings_Opt2] ON {databaseOwner}{objectQualifier}activeforums_Settings GO IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'{databaseOwner}{objectQualifier}activeforums_Topics') AND name = N'idx_{objectQualifier}activeforums_Topics_Opt1') DROP INDEX [idx_{objectQualifier}activeforums_Topics_Opt1] ON {databaseOwner}{objectQualifier}activeforums_Topics diff --git a/Dnn.CommunityForumsTests/TestBase.cs b/Dnn.CommunityForumsTests/TestBase.cs index e29eae258..27b16a411 100644 --- a/Dnn.CommunityForumsTests/TestBase.cs +++ b/Dnn.CommunityForumsTests/TestBase.cs @@ -56,7 +56,7 @@ public class TestBase internal Mock mockModule; - internal Mock MainSettings; + internal Mock MainSettings; [SetUp] @@ -81,7 +81,7 @@ public void SetUp() MockComponentProvider.CreateNew(); MockComponentProvider.CreateEventLogController(); - this.MainSettings = new Mock(); + this.MainSettings = new Mock(); this.SetupMainSettings(); this.mockHostController = new Mock(); diff --git a/Dnn.CommunityForumsTests/WebApiTests/WebApiForumGroupTests1.http b/Dnn.CommunityForumsTests/WebApiTests/WebApiForumGroupTests1.http new file mode 100644 index 000000000..132ec6dca --- /dev/null +++ b/Dnn.CommunityForumsTests/WebApiTests/WebApiForumGroupTests1.http @@ -0,0 +1,39 @@ +## These tests assume you have a DNN instance with DNN Community Forums installed and configured + +## change values in http-client.env.json to match your environment / browser session + +### first test is to verify a simple endpoint is reachable; we have a "Hello World" endpoint on each controller for this purpose" +### the HelloWorld endpoint does not require authentication but does require TabId and ModuleId headers for 'supported modules' check +GET {{hostname}}/API/ActiveForums/ForumGorup/HelloWorld +TabId: {{TabId}} +ModuleId: {{Moduleid}} + +### test to get a forum +GET {{hostname}}/API/ActiveForums/ForumGorup/Get?ForumId=1 +tabid: {{TabId}} +moduleid: {{Moduleid}} +requestverificationtoken: {{requestverificationtoken}} +cookie: .DOTNETNUKE={{.DOTNETNUKE}};__RequestVerificationToken={{__RequestVerificationToken}} + +### test to get a forum list +GET {{hostname}}/API/ActiveForums/ForumGorup/List +tabid: {{TabId}} +moduleid: {{Moduleid}} +requestverificationtoken: {{requestverificationtoken}} +cookie: .DOTNETNUKE={{.DOTNETNUKE}};__RequestVerificationToken={{__RequestVerificationToken}} + +### test to subscribe to a forum +POST {{hostname}}/API/ActiveForums/ForumGorup/Subscribe +tabid: {{TabId}} +moduleid: {{Moduleid}} +requestverificationtoken: {{requestverificationtoken}} +cookie: .DOTNETNUKE={{.DOTNETNUKE}};__RequestVerificationToken={{__RequestVerificationToken}} +content-type: application/json +content: {"forumid":"1"} + +### test to get subscriber count to a forum +GET {{hostname}}/API/ActiveForums/ForumGorup/SubscriberCount?ForumId=1 +tabid: {{TabId}} +moduleid: {{Moduleid}} +requestverificationtoken: {{requestverificationtoken}} +cookie: .DOTNETNUKE={{.DOTNETNUKE}};__RequestVerificationToken={{__RequestVerificationToken}} diff --git a/DnnCommunityForums.sln b/DnnCommunityForums.sln index 176855f43..c97fe3a63 100644 --- a/DnnCommunityForums.sln +++ b/DnnCommunityForums.sln @@ -8,6 +8,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Configuration", "Configurat .editorconfig = .editorconfig .gitattributes = .gitattributes .gitignore = .gitignore + .github\copilot-instructions.md = .github\copilot-instructions.md LICENSE = LICENSE README.md = README.md stylecop.json = stylecop.json From 7c064c37cf6a53c151f6567b016186865cdf7c9f Mon Sep 17 00:00:00 2001 From: John Henley Date: Wed, 8 Oct 2025 19:03:43 +0000 Subject: [PATCH 03/20] FIX: Error moving topic to another forum --- Dnn.CommunityForums/DnnCommunityForums.csproj | 4 +- Dnn.CommunityForums/DnnCommunityForums.dnn | 15 ++++--- .../DnnCommunityForums_Symbols.dnn | 4 +- Dnn.CommunityForums/ReleaseNotes.txt | 4 +- .../sql/09.02.00.SqlDataProvider | 43 +++++++++++++++++++ 5 files changed, 59 insertions(+), 11 deletions(-) create mode 100644 Dnn.CommunityForums/sql/09.02.00.SqlDataProvider diff --git a/Dnn.CommunityForums/DnnCommunityForums.csproj b/Dnn.CommunityForums/DnnCommunityForums.csproj index 124102fa4..cca9bca27 100644 --- a/Dnn.CommunityForums/DnnCommunityForums.csproj +++ b/Dnn.CommunityForums/DnnCommunityForums.csproj @@ -12,8 +12,8 @@ Discussion Forum Module for DNN dnncommunity.org dnncommunity.org - 09.01.01.00 - 09.01.01.00 + 09.02.00.00 + 09.02.00.00 False True diff --git a/Dnn.CommunityForums/DnnCommunityForums.dnn b/Dnn.CommunityForums/DnnCommunityForums.dnn index 25eeaebdc..5fd38177c 100644 --- a/Dnn.CommunityForums/DnnCommunityForums.dnn +++ b/Dnn.CommunityForums/DnnCommunityForums.dnn @@ -1,6 +1,6 @@  - + DNN Community Forums DNN Community Forums: The official online forums module for the DNN Community. DesktopModules/ActiveForums/images/branding/logo/DNN-Community-Forums-Icon-64px.png @@ -86,7 +86,7 @@ DotNetNuke.Modules.ActiveForums.dll bin\DotNetNuke.Modules.ActiveForums.dll - 09.01.01 + 09.02.00 @@ -439,10 +439,15 @@ 09.01.00.SqlDataProvider 09.01.00 + @@ -486,7 +491,7 @@ - + DNN Community Forums What's New ActiveForumsWhatsNew DNN Community Forums: Display the most recent topics or replies from selected forums on any page within your site. @@ -555,7 +560,7 @@ - + DNN Community Forums Forums Viewer ActiveForumsViewer DNN Community Forums: Display any forum topic view on any page within your site. diff --git a/Dnn.CommunityForums/DnnCommunityForums_Symbols.dnn b/Dnn.CommunityForums/DnnCommunityForums_Symbols.dnn index 7a9340c9a..be5cde55a 100644 --- a/Dnn.CommunityForums/DnnCommunityForums_Symbols.dnn +++ b/Dnn.CommunityForums/DnnCommunityForums_Symbols.dnn @@ -1,6 +1,6 @@  - + DNN Community Forums Symbols DNN Community Forums: The official online forums module for the DNN Community. DesktopModules/ActiveForums/images/branding/logo/DNN-Community-Forums-Icon-64px.png @@ -14,7 +14,7 @@ True - Active Forums + Active Forums diff --git a/Dnn.CommunityForums/ReleaseNotes.txt b/Dnn.CommunityForums/ReleaseNotes.txt index 429149212..c1e8d6182 100644 --- a/Dnn.CommunityForums/ReleaseNotes.txt +++ b/Dnn.CommunityForums/ReleaseNotes.txt @@ -46,7 +46,7 @@ DNN Community Forums Release Notes

    - 09.01.01 + 09.02.00

    diff --git a/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider b/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider index 236089c0a..c0aa15b3a 100644 --- a/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider +++ b/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider @@ -787,7 +787,7 @@ IF (SELECT ReplyCount FROM {databaseOwner}{objectQualifier}activeforums_Topics W If (@TopicsOnly = 1 AND @IsNewTopic = 0) OR (@TopicsOnly = 0) BEGIN IF @AutoSubscribe = 1 AND @AutoSubscribeRoles <> '' - BEGIN + BEGIN INSERT INTO @subs (userid, email, topicsubscriber) @@ -921,7 +921,7 @@ DELETE FROM {databaseOwner}{objectQualifier}activeforums_Settings WHERE Settings GO - + /* begin: activeforums_Search_GetSearchItemsFromBegDate */ IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Search_GetSearchItemsFromBegDate]') AND type in (N'P', N'PC')) DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Search_GetSearchItemsFromBegDate] @@ -954,6 +954,10 @@ INNER JOIN {databaseOwner}{objectQualifier}activeforums_settings S ON S.Settings WHERE F.Active = 1 AND S.SettingValue = 'true' AND F.ModuleId = @ModuleId GO + -- set last topic / reply on old Forum + SET @LastReplyId = (SELECT MAX(r.ReplyId) FROM {databaseOwner}{objectQualifier}activeforums_Replies as r inner join {databaseOwner}{objectQualifier}activeforums_topics as t on r.topicid = t.topicid inner join {databaseOwner}{objectQualifier}activeforums_ForumTopics as ft on t.topicid = ft.topicid WHERE r.IsApproved = 1 AND r.IsDeleted = 0 AND ft.forumid = @OldForumId ) + SET @LastTopicId = (SELECT MAX(t.TopicId) FROM {databaseOwner}{objectQualifier}activeforums_Topics as t inner join {databaseOwner}{objectQualifier}activeforums_ForumTopics as ft on t.topicid = ft.topicid WHERE t.IsApproved = 1 AND t.IsDeleted = 0 AND ft.forumid = @OldForumId ) + UPDATE {databaseOwner}{objectQualifier}activeforums_Forums SET LastReplyId = IsNull(@LastReplyId,0), LastTopicId = ISNULL(@LastTopicId,0) WHERE ForumId = @OldForumId /* activeforums_Settings_Delete */ IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Settings_Delete]') AND type in (N'P', N'PC')) @@ -1055,3 +1059,45 @@ GO /* issue 1582 - end - settings table overhaul */ /* --------------------- */ + + +/* Issue 1594 - Begin - update activeforums_Topics_Move procedure to remove previously-removed LastPostId from activeforums_Forums */ +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Topics_Move]') AND type in (N'P', N'PC')) +DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Topics_Move] +GO +CREATE PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Topics_Move] +@PortalId int, +@ModuleId int, +@ForumId int, +@TopicId int +AS +DECLARE @OldForumId int +SELECT @OldForumId = ForumId FROM {databaseOwner}{objectQualifier}activeforums_ForumTopics WHERE TopicId = @TopicId +If @OldForumId <> @ForumId + BEGIN + UPDATE {databaseOwner}{objectQualifier}activeforums_ForumTopics SET ForumId = @ForumId WHERE TopicId = @TopicId AND ForumId = @OldForumId + + DECLARE @LastReplyId int + DECLARE @LastTopicId int + + -- set last topic / reply on new Forum + SET @LastReplyId = (SELECT MAX(r.ReplyId) FROM {databaseOwner}{objectQualifier}activeforums_Replies as r inner join {databaseOwner}{objectQualifier}activeforums_topics as t on r.topicid = t.topicid inner join {databaseOwner}{objectQualifier}activeforums_ForumTopics as ft on t.topicid = ft.topicid WHERE r.IsApproved = 1 AND r.IsDeleted = 0 AND ft.forumid = @ForumId) + SET @LastTopicId = (SELECT MAX(t.TopicId) FROM {databaseOwner}{objectQualifier}activeforums_Topics as t inner join {databaseOwner}{objectQualifier}activeforums_ForumTopics as ft on t.topicid = ft.topicid WHERE t.IsApproved = 1 AND t.IsDeleted = 0 AND ft.forumid = @ForumId) + UPDATE {databaseOwner}{objectQualifier}activeforums_Forums SET LastReplyId = IsNull(@LastReplyId,0), LastTopicId = ISNULL(@LastTopicId,0) WHERE ForumId = @ForumId + + -- set last topic / reply on old Forum + SET @LastReplyId = (SELECT MAX(r.ReplyId) FROM {databaseOwner}{objectQualifier}activeforums_Replies as r inner join {databaseOwner}{objectQualifier}activeforums_topics as t on r.topicid = t.topicid inner join {databaseOwner}{objectQualifier}activeforums_ForumTopics as ft on t.topicid = ft.topicid WHERE r.IsApproved = 1 AND r.IsDeleted = 0 AND ft.forumid = @OldForumId ) + SET @LastTopicId = (SELECT MAX(t.TopicId) FROM {databaseOwner}{objectQualifier}activeforums_Topics as t inner join {databaseOwner}{objectQualifier}activeforums_ForumTopics as ft on t.topicid = ft.topicid WHERE t.IsApproved = 1 AND t.IsDeleted = 0 AND ft.forumid = @OldForumId ) + UPDATE {databaseOwner}{objectQualifier}activeforums_Forums SET LastReplyId = IsNull(@LastReplyId,0), LastTopicId = ISNULL(@LastTopicId,0) WHERE ForumId = @OldForumId + + -- clean up tracking records for the old forum pointing to this topic + DELETE FROM {databaseOwner}{objectQualifier}activeforums_Forums_Tracking WHERE ForumId = @OldForumId AND MaxTopicRead = @TopicId + UPDATE {databaseOwner}{objectQualifier}activeforums_Topics_Tracking SET ForumId = @ForumId WHERE TopicId = @TopicId AND ForumId = @OldForumId + + -- move any subscriptions for this topic from the old forum to the new forum + UPDATE {databaseOwner}{objectQualifier}activeforums_Subscriptions SET ForumId = @ForumId WHERE TopicId = @TopicId AND ForumId = @OldForumId + END +GO +/* Issue 1594 - End - update activeforums_Topics_Move procedure to remove previously-removed LastPostId from activeforums_Forums */ + +/* --------------------- */ From bc25a894c6e97b572235ae71e04a03ca24f40f56 Mon Sep 17 00:00:00 2001 From: John Henley Date: Wed, 8 Oct 2025 19:14:57 +0000 Subject: [PATCH 05/20] Fix bad SQL merge in #1595 --- Dnn.CommunityForums/sql/09.02.00.SqlDataProvider | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider b/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider index c0aa15b3a..4dfd2979c 100644 --- a/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider +++ b/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider @@ -954,11 +954,6 @@ INNER JOIN {databaseOwner}{objectQualifier}activeforums_settings S ON S.Settings WHERE F.Active = 1 AND S.SettingValue = 'true' AND F.ModuleId = @ModuleId GO - -- set last topic / reply on old Forum - SET @LastReplyId = (SELECT MAX(r.ReplyId) FROM {databaseOwner}{objectQualifier}activeforums_Replies as r inner join {databaseOwner}{objectQualifier}activeforums_topics as t on r.topicid = t.topicid inner join {databaseOwner}{objectQualifier}activeforums_ForumTopics as ft on t.topicid = ft.topicid WHERE r.IsApproved = 1 AND r.IsDeleted = 0 AND ft.forumid = @OldForumId ) - SET @LastTopicId = (SELECT MAX(t.TopicId) FROM {databaseOwner}{objectQualifier}activeforums_Topics as t inner join {databaseOwner}{objectQualifier}activeforums_ForumTopics as ft on t.topicid = ft.topicid WHERE t.IsApproved = 1 AND t.IsDeleted = 0 AND ft.forumid = @OldForumId ) - UPDATE {databaseOwner}{objectQualifier}activeforums_Forums SET LastReplyId = IsNull(@LastReplyId,0), LastTopicId = ISNULL(@LastTopicId,0) WHERE ForumId = @OldForumId - /* activeforums_Settings_Delete */ IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Settings_Delete]') AND type in (N'P', N'PC')) DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Settings_Delete] From ca822611568a31411a310400067c98fb362b2156 Mon Sep 17 00:00:00 2001 From: John Henley Date: Tue, 23 Sep 2025 20:49:39 +0000 Subject: [PATCH 06/20] add some minimal web api endpoint tests (still an issue with POST authentication) --- .../WebApiTests/WebApiForumTests1.http | 32 +++++++++++++++++++ .../WebApiTests/WebApiUserTests1.http | 25 +++++++++++++++ .../WebApiTests/http-client.env.json | 22 +++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 Dnn.CommunityForumsTests/WebApiTests/WebApiForumTests1.http create mode 100644 Dnn.CommunityForumsTests/WebApiTests/WebApiUserTests1.http create mode 100644 Dnn.CommunityForumsTests/WebApiTests/http-client.env.json diff --git a/Dnn.CommunityForumsTests/WebApiTests/WebApiForumTests1.http b/Dnn.CommunityForumsTests/WebApiTests/WebApiForumTests1.http new file mode 100644 index 000000000..5f8047db2 --- /dev/null +++ b/Dnn.CommunityForumsTests/WebApiTests/WebApiForumTests1.http @@ -0,0 +1,32 @@ +## These tests assume you have a DNN instance with DNN Community Forums installed and configured + +## change values in http-client.env.json to match your environment / browser session + +### first test is to verify a simple endpoint is reachable; we have a "Hello World" endpoint on each controller for this purpose" +### the HelloWorld endpoint does not require authentication but does require TabId and ModuleId headers for 'supported modules' check +GET {{hostname}}/API/ActiveForums/Forum/HelloWorld +TabId: {{TabId}} +ModuleId: {{Moduleid}} + +### test to get a forum +GET {{hostname}}/API/ActiveForums/Forum/Get?ForumId=1 +tabid: {{TabId}} +moduleid: {{Moduleid}} +requestverificationtoken: {{requestverificationtoken}} +cookie: .DOTNETNUKE={{.DOTNETNUKE}};__RequestVerificationToken={{__RequestVerificationToken}} + +### test to subscribe to a forum +POST {{hostname}}/API/ActiveForums/Forum/Subscribe +tabid: {{TabId}} +moduleid: {{Moduleid}} +requestverificationtoken: {{requestverificationtoken}} +cookie: .DOTNETNUKE={{.DOTNETNUKE}};__RequestVerificationToken={{__RequestVerificationToken}} +content-type: application/json +content: {"forumid":"1"} + +### test to get subscriber count to a forum +GET {{hostname}}/API/ActiveForums/Forum/SubscriberCount?ForumId=1 +tabid: {{TabId}} +moduleid: {{Moduleid}} +requestverificationtoken: {{requestverificationtoken}} +cookie: .DOTNETNUKE={{.DOTNETNUKE}};__RequestVerificationToken={{__RequestVerificationToken}} diff --git a/Dnn.CommunityForumsTests/WebApiTests/WebApiUserTests1.http b/Dnn.CommunityForumsTests/WebApiTests/WebApiUserTests1.http new file mode 100644 index 000000000..34dadfd92 --- /dev/null +++ b/Dnn.CommunityForumsTests/WebApiTests/WebApiUserTests1.http @@ -0,0 +1,25 @@ +## These tests assume you have a DNN instance with DNN Community Forums installed and configured + +## change values in http-client.env.json to match your environment / browser session + +### first test is to verify a simple endpoint is reachable; we have a "Hello World" endpoint on each controller for this purpose" +### the HelloWorld endpoint does not require authentication but does require TabId and ModuleId headers for 'supported modules' check +GET {{hostname}}/API/ActiveForums/User/HelloWorld +TabId: {{TabId}} +ModuleId: {{Moduleid}} + + +### test to get online users - requires authentication + +GET {{hostname}}/API/ActiveForums/User/GetUsersOnline +TabId: {{TabId}} +ModuleId: {{Moduleid}} +requestverificationtoken: {{requestverificationtoken}} + +### test to update online users - requires authentication + +POST {{hostname}}/API/ActiveForums/User/UpdateUserIsOnline +tabid: {{TabId}} +moduleid: {{Moduleid}} +requestverificationtoken: {{requestverificationtoken}} +cookie: .DOTNETNUKE={{.DOTNETNUKE}};__RequestVerificationToken={{__RequestVerificationToken}} diff --git a/Dnn.CommunityForumsTests/WebApiTests/http-client.env.json b/Dnn.CommunityForumsTests/WebApiTests/http-client.env.json new file mode 100644 index 000000000..13964805f --- /dev/null +++ b/Dnn.CommunityForumsTests/WebApiTests/http-client.env.json @@ -0,0 +1,22 @@ +/* + + These tests assume you have a DNN instance with DNN Community Forums installed and configured + + change values in this file (http-client.env.json) to match your environment / browser session + 1. capture moduleid, tabid, and requestverificationtoken from browser tools header request and insert here + 2. capture .DOTNETNUKE cookie value from browser tools application cookies and insert here + 3. capture __RequestVerificationToken cookie value from browser tools application cookies and insert here + + */ + +{ + "$shared": { + + "hostname": "https://dnndev.me", + "tabid": 34, + "moduleid": 382, + "requestverificationtoken": "6F0eqq5Pzh2fbzUTxWR7r4_WJ7eyaT6757hIXMCFjyWSfHQnMy_OZ18ANFCaYehlNo9URvDSWExlCgiZ0", /* from header request */ + ".DOTNETNUKE": "0456C0ECED94253A50C6084161E1CC2B15247C67C9899BA32434188FB8D752ED157F3CF1558EBA48C7CD3CB4615099C28C5F0D9846BCAC5C4EED0E8260625DD72448E14B", /* from application cookies */ + "__RequestVerificationToken": "JYRC09S-5Rq9QZ-l-djN9jCdxldMF4i_joDbtnOrj8ZYCcgBLtMaxR8I6XPFqYbjdplZCQ2" /* from application cookies */ + } +} From 9ef8e50effa467c11d2092271cb72fd52f7ee7bc Mon Sep 17 00:00:00 2001 From: John Henley Date: Tue, 23 Sep 2025 20:49:59 +0000 Subject: [PATCH 07/20] add view models for permissions and forums --- Dnn.CommunityForums/ViewModels/Forum.cs | 100 ++++++------ Dnn.CommunityForums/ViewModels/Permissions.cs | 153 ++++++++++++++++++ 2 files changed, 206 insertions(+), 47 deletions(-) create mode 100644 Dnn.CommunityForums/ViewModels/Permissions.cs diff --git a/Dnn.CommunityForums/ViewModels/Forum.cs b/Dnn.CommunityForums/ViewModels/Forum.cs index ce5379860..435f727d6 100644 --- a/Dnn.CommunityForums/ViewModels/Forum.cs +++ b/Dnn.CommunityForums/ViewModels/Forum.cs @@ -29,83 +29,89 @@ public class Forum public Forum(DotNetNuke.Modules.ActiveForums.Entities.ForumInfo forum) { this.forum = forum; - this.forum.Security = new DotNetNuke.Modules.ActiveForums.Entities.PermissionInfo(); + if (this.forum.Security == null) + { + this.forum.Security = new DotNetNuke.Modules.ActiveForums.Entities.PermissionInfo(); + } } - public int ForumId { get => this.forum.ForumID; set => this.forum.ForumID = value; } + public int Id { get => this.forum.ForumID; set => this.forum.ForumID = value; } - public string ForumName { get => this.forum.ForumName; set => this.forum.ForumName = value; } + public string Name { get => this.forum.ForumName; set => this.forum.ForumName = value; } - public string ForumDescription { get => this.forum.ForumDesc; set => this.forum.ForumDesc = value; } + public string Description { get => this.forum.ForumDesc; set => this.forum.ForumDesc = value; } public int PortalId { get => this.forum.PortalId; set => this.forum.PortalId = value; } public int ModuleId { get => this.forum.ModuleId; set => this.forum.ModuleId = value; } - public int ForumGroupId { get => this.forum.ForumGroupId; set => this.forum.ForumGroupId = value; } + public int GroupId { get => this.forum.ForumGroupId; set => this.forum.ForumGroupId = value; } - public string ForumGroupName => this.forum.GroupName; + public string GroupName => this.forum.GroupName; - public int ForumPermissionsId { get => this.forum.PermissionsId; set => this.forum.PermissionsId = value; } + public int PermissionsId { get => this.forum.PermissionsId; set => this.forum.PermissionsId = value; } - public int ForumLastTopicId => this.forum.LastTopicId; + public int LastTopicId => this.forum.LastTopicId; - public int ForumLastReplyId => this.forum.LastReplyId; + public int LastReplyId => this.forum.LastReplyId; - public int ForumLastPostID => this.forum.LastPostID; + public int LastPostID => this.forum.LastPostID; - public int ForumTotalTopics => this.forum.TotalTopics; + public int TotalTopics => this.forum.TotalTopics; public int TotalReplies => this.forum.TotalReplies; - public string ForumSettingsKey { get => this.forum.ForumSettingsKey; set => this.forum.ForumSettingsKey = value; } + public string SettingsKey { get => this.forum.ForumSettingsKey; set => this.forum.ForumSettingsKey = value; } - public bool ForumActive { get => this.forum.Active; set => this.forum.Active = value; } + public bool Active { get => this.forum.Active; set => this.forum.Active = value; } - public bool ForumHidden { get => this.forum.Hidden; set => this.forum.Hidden = value; } + public bool Hidden { get => this.forum.Hidden; set => this.forum.Hidden = value; } - public int ForumSubscriberCount => this.forum.SubscriberCount; + public int SubscriberCount => this.forum.SubscriberCount; - public string ForumURL => this.forum.ForumURL; + public string URL => this.forum.ForumURL; - public string ForumGroupPrefixURL => this.forum.GroupPrefixURL; + public string GroupPrefixURL => this.forum.GroupPrefixURL; - public DotNetNuke.Modules.ActiveForums.Entities.PermissionInfo ForumSecurity => this.forum.Security; + public DotNetNuke.Modules.ActiveForums.ViewModels.Permissions Security => new DotNetNuke.Modules.ActiveForums.ViewModels.Permissions(this.forum.Security); - public string ForumSecurityCreate => this.forum.Security.Create; - - public string ForumSecurityEdit => this.forum.Security.Edit; - - public string ForumSecurityDelete => this.forum.Security.Delete; - - public string ForumSecurityView => this.forum.Security.View; - - public string ForumSecurityAnnounce => this.forum.Security.Announce; - - public string ForumSecurityModerate => this.forum.Security.Moderate; - - public string ForumSecurityMove => this.forum.Security.Move; - - public string ForumSecuritySplit => this.forum.Security.Split; - - public string ForumSecurityTrust => this.forum.Security.Trust; - - public string ForumSecurityAttach => this.forum.Security.Attach; - - public string ForumSecurityAuthRolesCreate => this.forum.Security.Ban; - - public string ForumSecurityTag => this.forum.Security.Tag; - - public string ForumSecuritySubscribe => this.forum.Security.Subscribe; - - public string ForumPrefixURL => this.forum.PrefixURL; + public string PrefixURL => this.forum.PrefixURL; public int ParentForumId => this.forum.ParentForumId; public string ParentForumName => this.forum.ParentForumName; - public bool ForumHasProperties => this.forum.HasProperties; + public bool HasProperties => this.forum.HasProperties; + + public IEnumerable Properties => this.forum.Properties; - public IEnumerable ForumProperties => this.forum.Properties; + /// + /// Maps the current Forum view model to a ForumInfo entity. + /// + /// A new instance of ForumInfo with properties set from this view model. + public DotNetNuke.Modules.ActiveForums.Entities.ForumInfo ToForumInfo() + { + var forumInfo = new DotNetNuke.Modules.ActiveForums.Entities.ForumInfo(); + forumInfo.ForumID = this.Id; + forumInfo.ForumName = this.Name; + forumInfo.ForumDesc = this.Description; + forumInfo.PortalId = this.PortalId; + forumInfo.ModuleId = this.ModuleId; + forumInfo.ForumGroupId = this.GroupId; + forumInfo.PermissionsId = this.PermissionsId; + forumInfo.LastTopicId = this.LastTopicId; + forumInfo.LastReplyId = this.LastReplyId; + forumInfo.TotalTopics = this.TotalTopics; + forumInfo.TotalReplies = this.TotalReplies; + forumInfo.ForumSettingsKey = this.SettingsKey; + forumInfo.Active = this.Active; + forumInfo.Hidden = this.Hidden; + forumInfo.PrefixURL = this.PrefixURL; + forumInfo.ParentForumId = this.ParentForumId; + forumInfo.HasProperties = this.HasProperties; + forumInfo.Properties = this.Properties != null ? new List(this.Properties) : null; + + return forumInfo; + } } } diff --git a/Dnn.CommunityForums/ViewModels/Permissions.cs b/Dnn.CommunityForums/ViewModels/Permissions.cs new file mode 100644 index 000000000..22d915318 --- /dev/null +++ b/Dnn.CommunityForums/ViewModels/Permissions.cs @@ -0,0 +1,153 @@ +// Copyright (c) by DNN Community +// +// DNN Community licenses this file to you under the MIT license. +// +// See the LICENSE file in the project root for more information. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +namespace DotNetNuke.Modules.ActiveForums.ViewModels +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web.Security; + + public class Permissions + { + private readonly DotNetNuke.Modules.ActiveForums.Entities.PermissionInfo permissions; + + public Permissions() + { + permissions = new DotNetNuke.Modules.ActiveForums.Entities.PermissionInfo(); + } + + public Permissions(DotNetNuke.Modules.ActiveForums.Entities.PermissionInfo permissions) + { + this.permissions = permissions; + } + + public int PermissionsId { get => this.permissions.PermissionsId; } + + public HashSet ViewRoleIds { get => this.permissions.ViewRoleIds; } + + public HashSet ReadRoleIds { get => this.permissions.ReadRoleIds; } + + public HashSet CreateRoleIds { get => this.permissions.CreateRoleIds; } + + public HashSet ReplyRoleIds { get => this.permissions.ReplyRoleIds; } + + public HashSet EditRoleIds { get => this.permissions.EditRoleIds; } + + public HashSet DeleteRoleIds { get => this.permissions.DeleteRoleIds; } + + public HashSet LockRoleIds { get => this.permissions.LockRoleIds; } + + public HashSet PinRoleIds { get => this.permissions.PinRoleIds; } + + public HashSet AttachRoleIds { get => this.permissions.AttachRoleIds; } + + public HashSet PollRoleIds { get => this.permissions.PollRoleIds; } + + public HashSet BlockRoleIds { get => this.permissions.BlockRoleIds; } + + public HashSet TrustRoleIds { get => this.permissions.TrustRoleIds; } + + public HashSet SubscribeRoleIds { get => this.permissions.SubscribeRoleIds; } + + public HashSet AnnounceRoleIds { get => this.permissions.AnnounceRoleIds; } + + public HashSet TagRoleIds { get => this.permissions.TagRoleIds; } + + public HashSet CategorizeRoleIds { get => this.permissions.CategorizeRoleIds; } + + public HashSet PrioritizeRoleIds { get => this.permissions.PrioritizeRoleIds; } + + public HashSet ModerateRoleIds { get => this.permissions.ModerateRoleIds; } + + public HashSet MoveRoleIds { get => this.permissions.MoveRoleIds; } + + public HashSet SplitRoleIds { get => this.permissions.SplitRoleIds; } + + public HashSet BanRoleIds { get => this.permissions.BanRoleIds; } + + public bool EqualPermissions(Permissions other) + { + return !(other is null) && + this.EqualPermissionMembers(this.AnnounceRoleIds, other.AnnounceRoleIds) && + this.EqualPermissionMembers(this.AttachRoleIds, other.AttachRoleIds) && + this.EqualPermissionMembers(this.BanRoleIds, other.BanRoleIds) && + // EqualPermissionMembers(this.BlockRoleIds, other.BlockRoleIds) && + this.EqualPermissionMembers(this.CategorizeRoleIds, other.CategorizeRoleIds) && + this.EqualPermissionMembers(this.CreateRoleIds, other.CreateRoleIds) && + this.EqualPermissionMembers(this.DeleteRoleIds, other.DeleteRoleIds) && + this.EqualPermissionMembers(this.EditRoleIds, other.EditRoleIds) && + this.EqualPermissionMembers(this.LockRoleIds, other.LockRoleIds) && + this.EqualPermissionMembers(this.ModerateRoleIds, other.ModerateRoleIds) && + this.EqualPermissionMembers(this.ModerateRoleIds, other.ModerateRoleIds) && + this.EqualPermissionMembers(this.MoveRoleIds, other.MoveRoleIds) && + this.EqualPermissionMembers(this.PinRoleIds, other.PinRoleIds) && + this.EqualPermissionMembers(this.PollRoleIds, other.PollRoleIds) && + this.EqualPermissionMembers(this.PrioritizeRoleIds, other.PrioritizeRoleIds) && + this.EqualPermissionMembers(this.ReadRoleIds, other.ReadRoleIds) && + this.EqualPermissionMembers(this.ReplyRoleIds, other.ReplyRoleIds) && + this.EqualPermissionMembers(this.SplitRoleIds, other.SplitRoleIds) && + this.EqualPermissionMembers(this.SubscribeRoleIds, other.SubscribeRoleIds) && + this.EqualPermissionMembers(this.TagRoleIds, other.TagRoleIds) && + this.EqualPermissionMembers(this.TrustRoleIds, other.TrustRoleIds) && + this.EqualPermissionMembers(this.ViewRoleIds, other.ViewRoleIds); + } + + public bool EqualPermissionMembers(HashSet thisPermissions, HashSet otherPermissions) + { + return thisPermissions.SetEquals(otherPermissions); + } + + /// + /// Maps this view model to a entity. + /// + /// A new entity with values from this view model. + public DotNetNuke.Modules.ActiveForums.Entities.PermissionInfo ToPermissionInfo() + { + var entity = new DotNetNuke.Modules.ActiveForums.Entities.PermissionInfo + { + PermissionsId = this.PermissionsId, + View = string.Join(";", this.ViewRoleIds.Distinct().OrderBy(r => r)), + Read = string.Join(";", this.ReadRoleIds.Distinct().OrderBy(r => r)), + Create = string.Join(";", this.CreateRoleIds.Distinct().OrderBy(r => r)), + Reply = string.Join(";", this.ReplyRoleIds.Distinct().OrderBy(r => r)), + Edit = string.Join(";", this.EditRoleIds.Distinct().OrderBy(r => r)), + Delete = string.Join(";", this.DeleteRoleIds.Distinct().OrderBy(r => r)), + Lock = string.Join(";", this.LockRoleIds.Distinct().OrderBy(r => r)), + Pin = string.Join(";",this.PinRoleIds.Distinct().OrderBy(r => r)), + Attach = string.Join(";",this.AttachRoleIds.Distinct().OrderBy(r => r)), + Poll = string.Join(";",this.PollRoleIds.Distinct().OrderBy(r => r)), + Block = string.Join(";",this.BlockRoleIds.Distinct().OrderBy(r => r)), + Trust = string.Join(";",this.TrustRoleIds.Distinct().OrderBy(r => r)), + Subscribe = string.Join(";",this.SubscribeRoleIds.Distinct().OrderBy(r => r)), + Announce = string.Join(";",this.AnnounceRoleIds.Distinct().OrderBy(r => r)), + Tag = string.Join(";",this.TagRoleIds.Distinct().OrderBy(r => r)), + Categorize = string.Join(";",this.CategorizeRoleIds.Distinct().OrderBy(r => r)), + Prioritize = string.Join(";",this.PrioritizeRoleIds.Distinct().OrderBy(r => r)), + Moderate = string.Join(";",this.ModerateRoleIds.Distinct().OrderBy(r => r)), + Move = string.Join(";",this.MoveRoleIds.Distinct().OrderBy(r => r)), + Split = string.Join(";",this.SplitRoleIds.Distinct().OrderBy(r => r)), + Ban = string.Join(";",this.BanRoleIds.Distinct().OrderBy(r => r)), + }; + + return entity; + } + } +} From ec3428d653759ed0856e59fb55a3ddbb310d9e8a Mon Sep 17 00:00:00 2001 From: John Henley Date: Tue, 23 Sep 2025 22:15:46 +0000 Subject: [PATCH 08/20] settings table revamp --- .../sql/09.02.00.SqlDataProvider | 46 +++++++++++++++++-- .../WebApiTests/WebApiForumTests1.http | 7 +++ DnnCommunityForums.sln | 5 ++ 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider b/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider index 4dfd2979c..3e162ab57 100644 --- a/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider +++ b/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider @@ -44,7 +44,7 @@ GO CREATE UNIQUE NONCLUSTERED INDEX [IX_{objectQualifier}activeforums_Settings_Opt1] ON {databaseOwner}[{objectQualifier}activeforums_Settings] - ( + ( [ModuleId] ASC, [SettingsKey] ASC, [SettingName] ASC @@ -52,6 +52,8 @@ CREATE UNIQUE NONCLUSTERED INDEX [IX_{objectQualifier}activeforums_Settings_Opt1 INCLUDE([SettingValue]); GO + + /* activeforums_Groups_Delete */ IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Groups_Delete]') AND type in (N'P', N'PC')) DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Groups_Delete] @@ -787,7 +789,7 @@ IF (SELECT ReplyCount FROM {databaseOwner}{objectQualifier}activeforums_Topics W If (@TopicsOnly = 1 AND @IsNewTopic = 0) OR (@TopicsOnly = 0) BEGIN IF @AutoSubscribe = 1 AND @AutoSubscribeRoles <> '' - BEGIN + BEGIN INSERT INTO @subs (userid, email, topicsubscriber) @@ -820,6 +822,43 @@ SELECT DISTINCT userid, email, topicsubscriber FROM @subs GO +/* activeforums_SettingsTable */ +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_SettingsTable]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT')) +DROP FUNCTION {databaseOwner}[{objectQualifier}activeforums_SettingsTable] +GO +CREATE FUNCTION {databaseOwner}[{objectQualifier}activeforums_SettingsTable]( +@SettingsKey nvarchar(255) +) +RETURNS TABLE +AS +RETURN +( +SELECT pvt.SettingKey, [ALLOWATTACH],[ALLOWEMOTICONS],[ALLOWHTML],[ALLOWPOSTICON],[ALLOWRSS],[ALLOWSCRIPT],[ALLOWTAGS],[ATTACHCOUNT],[ATTACHMAXHEIGHT],[ATTACHMAXSIZE],[ATTACHMAXWIDTH],[ATTACHSTORE],[ATTACHTYPEALLOWED],[ATTACHUNIQUEFILENAMES],[AUTOSUBSCRIBEENABLED],[AUTOSUBSCRIBENEWTOPICSONLY],[AUTOSUBSCRIBEROLES],[ATTACHINSERTALLOWED],[MAXATTACHHEIGHT],[MAXATTACHWIDTH],[CONVERTINGTOJPEGALLOWED],[AUTOTRUSTLEVEL],[DEFAULTTRUSTLEVEL],[EDITORHEIGHT],[EDITORPERMITTEDUSERS],[EDITORSTYLE],[EDITORTOOLBAR],[EDITORTYPE],[EDITORWIDTH],[EMAILADDRESS],[INDEXCONTENT],[ISMODERATED],[MCADDRESS],[MCADMINNOTIFY],[MCAUTOCREATEUSERS],[MCAUTORESPONSE],[MCENABLED],[MCEOMTAG],[MCEOMTAGREQ],[MCMODTYPE],[MCPOPPASSWORD],[MCPOPSERVER],[MCPOPUSERNAME],[MCREJECTNOTIFY],[MCRESTRICTALIAS],[MCSTRIPHTML],[MCSUBNOTIFY],[MCURL],[MODAPPROVETEMPLATEID],[MODDELETETEMPLATEID],[MODMOVETEMPLATEID],[MODNOTIFYTEMPLATEID],[MODREJECTTEMPLATEID],[PROFILETEMPLATEID],[QUICKREPLYFORMID],[REPLYFORMID],[TOPICFORMID],[TOPICSTEMPLATEID],[TOPICTEMPLATEID],[USEFILTER] from + ( + SELECT SettingKey, SettingName, SettingValue FROM [dbo].activeforums_Settings + ) s PIVOT (MAX(SettingValue) FOR SettingName IN ([ALLOWATTACH],[ALLOWEMOTICONS],[ALLOWHTML],[ALLOWPOSTICON],[ALLOWRSS],[ALLOWSCRIPT],[ALLOWTAGS],[ATTACHCOUNT],[ATTACHMAXHEIGHT],[ATTACHMAXSIZE],[ATTACHMAXWIDTH],[ATTACHSTORE],[ATTACHTYPEALLOWED],[ATTACHUNIQUEFILENAMES],[AUTOSUBSCRIBEENABLED],[AUTOSUBSCRIBENEWTOPICSONLY],[AUTOSUBSCRIBEROLES],[ATTACHINSERTALLOWED],[MAXATTACHHEIGHT],[MAXATTACHWIDTH],[CONVERTINGTOJPEGALLOWED],[AUTOTRUSTLEVEL],[DEFAULTTRUSTLEVEL],[EDITORHEIGHT],[EDITORPERMITTEDUSERS],[EDITORSTYLE],[EDITORTOOLBAR],[EDITORTYPE],[EDITORWIDTH],[EMAILADDRESS],[INDEXCONTENT],[ISMODERATED],[MCADDRESS],[MCADMINNOTIFY],[MCAUTOCREATEUSERS],[MCAUTORESPONSE],[MCENABLED],[MCEOMTAG],[MCEOMTAGREQ],[MCMODTYPE],[MCPOPPASSWORD],[MCPOPSERVER],[MCPOPUSERNAME],[MCREJECTNOTIFY],[MCRESTRICTALIAS],[MCSTRIPHTML],[MCSUBNOTIFY],[MCURL],[MODAPPROVETEMPLATEID],[MODDELETETEMPLATEID],[MODMOVETEMPLATEID],[MODNOTIFYTEMPLATEID],[MODREJECTTEMPLATEID],[PROFILETEMPLATEID],[QUICKREPLYFORMID],[REPLYFORMID],[TOPICFORMID],[TOPICSTEMPLATEID],[TOPICTEMPLATEID],[USEFILTER])) as pvt +) + +GO + + +/*activeforums_ForumsList*/ +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_ForumsList]') AND type in (N'P', N'PC')) +DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_ForumsList] +GO +CREATE PROCEDURE {databaseOwner}[{objectQualifier}activeforums_ForumsList] +@PortalId int, +@ModuleId int +AS +SELECT F.*,P.*,s.*,G.GroupName,G.Active as GroupActive, G.Hidden as GroupHidden,ISNULL(g.PrefixURL,'') as GroupPrefixURL,GETUTCDATE() as LastRead from {databaseOwner}{objectQualifier}activeforums_Forums as f INNER JOIN + {databaseOwner}{objectQualifier}activeforums_Groups as G ON F.ForumGroupId = G.ForumGroupId INNER JOIN + {databaseOwner}{objectQualifier}activeforums_Permissions as P ON P.PermissionsId = f.PermissionsId INNER JOIN + {databaseOwner}{objectQualifier}activeforums_SettingsTable('F') as s ON s.SettingKey = f.ForumSettingsKey +WHERE F.PortalId = @PortalId AND (F.ModuleId = @ModuleId OR @ModuleId=-1) +ORDER BY G.SortOrder, F.SortOrder + +GO + /* activeforums_Forums_List */ IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Forums_List]') AND type in (N'P', N'PC')) @@ -921,7 +960,7 @@ DELETE FROM {databaseOwner}{objectQualifier}activeforums_Settings WHERE Settings GO - + /* begin: activeforums_Search_GetSearchItemsFromBegDate */ IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Search_GetSearchItemsFromBegDate]') AND type in (N'P', N'PC')) DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Search_GetSearchItemsFromBegDate] @@ -954,6 +993,7 @@ INNER JOIN {databaseOwner}{objectQualifier}activeforums_settings S ON S.Settings WHERE F.Active = 1 AND S.SettingValue = 'true' AND F.ModuleId = @ModuleId GO + /* activeforums_Settings_Delete */ IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Settings_Delete]') AND type in (N'P', N'PC')) DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Settings_Delete] diff --git a/Dnn.CommunityForumsTests/WebApiTests/WebApiForumTests1.http b/Dnn.CommunityForumsTests/WebApiTests/WebApiForumTests1.http index 5f8047db2..d84a67b31 100644 --- a/Dnn.CommunityForumsTests/WebApiTests/WebApiForumTests1.http +++ b/Dnn.CommunityForumsTests/WebApiTests/WebApiForumTests1.http @@ -15,6 +15,13 @@ moduleid: {{Moduleid}} requestverificationtoken: {{requestverificationtoken}} cookie: .DOTNETNUKE={{.DOTNETNUKE}};__RequestVerificationToken={{__RequestVerificationToken}} +### test to get a forum list +GET {{hostname}}/API/ActiveForums/Forum/List +tabid: {{TabId}} +moduleid: {{Moduleid}} +requestverificationtoken: {{requestverificationtoken}} +cookie: .DOTNETNUKE={{.DOTNETNUKE}};__RequestVerificationToken={{__RequestVerificationToken}} + ### test to subscribe to a forum POST {{hostname}}/API/ActiveForums/Forum/Subscribe tabid: {{TabId}} diff --git a/DnnCommunityForums.sln b/DnnCommunityForums.sln index c97fe3a63..690a35bb7 100644 --- a/DnnCommunityForums.sln +++ b/DnnCommunityForums.sln @@ -18,6 +18,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DnnCommunityForums", "Dnn.C EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DnnCommunityForumsTests", "Dnn.CommunityForumsTests\DnnCommunityForumsTests.csproj", "{B268075A-B369-4B84-8AB9-D338AD41C6D6}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8EC462FD-D22E-90A8-E5CE-7E832BA40C5D}" + ProjectSection(SolutionItems) = preProject + .github\copilot-instructions.md = .github\copilot-instructions.md + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU From 64626940b0da446c1b3279b3521a35bd85501df9 Mon Sep 17 00:00:00 2001 From: John Henley Date: Wed, 8 Oct 2025 19:49:40 +0000 Subject: [PATCH 09/20] TASK: Updates for Web API --- .../Controllers/FeatureSettingsController.cs | 18 +++++----- .../Services/Controllers/ForumController.cs | 35 ++++++++++--------- .../Controllers/ForumGroupController.cs | 19 +++------- .../Services/Controllers/LikeController.cs | 1 + .../Services/Controllers/TagController.cs | 4 +-- .../Services/Controllers/TopicController.cs | 2 ++ 6 files changed, 36 insertions(+), 43 deletions(-) diff --git a/Dnn.CommunityForums/Services/Controllers/FeatureSettingsController.cs b/Dnn.CommunityForums/Services/Controllers/FeatureSettingsController.cs index 165f00c15..20bdc460b 100644 --- a/Dnn.CommunityForums/Services/Controllers/FeatureSettingsController.cs +++ b/Dnn.CommunityForums/Services/Controllers/FeatureSettingsController.cs @@ -39,7 +39,6 @@ public class FeatureSettingsController : ControllerBasesettings [HttpGet] [DnnAuthorize] - [ForumsAuthorize(SecureActions.Ban)] public IHttpActionResult GetAllSettings(string settingsKey) { try @@ -61,7 +60,6 @@ public IHttpActionResult GetAllSettings(string settingsKey) /// setting [HttpGet] [DnnAuthorize] - [ForumsAuthorize(SecureActions.Ban)] public IHttpActionResult GetSetting(string settingsKey, string key) { try @@ -87,8 +85,8 @@ public IHttpActionResult GetSetting(string settingsKey, string key) /// value /// HTTP status [HttpPost] - [DnnAuthorize] - [ForumsAuthorize(SecureActions.Ban)] + [ValidateAntiForgeryToken] + [DnnAuthorize(StaticRoles = "Administrators")] public IHttpActionResult SetSetting(string settingsKey, string key, [FromBody] string value) { try @@ -111,8 +109,8 @@ public IHttpActionResult SetSetting(string settingsKey, string key, [FromBody] s /// key /// HTTP status [HttpDelete] - [DnnAuthorize] - [ForumsAuthorize(SecureActions.Ban)] + [ValidateAntiForgeryToken] + [DnnAuthorize(StaticRoles = "Administrators")] public IHttpActionResult DeleteSetting(string settingsKey, string key) { try @@ -139,8 +137,8 @@ public IHttpActionResult DeleteSetting(string settingsKey, string key) /// newSettings /// HTTP status [HttpPut] - [DnnAuthorize] - [ForumsAuthorize(SecureActions.Ban)] + [ValidateAntiForgeryToken] + [DnnAuthorize(StaticRoles = "Administrators")] public IHttpActionResult UpdateAllSettings(string settingsKey, [FromBody] Hashtable newSettings) { try @@ -161,8 +159,8 @@ public IHttpActionResult UpdateAllSettings(string settingsKey, [FromBody] Hashta /// settingsKey /// HTTP status [HttpDelete] - [DnnAuthorize] - [ForumsAuthorize(SecureActions.Ban)] + [ValidateAntiForgeryToken] + [DnnAuthorize(StaticRoles = "Administrators")] public IHttpActionResult DeleteAllSettings(string settingsKey) { try diff --git a/Dnn.CommunityForums/Services/Controllers/ForumController.cs b/Dnn.CommunityForums/Services/Controllers/ForumController.cs index e243a982f..15c32fb94 100644 --- a/Dnn.CommunityForums/Services/Controllers/ForumController.cs +++ b/Dnn.CommunityForums/Services/Controllers/ForumController.cs @@ -75,6 +75,7 @@ public HttpResponseMessage Subscribe(ForumDto dto) /// https://dnndev.me/API/ActiveForums/Forum/SubscriberCount?ForumId=xxx [HttpGet] [DnnAuthorize] + [ForumsAuthorize(SecureActions.View)] public HttpResponseMessage SubscriberCount(int forumId) { try @@ -99,6 +100,7 @@ public HttpResponseMessage SubscriberCount(int forumId) /// https://dnndev.me/API/ActiveForums/Forum/SubscriberCountString?ForumId=xxx [HttpGet] [DnnAuthorize] + [ForumsAuthorize(SecureActions.View)] public HttpResponseMessage SubscriberCountString(int forumId) { try @@ -148,7 +150,7 @@ public HttpResponseMessage ListForHtml(ForumDto dto) /// https://dnndev.me/API/ActiveForums/Forum/Get?forumId=x [HttpGet] [DnnAuthorize] - [ForumsAuthorize(SecureActions.Ban)] + [ForumsAuthorize(SecureActions.View)] public HttpResponseMessage Get(int forumId) { try @@ -178,9 +180,8 @@ public HttpResponseMessage Get(int forumId) /// ForumInfo /// Created forum [HttpPost] - [DnnAuthorize] [ValidateAntiForgeryToken] - [ForumsAuthorize(SecureActions.Ban)] + [DnnAuthorize(StaticRoles = "Administrators")] public HttpResponseMessage Create([FromBody] DotNetNuke.Modules.ActiveForums.Entities.ForumInfo forum) { try @@ -212,9 +213,8 @@ public HttpResponseMessage Create([FromBody] DotNetNuke.Modules.ActiveForums.Ent /// /// Created forum [HttpPost] - [DnnAuthorize] [ValidateAntiForgeryToken] - [ForumsAuthorize(SecureActions.Ban)] + [DnnAuthorize(StaticRoles = "Administrators")] public HttpResponseMessage Create([FromBody] DotNetNuke.Modules.ActiveForums.Entities.ForumInfo forum, bool useGroupFeatures, bool useGroupSecurity) { try @@ -244,9 +244,8 @@ public HttpResponseMessage Create([FromBody] DotNetNuke.Modules.ActiveForums.Ent /// ForumInfo /// updated forum [HttpPut] - [DnnAuthorize] [ValidateAntiForgeryToken] - [ForumsAuthorize(SecureActions.Ban)] + [DnnAuthorize(StaticRoles = "Administrators")] public HttpResponseMessage Update([FromBody] DotNetNuke.Modules.ActiveForums.Entities.ForumInfo forum) { try @@ -275,9 +274,8 @@ public HttpResponseMessage Update([FromBody] DotNetNuke.Modules.ActiveForums.Ent /// /// Success status [HttpPut] - [DnnAuthorize] [ValidateAntiForgeryToken] - [ForumsAuthorize(SecureActions.Ban)] + [DnnAuthorize(StaticRoles = "Administrators")] public HttpResponseMessage Update([FromBody] DotNetNuke.Modules.ActiveForums.Entities.ForumInfo forum, bool useGroupFeatures, bool useGroupSecurity) { try @@ -304,9 +302,8 @@ public HttpResponseMessage Update([FromBody] DotNetNuke.Modules.ActiveForums.Ent /// Forum ID /// Success status [HttpDelete] - [DnnAuthorize] [ValidateAntiForgeryToken] - [ForumsAuthorize(SecureActions.Ban)] + [DnnAuthorize(StaticRoles = "Administrators")] public HttpResponseMessage Delete(int forumId) { try @@ -337,13 +334,20 @@ public HttpResponseMessage Delete(int forumId) ///
    [HttpGet] [DnnAuthorize] - [ForumsAuthorize(SecureActions.Ban)] public HttpResponseMessage List() { try { + var forumUser = new DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController(this.ForumModuleId).GetByUserId(this.ActiveModule.PortalID, this.UserInfo.UserID); var forums = new List(); - new DotNetNuke.Modules.ActiveForums.Controllers.ForumController().GetForums(moduleId: this.ForumModuleId).ForEach(f => forums.Add(new DotNetNuke.Modules.ActiveForums.ViewModels.Forum(f))); + new DotNetNuke.Modules.ActiveForums.Controllers.ForumController().GetForums(moduleId: this.ForumModuleId).ForEach(f => + { + if (DotNetNuke.Modules.ActiveForums.Controllers.PermissionController.HasRequiredPerm(f.Security.ViewRoleIds, forumUser.UserRoleIds) + { + forums.Add(new DotNetNuke.Modules.ActiveForums.ViewModels.Forum(f)); + } + }); + return this.Request.CreateResponse(HttpStatusCode.OK, forums); } catch (Exception ex) @@ -358,7 +362,7 @@ public HttpResponseMessage List() /// [HttpGet] [DnnAuthorize] - [ForumsAuthorize(SecureActions.Ban)] + [DnnAuthorize(StaticRoles = "Administrators")] public HttpResponseMessage Moderators(int forumId) { try @@ -378,7 +382,6 @@ public HttpResponseMessage Moderators(int forumId) /// [HttpGet] [DnnAuthorize] - [ForumsAuthorize(SecureActions.Ban)] public HttpResponseMessage Subscriptions(int userId) { try @@ -403,7 +406,6 @@ public HttpResponseMessage Subscriptions(int userId) /// [HttpGet] [DnnAuthorize] - [ForumsAuthorize(SecureActions.Ban)] public HttpResponseMessage Settings(int forumId) { try @@ -433,7 +435,6 @@ public HttpResponseMessage Settings(int forumId) /// [HttpGet] [DnnAuthorize] - [ForumsAuthorize(SecureActions.Ban)] public HttpResponseMessage Security(int forumId) { try diff --git a/Dnn.CommunityForums/Services/Controllers/ForumGroupController.cs b/Dnn.CommunityForums/Services/Controllers/ForumGroupController.cs index d9b58db58..15fd7195a 100644 --- a/Dnn.CommunityForums/Services/Controllers/ForumGroupController.cs +++ b/Dnn.CommunityForums/Services/Controllers/ForumGroupController.cs @@ -45,7 +45,6 @@ public struct ForumGroupDto /// https://dnndev.me/API/ActiveForums/ForumGroup/Get?ForumGroupId=x [HttpGet] [DnnAuthorize] - [ForumsAuthorize(SecureActions.Ban)] public HttpResponseMessage Get(int ForumGroupId) { try @@ -75,9 +74,8 @@ public HttpResponseMessage Get(int ForumGroupId) /// ForumGroupInfo /// Created ForumGroup [HttpPost] - [DnnAuthorize] [ValidateAntiForgeryToken] - [ForumsAuthorize(SecureActions.Ban)] + [DnnAuthorize(StaticRoles = "Administrators")] public HttpResponseMessage Create([FromBody] DotNetNuke.Modules.ActiveForums.Entities.ForumGroupInfo forumGroup) { try @@ -108,9 +106,8 @@ public HttpResponseMessage Create([FromBody] DotNetNuke.Modules.ActiveForums.Ent /// /// Created ForumGroup [HttpPost] - [DnnAuthorize] [ValidateAntiForgeryToken] - [ForumsAuthorize(SecureActions.Ban)] + [DnnAuthorize(StaticRoles = "Administrators")] public HttpResponseMessage Create([FromBody] DotNetNuke.Modules.ActiveForums.Entities.ForumGroupInfo forumGroup, bool useDefaultFeatures, bool useDefaultSecurity) { try @@ -139,9 +136,8 @@ public HttpResponseMessage Create([FromBody] DotNetNuke.Modules.ActiveForums.Ent /// ForumGroupInfo /// updated ForumGroup [HttpPut] - [DnnAuthorize] [ValidateAntiForgeryToken] - [ForumsAuthorize(SecureActions.Ban)] + [DnnAuthorize(StaticRoles = "Administrators")] public HttpResponseMessage Update([FromBody] DotNetNuke.Modules.ActiveForums.Entities.ForumGroupInfo forumGroup) { try @@ -170,9 +166,8 @@ public HttpResponseMessage Update([FromBody] DotNetNuke.Modules.ActiveForums.Ent /// /// Success status [HttpPut] - [DnnAuthorize] [ValidateAntiForgeryToken] - [ForumsAuthorize(SecureActions.Ban)] + [DnnAuthorize(StaticRoles = "Administrators")] public HttpResponseMessage Update([FromBody] DotNetNuke.Modules.ActiveForums.Entities.ForumGroupInfo forumGroup, bool useDefaultFeatures, bool useDefaultSecurity) { try @@ -199,9 +194,8 @@ public HttpResponseMessage Update([FromBody] DotNetNuke.Modules.ActiveForums.Ent /// ForumGroup ID /// Success status [HttpDelete] - [DnnAuthorize] [ValidateAntiForgeryToken] - [ForumsAuthorize(SecureActions.Ban)] + [DnnAuthorize(StaticRoles = "Administrators")] public HttpResponseMessage Delete(int forumGroupId) { try @@ -232,7 +226,6 @@ public HttpResponseMessage Delete(int forumGroupId) /// [HttpGet] [DnnAuthorize] - [ForumsAuthorize(SecureActions.Ban)] public HttpResponseMessage List() { try @@ -252,7 +245,6 @@ public HttpResponseMessage List() /// [HttpGet] [DnnAuthorize] - [ForumsAuthorize(SecureActions.Ban)] public HttpResponseMessage Settings(int ForumGroupId) { try @@ -282,7 +274,6 @@ public HttpResponseMessage Settings(int ForumGroupId) /// [HttpGet] [DnnAuthorize] - [ForumsAuthorize(SecureActions.Ban)] public HttpResponseMessage Security(int ForumGroupId) { try diff --git a/Dnn.CommunityForums/Services/Controllers/LikeController.cs b/Dnn.CommunityForums/Services/Controllers/LikeController.cs index 5ab1dbc26..270cda62e 100644 --- a/Dnn.CommunityForums/Services/Controllers/LikeController.cs +++ b/Dnn.CommunityForums/Services/Controllers/LikeController.cs @@ -87,6 +87,7 @@ public HttpResponseMessage Like(LikeDto dto) /// https://dnndev.me/API/ActiveForums/Like/Get/1/1 [HttpGet] [DnnAuthorize] + [ForumsAuthorize(SecureActions.View)] public HttpResponseMessage Get(int forumId, int contentId) { try diff --git a/Dnn.CommunityForums/Services/Controllers/TagController.cs b/Dnn.CommunityForums/Services/Controllers/TagController.cs index 6963fbf4c..ce14286f4 100644 --- a/Dnn.CommunityForums/Services/Controllers/TagController.cs +++ b/Dnn.CommunityForums/Services/Controllers/TagController.cs @@ -44,7 +44,7 @@ public class TagController : ControllerBase #pragma warning restore CS1570 [HttpGet] [DnnAuthorize] - [ForumsAuthorize(SecureActions.Tag)] + [ForumsAuthorize(SecureActions.Edit)] public HttpResponseMessage Matches(int forumId, string matchString) { return this.Match($"%{CleanAndChopString(matchString, 20)}%"); @@ -61,7 +61,7 @@ public HttpResponseMessage Matches(int forumId, string matchString) #pragma warning restore CS1570 [HttpGet] [DnnAuthorize] - [ForumsAuthorize(SecureActions.Tag)] + [ForumsAuthorize(SecureActions.Edit)] public HttpResponseMessage BeginsWith(int forumId, string matchString) { return this.Match($"{CleanAndChopString(matchString, 20)}%"); diff --git a/Dnn.CommunityForums/Services/Controllers/TopicController.cs b/Dnn.CommunityForums/Services/Controllers/TopicController.cs index 381f78545..402daa6e3 100644 --- a/Dnn.CommunityForums/Services/Controllers/TopicController.cs +++ b/Dnn.CommunityForums/Services/Controllers/TopicController.cs @@ -88,6 +88,7 @@ public HttpResponseMessage Subscribe(TopicDto1 dto) #pragma warning restore CS1570 [HttpGet] [DnnAuthorize] + [ForumsAuthorize(SecureActions.View)] public HttpResponseMessage SubscriberCount(int forumId, int topicId) { try @@ -118,6 +119,7 @@ public HttpResponseMessage SubscriberCount(int forumId, int topicId) #pragma warning restore CS1570 [HttpGet] [DnnAuthorize] + [ForumsAuthorize(SecureActions.View)] public HttpResponseMessage SubscriberCountString(int forumId, int topicId) { try From b069627970e8931421e30912a0d3921675493836 Mon Sep 17 00:00:00 2001 From: John Henley Date: Thu, 9 Oct 2025 21:51:52 +0000 Subject: [PATCH 10/20] TASK: Correct/standardize user's TopicCount/ReplyCount #1599 --- .../Controllers/ForumUserController.cs | 33 +++-- .../Controllers/ReplyController.cs | 7 + .../Controllers/TopicController.cs | 12 +- Dnn.CommunityForums/Entities/ForumInfo.cs | 3 +- .../sql/09.02.00.SqlDataProvider | 126 ++++++++++++++++++ 5 files changed, 160 insertions(+), 21 deletions(-) diff --git a/Dnn.CommunityForums/Controllers/ForumUserController.cs b/Dnn.CommunityForums/Controllers/ForumUserController.cs index 6b9a48d80..fe88c5303 100644 --- a/Dnn.CommunityForums/Controllers/ForumUserController.cs +++ b/Dnn.CommunityForums/Controllers/ForumUserController.cs @@ -27,18 +27,10 @@ namespace DotNetNuke.Modules.ActiveForums.Controllers using System.Web; using System.Web.UI.WebControls; using DotNetNuke.Data; - using DotNetNuke.Data; - using DotNetNuke.Entities.Portals; using DotNetNuke.Entities.Portals; using DotNetNuke.Entities.Users; - using DotNetNuke.Entities.Users; - using DotNetNuke.Services.GeneratedImage; - using DotNetNuke.Services.Journal; using DotNetNuke.Services.Journal; using DotNetNuke.Services.Log.EventLog; - using DotNetNuke.Services.Log.EventLog; - using DotNetNuke.Services.Social.Notifications; - using DotNetNuke.UI.UserControls; internal class ForumUserController : DotNetNuke.Modules.ActiveForums.Controllers.RepositoryControllerBase { @@ -222,11 +214,13 @@ public static int Save(DotNetNuke.Modules.ActiveForums.Entities.ForumUserInfo us return forumUser.UserId; } + [Obsolete("Deprecated in Community Forums. Removing in 10.00.00. Not Needed.")] public bool GetUserIsAdmin(int portalId, int moduleId, int userId) { return this.GetByUserId(portalId, userId).IsAdmin; } + [Obsolete("Deprecated in Community Forums. Removing in 10.00.00. Not Needed.")] public bool GetUserIsSuperUser(int portalId, int moduleId, int userId) { return this.GetByUserId(portalId, userId).IsSuperUser; @@ -526,17 +520,30 @@ internal static string GetAvatar(PortalSettings portalSettings, int userId, int internal static void UpdateUserTopicCount(int portalId, int userId) { - string sSql = "UPDATE {databaseOwner}{objectQualifier}activeforums_UserProfiles SET TopicCount = ISNULL((Select Count(t.TopicId) FROM "; - sSql += "{databaseOwner}{objectQualifier}activeforums_Topics as t INNER JOIN "; - sSql += "{databaseOwner}{objectQualifier}activeforums_Content as c ON t.ContentId = c.ContentId AND c.AuthorId = @1 INNER JOIN "; - sSql += "{databaseOwner}{objectQualifier}activeforums_ForumTopics as ft ON ft.TopicId = t.TopicId INNER JOIN "; - sSql += "{databaseOwner}{objectQualifier}activeforums_Forums as f ON ft.ForumId = f.ForumId "; + string sSql = "UPDATE {databaseOwner}{objectQualifier}activeforums_UserProfiles SET TopicCount = ISNULL((SELECT COUNT(t.TopicId) "; + sSql += "FROM {databaseOwner}{objectQualifier}activeforums_Topics as t "; + sSql += "INNER JOIN {databaseOwner}{objectQualifier}activeforums_Content as c ON c.ContentId = t.ContentId AND c.AuthorId = @1 "; + sSql += "INNER JOIN {databaseOwner}{objectQualifier}activeforums_ForumTopics as ft ON ft.TopicId = t.TopicId "; + sSql += "INNER JOIN {databaseOwner}{objectQualifier}activeforums_Forums as f ON f.ForumId = ft.ForumId "; sSql += "WHERE c.AuthorId = @1 AND t.IsApproved = 1 AND t.IsDeleted=0 AND f.PortalId=@0),0) "; sSql += "WHERE UserId = @1 AND PortalId = @0"; DataContext.Instance().Execute(System.Data.CommandType.Text, sSql, portalId, userId); DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.ClearCache(portalId, userId); } + internal static void UpdateUserReplyCount(int portalId, int userId) + { + string sSql = "UPDATE {databaseOwner}{objectQualifier}activeforums_UserProfiles SET ReplyCount = ISNULL((SELECT COUNT(r.ReplyId) "; + sSql += "FROM {databaseOwner}{objectQualifier}activeforums_Replies as r "; + sSql += "INNER JOIN {databaseOwner}{objectQualifier}activeforums_Content as c ON c.ContentId = r.ContentId AND c.AuthorId = @1 "; + sSql += "INNER JOIN {databaseOwner}{objectQualifier}activeforums_ForumTopics as ft ON ft.TopicId = r.TopicId "; + sSql += "INNER JOIN {databaseOwner}{objectQualifier}activeforums_Forums as f ON f.ForumId = ft.ForumId "; + sSql += "WHERE c.AuthorId = @1 AND r.IsApproved = 1 AND r.IsDeleted=0 AND f.PortalId=@0),0) "; + sSql += "WHERE UserId = @1 AND PortalId = @0"; + DataContext.Instance().Execute(System.Data.CommandType.Text, sSql, portalId, userId); + DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.ClearCache(portalId, userId); + } + internal string GetUsersOnline(DotNetNuke.Entities.Portals.PortalSettings portalSettings, DotNetNuke.Modules.ActiveForums.ModuleSettings mainSettings, int moduleId, DotNetNuke.Modules.ActiveForums.Entities.ForumUserInfo forumUser) { bool isAdmin = forumUser.IsAdmin || forumUser.IsSuperUser; diff --git a/Dnn.CommunityForums/Controllers/ReplyController.cs b/Dnn.CommunityForums/Controllers/ReplyController.cs index 21c024985..839919fd3 100644 --- a/Dnn.CommunityForums/Controllers/ReplyController.cs +++ b/Dnn.CommunityForums/Controllers/ReplyController.cs @@ -28,6 +28,7 @@ namespace DotNetNuke.Modules.ActiveForums.Controllers using DotNetNuke.Collections; using DotNetNuke.Modules.ActiveForums.Enums; using DotNetNuke.Modules.ActiveForums.Services.ProcessQueue; + using DotNetNuke.Modules.ActiveForums.ViewModels; using DotNetNuke.Services.FileSystem; using DotNetNuke.Services.Log.EventLog; @@ -319,6 +320,12 @@ internal static bool ProcessApprovedReplyAfterAction(int portalId, int tabId, in pqc.Add(ProcessType.UpdateForumLastUpdated, portalId, tabId: tabId, moduleId: moduleId, forumGroupId: forumGroupId, forumId: forumId, topicId: topicId, replyId: replyId, contentId: contentId, authorId: authorId, userId: userId, requestUrl: requestUrl); Utilities.UpdateModuleLastContentModifiedOnDate(moduleId); + + if (reply.IsApproved && reply.Content.AuthorId > 0) + { + DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.UpdateUserReplyCount(portalId, reply.Content.AuthorId); + } + return true; } catch (Exception ex) diff --git a/Dnn.CommunityForums/Controllers/TopicController.cs b/Dnn.CommunityForums/Controllers/TopicController.cs index 92714a6f2..0100e15ac 100644 --- a/Dnn.CommunityForums/Controllers/TopicController.cs +++ b/Dnn.CommunityForums/Controllers/TopicController.cs @@ -265,13 +265,6 @@ public static int Save(DotNetNuke.Modules.ActiveForums.Entities.TopicInfo ti) ti.Content.DateCreated = DateTime.UtcNow; } - if (ti.IsApproved && ti.Author.AuthorId > 0) - { - // TODO: put this in a better place and make it consistent with reply counter - DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.UpdateUserTopicCount(ti.Forum.PortalId, ti.Author.AuthorId); - } - - DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.ClearCache(ti.Forum.PortalId, ti.Content.AuthorId); Utilities.UpdateModuleLastContentModifiedOnDate(ti.ModuleId); DotNetNuke.Modules.ActiveForums.DataCache.ContentCacheClearForForum(ti.ModuleId, ti.ForumId); DotNetNuke.Modules.ActiveForums.DataCache.ContentCacheClearForTopic(ti.ModuleId, ti.TopicId); @@ -391,6 +384,11 @@ internal static bool ProcessApprovedTopicAfterAction(int portalId, int tabId, in Utilities.UpdateModuleLastContentModifiedOnDate(moduleId); + if (topic.IsApproved && topic.Content.AuthorId > 0) + { + DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.UpdateUserTopicCount(portalId, topic.Content.AuthorId); + } + return true; } catch (Exception ex) diff --git a/Dnn.CommunityForums/Entities/ForumInfo.cs b/Dnn.CommunityForums/Entities/ForumInfo.cs index 7de1323a8..5f676fa97 100644 --- a/Dnn.CommunityForums/Entities/ForumInfo.cs +++ b/Dnn.CommunityForums/Entities/ForumInfo.cs @@ -908,7 +908,8 @@ public string GetProperty(string propertyName, string format, System.Globalizati case "lastpostdisplayname": case "lastpostauthordisplayname": var forumUserController = new Controllers.ForumUserController(this.ModuleId); - return this.LastPostID > 0 && this.LastPostUserID > 0 ? PropertyAccess.FormatString(Controllers.ForumUserController.GetDisplayName(this.PortalSettings, this.MainSettings, forumUserController.GetByUserId(accessingUser.PortalID, accessingUser.UserID).GetIsMod(this.ModuleId), forumUserController.GetUserIsAdmin(accessingUser.PortalID, this.ModuleId, accessingUser.UserID) || forumUserController.GetUserIsSuperUser(accessingUser.PortalID, this.ModuleId, accessingUser.UserID), this.LastPostUserID, this.LastPostUserName, this.LastPostFirstName, this.LastPostLastName, this.LastPostDisplayName).Replace("&#", "&#").Replace("Anonymous", this.LastPostDisplayName), format) : string.Empty; + var forumUser = forumUserController.GetByUserId(accessingUser.PortalID, accessingUser.UserID); + return this.LastPostID > 0 && this.LastPostUserID > 0 ? PropertyAccess.FormatString(Controllers.ForumUserController.GetDisplayName(this.PortalSettings, this.MainSettings, forumUser.GetIsMod(this.ModuleId), forumUser.IsAdmin || forumUser.IsSuperUser, this.LastPostUserID, this.LastPostUserName, this.LastPostFirstName, this.LastPostLastName, this.LastPostDisplayName).Replace("&#", "&#").Replace("Anonymous", this.LastPostDisplayName), format) : string.Empty; case "statuscssclass": return PropertyAccess.FormatString(this.GetForumStatusCss(new Controllers.ForumUserController(this.ModuleId).GetByUserId(accessingUser.PortalID, accessingUser.UserID)), format); diff --git a/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider b/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider index 3e162ab57..bbc51b47f 100644 --- a/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider +++ b/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider @@ -1136,3 +1136,129 @@ GO /* Issue 1594 - End - update activeforums_Topics_Move procedure to remove previously-removed LastPostId from activeforums_Forums */ /* --------------------- */ + + + +/* issue 1599 - begin - don't update UserProfile Reply count from activeforums_Reply_Save */ + +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Reply_Save]') AND type in (N'P', N'PC')) +DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Reply_Save] +GO + +CREATE PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Reply_Save] +@PortalId int, +@TopicId int, +@ReplyId int, +@ReplyToId int, +@StatusId int, +@IsApproved bit, +@IsDeleted bit, +@Subject nvarchar(255), +@Body nvarchar(max), +@DateCreated datetime, +@DateUpdated datetime, +@AuthorId int, +@AuthorName nvarchar(150), +@IPAddress nvarchar(50) +AS +DECLARE @ContentId int +DECLARE @IsEdit bit +SET @IsEdit = 0 +DECLARE @ApprovedStatus bit +SET @ApprovedStatus = @IsApproved + +-- This part is a work around for Quick Reply feature not working for Tapatalk STARTS + +DECLARE @TopicSubject NVARCHAR(255) = ( + SELECT top 1 afc.Subject FROM {databaseOwner}[{objectQualifier}activeforums_Topics] aft + JOIN {databaseOwner}[{objectQualifier}activeforums_Content] afc ON aft.ContentId = afc.ContentId + WHERE TopicId = @TopicId + ) + +SET @Subject = ISNULL(NULLIF(@Subject, ''), 'RE: ' + @TopicSubject) + +IF (@Subject NOT LIKE 'RE:%') +BEGIN + SET @Subject = 'RE: ' + @Subject +END +-- This part is a work around for Quick Reply feature not working for Tapatalk ENDS + + +IF EXISTS(SELECT ContentId FROM {databaseOwner}{objectQualifier}activeforums_Replies WHERE ReplyId = @ReplyId) +BEGIN + SELECT @ContentId = ContentId, @ApprovedStatus = IsApproved FROM {databaseOwner}{objectQualifier}activeforums_Replies WHERE ReplyId = @ReplyId + + BEGIN + SET @IsEdit = 1 + UPDATE {databaseOwner}{objectQualifier}activeforums_Content + SET Subject = @Subject, + Body = @Body, + DateCreated = @DateCreated, + DateUpdated = @DateUpdated, + AuthorId = @AuthorId, + AuthorName = @AuthorName, + IsDeleted = @IsDeleted, + IPAddress = @IPAddress + WHERE ContentId = @ContentId + UPDATE {databaseOwner}{objectQualifier}activeforums_Replies + SET StatusId = @StatusId, + TopicId = @TopicId, + IsApproved = @IsApproved, + IsDeleted = @IsDeleted, + ReplyToId = @ReplyToId + WHERE ReplyId = @ReplyId +END + END +ELSE +--INSERT +BEGIN + BEGIN + INSERT INTO {databaseOwner}{objectQualifier}activeforums_Content + (Subject, Body, DateCreated, DateUpdated, AuthorId, AuthorName, IsDeleted, IPAddress) + VALUES + (@Subject, @Body, @DateCreated, @DateUpdated, @AuthorId, @AuthorName, @IsDeleted, @IPAddress) + SET @ContentId = SCOPE_IDENTITY() + END + BEGIN + INSERT INTO {databaseOwner}{objectQualifier}activeforums_Replies + (ContentId, TopicId, StatusId, IsApproved, IsDeleted, ReplyToId) + VALUES + (@ContentId, @TopicId, @StatusId, @IsApproved, @IsDeleted, @ReplyToId) + SET @ReplyId = SCOPE_IDENTITY() + + END + + +END +IF @IsApproved = 1 + BEGIN + DECLARE @ForumId int + SELECT @ForumId = ForumId FROM {databaseOwner}{objectQualifier}activeforums_ForumTopics WHERE TopicId = @TopicId + DECLARE @TotalReplies int + SET @TotalReplies = (SELECT Count(ReplyId) from {databaseOwner}{objectQualifier}activeforums_replies as r inner join {databaseOwner}{objectQualifier}activeforums_topics as t on t.topicid = r.topicid and r.isapproved = 1 and r.isdeleted = 0 INNER JOIN {databaseOwner}{objectQualifier}activeforums_forumtopics as ft on t.topicid = ft.topicid WHERE ft.forumid = @ForumId) + UPDATE {databaseOwner}{objectQualifier}activeforums_Forums + SET LastTopicId = IsNull(@TopicId,0), LastReplyId = IsNull(@ReplyId,0), TotalReplies = ISNULL(@TotalReplies,0) + WHERE ForumId = @ForumId + UPDATE {databaseOwner}{objectQualifier}activeforums_Topics + SET ReplyCount = (Select Count(ReplyId) from {databaseOwner}{objectQualifier}activeforums_Replies WHERE TopicId = @TopicId AND IsDeleted = 0 AND IsApproved = 1) + WHERE TopicId = @TopicId + END + + +/* populate ModuleId in activeforums_Content */ +UPDATE c +SET c.ModuleId = f.ModuleId +FROM {databaseOwner}[{objectQualifier}activeforums_Content] c +LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Replies] r +ON r.ContentId = c.ContentId +LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_ForumTopics] ft +ON ft.TopicId = r.TopicId +LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f +ON f.ForumId = ft.ForumId +WHERE c.ModuleId IS NULL AND r.ReplyId = @ReplyId + + +SELECT @ReplyId +GO +/* issue 1599 - end - don't update UserProfile Reply count from activeforums_Reply_Save */ +/* --------------------- */ From 866ec271dfd4a813f5a9b101cf9526c3ae2aaeac Mon Sep 17 00:00:00 2001 From: John Henley Date: Tue, 8 Jul 2025 14:58:20 +0000 Subject: [PATCH 11/20] ENH: Implements user badge feature TASK: Create database objects to support badges #1480 TASK: Create UI for administrator to manually assigned badges #1485 TASK: Badge assignment process #1484 TASK: Add badge metric name to control panel badge list #147 TASK: User profile UI to show badges #1486 TASK: Add badge management to control panel #1483 TASK: Create default badges during install or upgrade #1488 TASK: Badge token replacement logic #1482 TASK: Add BadgeId to Process queue #1487 TASK: Add badge notification option to user profile #1486 TASK: Manual badge assignment UI for moderators #1485 TASK: Web API seucrity checking "ForumsAuthorizeAttribute" for certain functions (e.g. Ban) should not require forumId to be passed to the API #1507 --- .../ControlPanel.ascx.fr-FR.resx | 57 + .../ControlPanel.ascx.it-IT.resx | 57 + .../ControlPanel.ascx.nl-NL.resx | 57 + .../App_LocalResources/ControlPanel.ascx.resx | 57 + .../Controlpanel.ascx.de-DE.resx | 57 + .../Controlpanel.ascx.es-ES.resx | 57 + .../SharedResources.de-DE.resx | 33 + .../SharedResources.es-ES.resx | 33 + .../SharedResources.fr-FR.resx | 33 + .../SharedResources.it-IT.resx | 33 + .../SharedResources.nl-NL.resx | 33 + .../App_LocalResources/SharedResources.resx | 33 + Dnn.CommunityForums/Classic.ascx.cs | 21 + Dnn.CommunityForums/ControlPanel.ascx | 1 + Dnn.CommunityForums/ControlPanel.ascx.cs | 24 +- .../Controllers/BadgeController.cs | 86 ++ .../Controllers/ForumController.cs | 8 +- .../Controllers/ForumUserController.cs | 55 +- .../Controllers/LikeController.cs | 1 + .../Controllers/ProcessQueueController.cs | 10 +- .../Controllers/ReplyController.cs | 15 +- .../Controllers/RepositoryControllerBase.cs | 10 +- .../Controllers/TopicController.cs | 24 +- .../Controllers/TopicTrackingController.cs | 13 + .../Controllers/UserBadgeController.cs | 280 ++++ Dnn.CommunityForums/DnnCommunityForums.csproj | 19 +- Dnn.CommunityForums/DnnCommunityForums.dnn | 9 +- Dnn.CommunityForums/Entities/BadgeInfo.cs | 121 ++ Dnn.CommunityForums/Entities/ForumInfo.cs | 7 +- Dnn.CommunityForums/Entities/ForumUserInfo.cs | 92 +- Dnn.CommunityForums/Entities/LikeInfo.cs | 2 + .../Entities/ProcessQueueInfo.cs | 2 + Dnn.CommunityForums/Entities/UserBadgeInfo.cs | 216 +++ Dnn.CommunityForums/Enums/BadgeMetric.cs | 32 + Dnn.CommunityForums/Enums/TemplateType.cs | 3 + .../SqlDataProvider/SqlDataProvider.cs | 7 + Dnn.CommunityForums/ReleaseNotes.txt | 1 - .../Services/Avatars/AvatarRefreshQueue.cs | 49 +- .../Services/Badges/BadgeAwardQueue.cs | 193 +++ .../Services/Controllers/TopicController.cs | 1 + .../Controllers/UserBadgeController.cs | 102 ++ Dnn.CommunityForums/Services/ProcessQueue.cs | 3 + Dnn.CommunityForums/Services/ProcessType.cs | 1 + .../Tokens/ForumsModuleTokenReplacer.cs | 1 + .../Services/Tokens/TokenReplacer.cs | 51 +- Dnn.CommunityForums/ViewModels/Permissions.cs | 74 +- Dnn.CommunityForums/class/DataProvider.cs | 4 + Dnn.CommunityForums/class/ForumsConfig.cs | 98 ++ Dnn.CommunityForums/class/Globals.cs | 14 + Dnn.CommunityForums/class/Utilities.cs | 10 +- .../components/Extensions/ReWriter.cs | 6 + .../components/Topics/TopicsController.cs | 14 + .../config/defaultsetup.config | 17 +- .../templates/BadgeNotificationBody.ascx | 5 + .../templates/BadgeNotificationSubject.ascx | 1 + .../config/templates/ProfileInfo.ascx | 4 + .../config/templates/UserBadge.ascx | 8 + .../controls/admin_badges.ascx | 254 ++++ .../controls/admin_badges.ascx.cs | 103 ++ .../controls/admin_categories.ascx | 2 +- .../controls/admin_ranks.ascx.cs | 81 -- .../controls/af_assign_badge_users.ascx | 31 + .../controls/af_assign_badge_users.ascx.cs | 130 ++ .../controls/af_assign_user_badges.ascx | 32 + .../controls/af_assign_user_badges.ascx.cs | 125 ++ .../controls/af_topicscripts.ascx | 3 +- .../controls/af_topicscripts.ascx.cs | 8 +- .../controls/profile_mypreferences.ascx | 6 +- .../controls/profile_mypreferences.ascx.cs | 16 + .../profile_mypreferences.ascx.designer.cs | 111 -- .../handlers/adminhelper.ashx.cs | 164 ++- .../images/badges/AvidPoster.png | Bin 0 -> 577 bytes .../images/badges/AvidReader.png | Bin 0 -> 1306 bytes .../images/badges/DedicatedUser.png | Bin 0 -> 2095 bytes .../images/badges/EngagedPoster.png | Bin 0 -> 969 bytes .../images/badges/EngagedReader.png | Bin 0 -> 1371 bytes .../images/badges/HelpfulReplier.png | Bin 0 -> 1409 bytes .../images/badges/LifeSaver.png | Bin 0 -> 1084 bytes Dnn.CommunityForums/images/badges/MVP.png | Bin 0 -> 1678 bytes .../images/badges/MostLiked.png | Bin 0 -> 1633 bytes .../images/badges/NewMember.png | Bin 0 -> 1393 bytes .../images/badges/NewPoster.png | Bin 0 -> 1244 bytes Dnn.CommunityForums/images/badges32.png | Bin 0 -> 1078 bytes Dnn.CommunityForums/module.css | 13 +- Dnn.CommunityForums/scripts/afcommon.js | 20 + Dnn.CommunityForums/scripts/usereditor.js | 28 + .../sql/09.01.00.SqlDataProvider | 12 +- .../sql/09.02.00.SqlDataProvider | 1196 ++++++++++++++++- .../sql/Uninstall.SqlDataProvider | 17 +- .../templates/ProfileInfo.ascx | 3 + .../templates/ProfileInfo.ascx | 3 + DnnCommunityForums.sln | 5 - 92 files changed, 4233 insertions(+), 385 deletions(-) create mode 100644 Dnn.CommunityForums/Controllers/BadgeController.cs create mode 100644 Dnn.CommunityForums/Controllers/UserBadgeController.cs create mode 100644 Dnn.CommunityForums/Entities/BadgeInfo.cs create mode 100644 Dnn.CommunityForums/Entities/UserBadgeInfo.cs create mode 100644 Dnn.CommunityForums/Enums/BadgeMetric.cs create mode 100644 Dnn.CommunityForums/Services/Badges/BadgeAwardQueue.cs create mode 100644 Dnn.CommunityForums/Services/Controllers/UserBadgeController.cs create mode 100644 Dnn.CommunityForums/config/templates/BadgeNotificationBody.ascx create mode 100644 Dnn.CommunityForums/config/templates/BadgeNotificationSubject.ascx create mode 100644 Dnn.CommunityForums/config/templates/UserBadge.ascx create mode 100644 Dnn.CommunityForums/controls/admin_badges.ascx create mode 100644 Dnn.CommunityForums/controls/admin_badges.ascx.cs delete mode 100644 Dnn.CommunityForums/controls/admin_ranks.ascx.cs create mode 100644 Dnn.CommunityForums/controls/af_assign_badge_users.ascx create mode 100644 Dnn.CommunityForums/controls/af_assign_badge_users.ascx.cs create mode 100644 Dnn.CommunityForums/controls/af_assign_user_badges.ascx create mode 100644 Dnn.CommunityForums/controls/af_assign_user_badges.ascx.cs delete mode 100644 Dnn.CommunityForums/controls/profile_mypreferences.ascx.designer.cs create mode 100644 Dnn.CommunityForums/images/badges/AvidPoster.png create mode 100644 Dnn.CommunityForums/images/badges/AvidReader.png create mode 100644 Dnn.CommunityForums/images/badges/DedicatedUser.png create mode 100644 Dnn.CommunityForums/images/badges/EngagedPoster.png create mode 100644 Dnn.CommunityForums/images/badges/EngagedReader.png create mode 100644 Dnn.CommunityForums/images/badges/HelpfulReplier.png create mode 100644 Dnn.CommunityForums/images/badges/LifeSaver.png create mode 100644 Dnn.CommunityForums/images/badges/MVP.png create mode 100644 Dnn.CommunityForums/images/badges/MostLiked.png create mode 100644 Dnn.CommunityForums/images/badges/NewMember.png create mode 100644 Dnn.CommunityForums/images/badges/NewPoster.png create mode 100644 Dnn.CommunityForums/images/badges32.png diff --git a/Dnn.CommunityForums/App_LocalResources/ControlPanel.ascx.fr-FR.resx b/Dnn.CommunityForums/App_LocalResources/ControlPanel.ascx.fr-FR.resx index ff4941278..10cb9dfc6 100644 --- a/Dnn.CommunityForums/App_LocalResources/ControlPanel.ascx.fr-FR.resx +++ b/Dnn.CommunityForums/App_LocalResources/ControlPanel.ascx.fr-FR.resx @@ -1483,4 +1483,61 @@ Votre méthode de suppression est actuellement définie sur {0}. Vos sujets ser Entrez une chaîne à utiliser lors de la récupération des modèles. Par exemple, si vous souhaitez disposer de fichiers de modèle distincts pour les forums modérés, entrez « modéré », puis les modèles seront récupérés à l’aide de « modéré » dans le nom de fichier, par exemple « TopicsView-moderated.ascx » plutôt que simplement « TopicsView.ascx » lorsque le modèle TopicsView est récupéré. + + Description + + + Insigne + + + Ordre de tri + + + Badges + + + Insigne + + + Nouveau badge + + + Seuil + + + Métrique + + + Image + + + Nouvel utilisateur + + + Sujets créés + + + Réponses aux rubriques + + + J’aime reçus + + + Sujets lus + + + Mettre à jour les utilisateurs + + + Balisage HTML pour badge (par exemple, font-awesome) + + + L’utilisateur ne peut gagner un badge qu’une seule fois + + + # de jours entre l’obtention de ce badge + + + Prix du manuel + \ No newline at end of file diff --git a/Dnn.CommunityForums/App_LocalResources/ControlPanel.ascx.it-IT.resx b/Dnn.CommunityForums/App_LocalResources/ControlPanel.ascx.it-IT.resx index 5df13a5c1..a83e6f427 100644 --- a/Dnn.CommunityForums/App_LocalResources/ControlPanel.ascx.it-IT.resx +++ b/Dnn.CommunityForums/App_LocalResources/ControlPanel.ascx.it-IT.resx @@ -1480,4 +1480,61 @@ Il metodo di rimozione è attualmente impostato su {0}. I tuoi argomenti verran Immettere una stringa da utilizzare per il recupero dei modelli. Ad esempio, se si desidera avere file modello separati per i forum moderati, immettere "moderato" e quindi i modelli verranno recuperati utilizzando "moderato" come parte del nome del file, ad esempio "TopicsView-moderated.ascx" anziché solo "TopicsView.ascx" quando viene recuperato il modello TopicsView. + + Descrizione + + + Distintivo + + + Ordinamento + + + Distintivi + + + Distintivo + + + Nuovo distintivo + + + Soglia + + + Metrico + + + Immagine + + + Nuovo utente + + + Argomenti creati + + + Risposta agli argomenti + + + Mi piace ricevuti + + + Argomenti Leggi + + + Aggiorna utenti + + + Markup HTML per badge (ad esempio, font-awesome) + + + L'utente può guadagnare il badge una sola volta + + + # di giorni tra l'ottenimento di questo distintivo + + + Premio Manuale + \ No newline at end of file diff --git a/Dnn.CommunityForums/App_LocalResources/ControlPanel.ascx.nl-NL.resx b/Dnn.CommunityForums/App_LocalResources/ControlPanel.ascx.nl-NL.resx index f895e4352..19a341a7e 100644 --- a/Dnn.CommunityForums/App_LocalResources/ControlPanel.ascx.nl-NL.resx +++ b/Dnn.CommunityForums/App_LocalResources/ControlPanel.ascx.nl-NL.resx @@ -1630,4 +1630,61 @@ De verwijder-methode is momenteel ingesteld op "{0}". Uw onderwerpen worden {1} Voer een tekenreeks in die moet worden gebruikt bij het ophalen van sjablonen. Als u bijvoorbeeld aparte sjabloonbestanden wilt hebben voor gemodereerde forums, voert u 'gemodereerd' in, waarna sjablonen worden opgehaald met 'gemodereerd' als onderdeel van de bestandsnaam, bijvoorbeeld 'TopicsView-moderated.ascx' in plaats van alleen 'TopicsView.ascx' wanneer het TopicsView-sjabloon wordt opgehaald. + + Beschrijving + + + Insigne + + + Sorteervolgorde + + + Badges + + + Insigne + + + Nieuwe badge + + + Drempel + + + Metriek + + + Beeld + + + Nieuwe gebruiker + + + Onderwerpen gemaakt + + + Gereageerd op onderwerpen + + + Likes ontvangen + + + Onderwerpen Lezen + + + Gebruikers bijwerken + + + HTML-opmaak voor badge (bijv. lettertype-geweldig) + + + De gebruiker kan slechts één keer een badge verdienen + + + # dagen tussen het verdienen van deze badge + + + Handleiding Award + \ No newline at end of file diff --git a/Dnn.CommunityForums/App_LocalResources/ControlPanel.ascx.resx b/Dnn.CommunityForums/App_LocalResources/ControlPanel.ascx.resx index 29b30e2e0..250f424b5 100644 --- a/Dnn.CommunityForums/App_LocalResources/ControlPanel.ascx.resx +++ b/Dnn.CommunityForums/App_LocalResources/ControlPanel.ascx.resx @@ -1585,4 +1585,61 @@ Your removal method is currently set to {0}. Your topics will be {1} based upon Enter a string to be used when retrieving templates. For example, if you want to have separate template files for moderated forums, enter 'moderated', and then templates will be retrieved using 'moderated' as part of the filename, e.g. 'TopicsView-moderated.ascx' rather than just 'TopicsView.ascx' when the TopicsView template is retrieved. + + Badge + + + Sort Order + + + Badges + + + Badge + + + New Badge + + + Threshold + + + Metric + + + Image + + + Manual Award + + + Description + + + New User + + + Topics Created + + + Replied to Topics + + + Likes Received + + + Topics Read + + + Update Users + + + HTML markup for badge (e.g., font-awesome) + + + User can only earn badge one time + + + # of days between earning this badge + \ No newline at end of file diff --git a/Dnn.CommunityForums/App_LocalResources/Controlpanel.ascx.de-DE.resx b/Dnn.CommunityForums/App_LocalResources/Controlpanel.ascx.de-DE.resx index 35ece8151..5055f1517 100644 --- a/Dnn.CommunityForums/App_LocalResources/Controlpanel.ascx.de-DE.resx +++ b/Dnn.CommunityForums/App_LocalResources/Controlpanel.ascx.de-DE.resx @@ -1585,4 +1585,61 @@ Ihre Entfernungsmethode ist derzeit auf {0} eingestellt. Ihre Themen werden anh Geben Sie eine Zeichenfolge ein, die beim Abrufen von Vorlagen verwendet werden soll. Wenn Sie z. B. separate Vorlagendateien für moderierte Foren haben möchten, geben Sie "moderiert" ein, und dann werden die Vorlagen mit "moderiert" als Teil des Dateinamens abgerufen, z. B. "TopicsView-moderated.ascx" und nicht nur "TopicsView.ascx", wenn die TopicsView-Vorlage abgerufen wird. + + Beschreibung + + + Abzeichen + + + Sortierreihenfolge + + + Kennzeichen + + + Abzeichen + + + Neues Abzeichen + + + Schwelle + + + Metrik + + + Bild + + + Neuer Benutzer + + + Erstellte Themen + + + Auf Themen geantwortet + + + Erhaltene "Gefällt mir"-Angaben + + + Gelesene Themen + + + Aktualisieren von Benutzern + + + HTML-Markup für Badge (z. B. font-awesome) + + + Der Benutzer kann das Abzeichen nur einmal verdienen + + + # der Tage zwischen dem Erhalt dieses Abzeichens + + + Manuelle Auszeichnung + \ No newline at end of file diff --git a/Dnn.CommunityForums/App_LocalResources/Controlpanel.ascx.es-ES.resx b/Dnn.CommunityForums/App_LocalResources/Controlpanel.ascx.es-ES.resx index 4e27b4a99..df0b5b4e8 100644 --- a/Dnn.CommunityForums/App_LocalResources/Controlpanel.ascx.es-ES.resx +++ b/Dnn.CommunityForums/App_LocalResources/Controlpanel.ascx.es-ES.resx @@ -1480,4 +1480,61 @@ El método de eliminación está configurado actualmente en {0}. Los temas se { Introduzca una cadena que se utilizará al recuperar plantillas. Por ejemplo, si desea tener archivos de plantilla separados para foros moderados, escriba 'moderados' y luego las plantillas se recuperarán usando 'moderados' como parte del nombre del archivo, por ejemplo, 'TopicsView-moderated.ascx' en lugar de solo 'TopicsView.ascx' cuando se recupere la plantilla TopicsView. + + Descripción + + + Insignia + + + Criterio de clasificación + + + Insignias + + + Insignia + + + Nueva insignia + + + Umbral + + + Métrico + + + Imagen + + + Nuevo usuario + + + Temas creados + + + Respondido a los temas + + + Me gusta recibidos + + + Temas leídos + + + Actualizar usuarios + + + Marcado HTML para insignia (por ejemplo, font-awesome) + + + El usuario solo puede ganar insignia una vez + + + # de días entre la obtención de esta insignia + + + Premio Manual + \ No newline at end of file diff --git a/Dnn.CommunityForums/App_LocalResources/SharedResources.de-DE.resx b/Dnn.CommunityForums/App_LocalResources/SharedResources.de-DE.resx index 1e06588d5..fc567bfca 100644 --- a/Dnn.CommunityForums/App_LocalResources/SharedResources.de-DE.resx +++ b/Dnn.CommunityForums/App_LocalResources/SharedResources.de-DE.resx @@ -1862,4 +1862,37 @@ Von Automatisches Abonnieren von "Meine Themen" + + Erhalten Sie Benachrichtigungen über Abzeichenauszeichnungen + + + Wählen Sie diese Option aus, wenn Sie Benachrichtigungen erhalten möchten, wenn Sie ein neues Erfolgsabzeichen erhalten. + + + Glückwunsch! Sie wurden mit einem neuen Abzeichen belohnt! + + + [DCF:FORENLINK|Bitte <a href="{0}">besuchen Sie</a> , um weiter teilzunehmen und weitere Belohnungen zu erhalten.] + + + Senden Sie dem Benutzer eine Benachrichtigung, wenn er vergeben wird + + + Senden Sie einem älteren Benutzer keine Benachrichtigung, wenn Sie Prämien auffüllen + + + Zuletzt verliehen + + + Abzeichen + + + Benutzer, die mit dem Abzeichen ausgezeichnet wurden: {0} + + + Abzeichen für Benutzer: {0} + + + Badge noch nicht zugewiesen + \ No newline at end of file diff --git a/Dnn.CommunityForums/App_LocalResources/SharedResources.es-ES.resx b/Dnn.CommunityForums/App_LocalResources/SharedResources.es-ES.resx index 5ed99899e..1699a9c59 100644 --- a/Dnn.CommunityForums/App_LocalResources/SharedResources.es-ES.resx +++ b/Dnn.CommunityForums/App_LocalResources/SharedResources.es-ES.resx @@ -1861,4 +1861,37 @@ De Suscríbete automáticamente a Mis temas + + Recibir notificaciones de premios de insignias + + + Seleccione esta opción si desea recibir notificaciones cuando se le otorgue una nueva insignia de logro. + + + ¡Felicidades! ¡Has sido recompensado con una nueva insignia! + + + [DCF:FORUMSLINK| <a href="{0}">Visite</a> para seguir participando y ganar más recompensas.] + + + Enviar una notificación al usuario cuando se otorgue + + + No envíes una notificación a un usuario mayor cuando rellenes premios + + + Última adjudicación + + + Insignia + + + Usuarios galardonados con la insignia: {0} + + + Insignias otorgadas al Usuario: {0} + + + Insignia aún no asignada + \ No newline at end of file diff --git a/Dnn.CommunityForums/App_LocalResources/SharedResources.fr-FR.resx b/Dnn.CommunityForums/App_LocalResources/SharedResources.fr-FR.resx index 2d6842640..030347b82 100644 --- a/Dnn.CommunityForums/App_LocalResources/SharedResources.fr-FR.resx +++ b/Dnn.CommunityForums/App_LocalResources/SharedResources.fr-FR.resx @@ -1858,4 +1858,37 @@ De, S’abonner automatiquement à Mes sujets + + Recevoir des notifications d’attribution de badge + + + Sélectionnez cette option si vous souhaitez recevoir des notifications lorsque vous recevez un nouvel insigne de succès. + + + Félicitations! Vous avez été récompensé par un nouveau badge ! + + + [DCF :FORUMSLINK|Veuillez <a href="{0}">vous y rendre</a> pour continuer à participer et gagner plus de récompenses.] + + + Envoyer une notification à l’utilisateur lorsqu’il est attribué + + + N’envoyez pas de notification à un utilisateur plus âgé lors du rachat de récompenses + + + Dernier prix + + + Insigne + + + Utilisateurs ayant reçu le badge : {0} + + + Badges attribués à l’utilisateur : {0} + + + Badge non encore attribué + \ No newline at end of file diff --git a/Dnn.CommunityForums/App_LocalResources/SharedResources.it-IT.resx b/Dnn.CommunityForums/App_LocalResources/SharedResources.it-IT.resx index 93f69fa22..58bf45b79 100644 --- a/Dnn.CommunityForums/App_LocalResources/SharedResources.it-IT.resx +++ b/Dnn.CommunityForums/App_LocalResources/SharedResources.it-IT.resx @@ -1861,4 +1861,37 @@ Da Iscrizione automatica ai miei argomenti + + Ricevi le notifiche di assegnazione dei badge + + + Seleziona questa opzione se desideri ricevere notifiche quando ti viene assegnato un nuovo badge obiettivo. + + + Felicitazioni! Sei stato ricompensato con un nuovo distintivo! + + + [DCF:FORUMSLINK| <a href="{0}">Visita per</a> continuare a partecipare e guadagnare più premi.] + + + Invia una notifica all'utente quando viene assegnato + + + Non inviare una notifica a un utente meno recente durante il backfill dei premi + + + Ultimo premio + + + Distintivo + + + Utenti che hanno ricevuto il Badge: {0} + + + Badge assegnati all'Utente: {0} + + + Badge non ancora assegnato + \ No newline at end of file diff --git a/Dnn.CommunityForums/App_LocalResources/SharedResources.nl-NL.resx b/Dnn.CommunityForums/App_LocalResources/SharedResources.nl-NL.resx index 254dfc2c4..699b0f082 100644 --- a/Dnn.CommunityForums/App_LocalResources/SharedResources.nl-NL.resx +++ b/Dnn.CommunityForums/App_LocalResources/SharedResources.nl-NL.resx @@ -1897,4 +1897,37 @@ Van, Automatisch abonneren op Mijn onderwerpen + + Ontvang meldingen over badges + + + Selecteer deze optie als u meldingen wilt ontvangen wanneer u een nieuwe prestatiebadge krijgt. + + + Gefeliciteerd! Je bent beloond met een nieuwe badge! + + + [DCF:FORUMSLINK|Ga <a href="{0}">naar</a> om te blijven deelnemen en meer beloningen te verdienen.] + + + Stuur de gebruiker een melding wanneer deze is toegekend + + + Stuur een oudere gebruiker geen melding bij het aanvullen van awards + + + Laatst toegekend + + + Insigne + + + Gebruikers met een badge: {0} + + + Badges toegekend aan gebruiker: {0} + + + Badge nog niet toegekend + \ No newline at end of file diff --git a/Dnn.CommunityForums/App_LocalResources/SharedResources.resx b/Dnn.CommunityForums/App_LocalResources/SharedResources.resx index e1171912b..3ba630b9d 100644 --- a/Dnn.CommunityForums/App_LocalResources/SharedResources.resx +++ b/Dnn.CommunityForums/App_LocalResources/SharedResources.resx @@ -1861,4 +1861,37 @@ From, Unsubscribe + + Receive Badge Award Notifications + + + Select this option if you wish to receive notifications when you are awarded a new achievement badge. + + + Congratulations! You've been rewarded with a new badge! + + + [DCF:FORUMSLINK|Please <a href="{0}">visit</a> to keep participating and earn more rewards.] + + + last awarded + + + Send user a notification when awarded + + + Don't send an older user a notification when backfilling awards + + + Badge + + + Users awarded Badge: {0} + + + Badges awarded to User: {0} + + + Badge not yet assigned + \ No newline at end of file diff --git a/Dnn.CommunityForums/Classic.ascx.cs b/Dnn.CommunityForums/Classic.ascx.cs index 070192d8b..ad0086494 100644 --- a/Dnn.CommunityForums/Classic.ascx.cs +++ b/Dnn.CommunityForums/Classic.ascx.cs @@ -61,6 +61,7 @@ protected override void OnLoad(EventArgs e) //ForumsConfig.Upgrade_PermissionSets_090000(); //DotNetNuke.Modules.ActiveForums.Helpers.UpgradeModuleSettings.DeleteObsoleteModuleSettings_090000(); //DotNetNuke.Modules.ActiveForums.Helpers.UpgradeModuleSettings.AddAvatarModuleSettings_090100(); + //new ForumsConfig().Install_DefaultBadges_090100(); #endif @@ -102,6 +103,18 @@ protected override void OnLoad(EventArgs e) opts = $"{ParamKeys.ContentId}={this.Request.QueryString[ParamKeys.ContentId]}"; } } + else if (this.Request.Params[ParamKeys.ViewType] != null && this.Request.Params[ParamKeys.ViewType] == Views.Grid && this.Request.Params[ParamKeys.GridType] != null && this.Request.Params[ParamKeys.GridType] == Views.BadgeUsers) + { + ctl = Views.BadgeUsers; + if (this.Request.QueryString[ParamKeys.BadgeId] != null) + { + opts = $"{ParamKeys.BadgeId}={this.Request.QueryString[ParamKeys.BadgeId]}"; + } + } + else if (this.Request.Params[ParamKeys.ViewType] != null && this.Request.Params[ParamKeys.ViewType] == Views.Grid && this.Request.Params[ParamKeys.GridType] != null && this.Request.Params[ParamKeys.GridType] == Views.UserBadges) + { + ctl = Views.UserBadges; + } else if (this.Request.Params[ParamKeys.ViewType] != null) { ctl = this.Request.Params[ParamKeys.ViewType]; @@ -182,6 +195,14 @@ private void GetControl(string view, string options) { ctl = (ForumBase)this.LoadControl(this.Page.ResolveUrl(Globals.ModulePath + "controls/af_recycle_bin.ascx")); } + else if (view.ToUpperInvariant() == Views.UserBadges.ToUpperInvariant() && this.Request.IsAuthenticated) + { + ctl = (ForumBase)this.LoadControl(this.Page.ResolveUrl(Globals.ModulePath + "controls/af_assign_user_badges.ascx")); + } + else if (view.ToUpperInvariant() == Views.BadgeUsers.ToUpperInvariant() && this.Request.IsAuthenticated) + { + ctl = (ForumBase)this.LoadControl(this.Page.ResolveUrl(Globals.ModulePath + "controls/af_assign_badge_users.ascx")); + } else if (view.ToUpperInvariant() == "FORUMVIEW") { ctl = (ForumBase)new DotNetNuke.Modules.ActiveForums.Controls.ForumView(); diff --git a/Dnn.CommunityForums/ControlPanel.ascx b/Dnn.CommunityForums/ControlPanel.ascx index 6a5006706..ffcf5275d 100644 --- a/Dnn.CommunityForums/ControlPanel.ascx +++ b/Dnn.CommunityForums/ControlPanel.ascx @@ -167,6 +167,7 @@ +
    diff --git a/Dnn.CommunityForums/ControlPanel.ascx.cs b/Dnn.CommunityForums/ControlPanel.ascx.cs index ecf539c41..659320ee7 100644 --- a/Dnn.CommunityForums/ControlPanel.ascx.cs +++ b/Dnn.CommunityForums/ControlPanel.ascx.cs @@ -49,18 +49,22 @@ protected override void OnLoad(EventArgs e) this.btnReturn.ClientSideScript = "window.location.href = '" + Utilities.NavigateURL(this.TabId) + "';"; this.cbModal.LoadingTemplate = this.GetLoadingTemplateSmall(); - Hashtable settings = DotNetNuke.Entities.Modules.ModuleController.Instance.GetModule(moduleId: this.ModuleId, tabId: this.TabId, ignoreCache: false).ModuleSettings; - if (Convert.ToBoolean(settings["AFINSTALLED"]) == false) + + if (!this.Page.IsPostBack) { - try - { - var fc = new ForumsConfig(); - bool configComplete = fc.ForumsInit(this.PortalId, this.ModuleId); - DotNetNuke.Entities.Modules.ModuleController.Instance.UpdateModuleSetting(this.ModuleId, "AFINSTALLED", configComplete.ToString()); - } - catch (Exception ex) + Hashtable settings = DotNetNuke.Entities.Modules.ModuleController.Instance.GetModule(moduleId: this.ModuleId, tabId: this.TabId, ignoreCache: false).ModuleSettings; + if (Convert.ToBoolean(settings["AFINSTALLED"]) == false) { - DotNetNuke.Services.Exceptions.Exceptions.LogException(ex); + try + { + var fc = new ForumsConfig(); + bool configComplete = fc.ForumsInit(this.PortalId, this.ModuleId); + DotNetNuke.Entities.Modules.ModuleController.Instance.UpdateModuleSetting(this.ModuleId, "AFINSTALLED", configComplete.ToString()); + } + catch (Exception ex) + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(ex); + } } } diff --git a/Dnn.CommunityForums/Controllers/BadgeController.cs b/Dnn.CommunityForums/Controllers/BadgeController.cs new file mode 100644 index 000000000..2196e94aa --- /dev/null +++ b/Dnn.CommunityForums/Controllers/BadgeController.cs @@ -0,0 +1,86 @@ +// Copyright (c) by DNN Community +// +// DNN Community licenses this file to you under the MIT license. +// +// See the LICENSE file in the project root for more information. +// +// Badge is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this Badge notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +namespace DotNetNuke.Modules.ActiveForums.Controllers +{ + using System; + using System.Collections.Generic; + using System.Linq; + using DotNetNuke.Modules.ActiveForums.Entities; + using static DotNetNuke.Entities.Modules.DesktopModuleInfo; + + /// + /// Controller for managing badges in the DNN Community Forums module. + /// + internal class BadgeController : DotNetNuke.Modules.ActiveForums.Controllers.RepositoryControllerBase + { + internal override string cacheKeyTemplate => CacheKeys.BadgeInfo; + + /// + /// Gets all active badges. + /// + /// List of active badges. + public IEnumerable GetActiveBadges(int moduleId) + { + return this.Get().Where(b => b.ModuleId.Equals(moduleId)); + } + + internal DotNetNuke.Modules.ActiveForums.Entities.BadgeInfo GetById(int badgeId, int moduleId) + { + var cachekey = this.GetCacheKey(moduleId: moduleId, id: badgeId); + DotNetNuke.Modules.ActiveForums.Entities.BadgeInfo badgeInfo = DataCache.SettingsCacheRetrieve(moduleId, cachekey) as DotNetNuke.Modules.ActiveForums.Entities.BadgeInfo; + if (badgeInfo == null) + { + badgeInfo = base.GetById(badgeId, moduleId); + DotNetNuke.Modules.ActiveForums.DataCache.SettingsCacheStore(moduleId, cachekey, badgeInfo); + } + + return badgeInfo; + } + + internal new void DeleteById(TProperty badgeId, int moduleId) + { + var cachekey = this.GetCacheKey(moduleId: moduleId, id: badgeId); + DataCache.SettingsCacheClear(moduleId, cachekey); + this.DeleteById(badgeId); + } + + internal new void Delete(DotNetNuke.Modules.ActiveForums.Entities.BadgeInfo badgeInfo) + { + var cachekey = this.GetCacheKey(moduleId: badgeInfo.ModuleId, id: badgeInfo.BadgeId); + DataCache.SettingsCacheClear(badgeInfo.ModuleId, cachekey); + base.Delete(badgeInfo); + } + + internal new DotNetNuke.Modules.ActiveForums.Entities.BadgeInfo Insert(DotNetNuke.Modules.ActiveForums.Entities.BadgeInfo badgeInfo) + { + base.Insert(badgeInfo); + return this.GetById(badgeInfo.BadgeId, badgeInfo.ModuleId); + } + + internal new DotNetNuke.Modules.ActiveForums.Entities.BadgeInfo Update(DotNetNuke.Modules.ActiveForums.Entities.BadgeInfo badgeInfo) + { + var cachekey = this.GetCacheKey(moduleId: badgeInfo.ModuleId, id: badgeInfo.BadgeId); + DataCache.SettingsCacheClear(badgeInfo.ModuleId, cachekey); + base.Update(badgeInfo); + return this.GetById(badgeInfo.BadgeId, badgeInfo.ModuleId); + } + } +} diff --git a/Dnn.CommunityForums/Controllers/ForumController.cs b/Dnn.CommunityForums/Controllers/ForumController.cs index d2a593729..a86eeb6d6 100644 --- a/Dnn.CommunityForums/Controllers/ForumController.cs +++ b/Dnn.CommunityForums/Controllers/ForumController.cs @@ -314,14 +314,14 @@ internal static void IterateForumsList(System.Collections.Generic.List subForumAction, bool includeHiddenForums) { - string tmpGroupKey = string.Empty; + string tmpSettingsKey = string.Empty; foreach (DotNetNuke.Modules.ActiveForums.Entities.ForumInfo fi in forums.Where(f => (includeHiddenForums || !f.Hidden) && f.ForumGroup != null && (includeHiddenForums || !f.ForumGroup.Hidden) && (forumUserInfo.IsSuperUser || DotNetNuke.Modules.ActiveForums.Controllers.PermissionController.HasRequiredPerm(f.Security?.ViewRoleIds, forumUserInfo.UserRoleIds)))) { - string groupKey = $"{fi.GroupName}{fi.ForumGroupId}"; - if (tmpGroupKey != groupKey) + string settingsKey = $"{fi.GroupName}{fi.ForumGroupId}"; + if (tmpSettingsKey != settingsKey) { groupAction(fi); - tmpGroupKey = groupKey; + tmpSettingsKey = settingsKey; } if (fi.ParentForumId == 0) diff --git a/Dnn.CommunityForums/Controllers/ForumUserController.cs b/Dnn.CommunityForums/Controllers/ForumUserController.cs index 6b9a48d80..e36671c0d 100644 --- a/Dnn.CommunityForums/Controllers/ForumUserController.cs +++ b/Dnn.CommunityForums/Controllers/ForumUserController.cs @@ -21,24 +21,18 @@ namespace DotNetNuke.Modules.ActiveForums.Controllers { using System; + using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Web; using System.Web.UI.WebControls; + using DotNetNuke.Data; - using DotNetNuke.Data; - using DotNetNuke.Entities.Portals; using DotNetNuke.Entities.Portals; using DotNetNuke.Entities.Users; - using DotNetNuke.Entities.Users; - using DotNetNuke.Services.GeneratedImage; - using DotNetNuke.Services.Journal; using DotNetNuke.Services.Journal; using DotNetNuke.Services.Log.EventLog; - using DotNetNuke.Services.Log.EventLog; - using DotNetNuke.Services.Social.Notifications; - using DotNetNuke.UI.UserControls; internal class ForumUserController : DotNetNuke.Modules.ActiveForums.Controllers.RepositoryControllerBase { @@ -65,6 +59,25 @@ public DotNetNuke.Modules.ActiveForums.Entities.ForumUserInfo GetById(int profil throw new NotImplementedException("There is no probably need to call this method; if you do, you probably should be using GetByUserId."); } + public IEnumerable GetActiveUsers(int portalId) + { + var forumUsers = this.Get().Where(u => u.PortalId.Equals(portalId)); + var users = DotNetNuke.Entities.Users.UserController.GetUsers(includeDeleted: false, superUsersOnly: false, portalId: portalId); + var superUsers = DotNetNuke.Entities.Users.UserController.GetUsers(includeDeleted: false, superUsersOnly: true, portalId: DotNetNuke.Common.Utilities.Null.NullInteger); + users.AddRange(superUsers); + return forumUsers + .Join( + users.Cast(), + forumUser => forumUser.UserId, + user => user.UserID, + (forumUser, user) => + { + forumUser.UserInfo = user; + return forumUser; + } + ); + } + public DotNetNuke.Modules.ActiveForums.Entities.ForumUserInfo GetByUserId(int portalId, int userId) { var cachekey = this.GetCacheKey(portalId: portalId, id: userId); @@ -90,6 +103,7 @@ public DotNetNuke.Modules.ActiveForums.Entities.ForumUserInfo GetByUserId(int po PrefBlockSignatures = false, PrefBlockAvatars = false, PrefTopicSubscribe = false, + BadgeNotificationsEnabled = true, LikeNotificationsEnabled = true, PrefJumpLastPost = false, PrefDefaultShowReplies = false, @@ -222,11 +236,13 @@ public static int Save(DotNetNuke.Modules.ActiveForums.Entities.ForumUserInfo us return forumUser.UserId; } + [Obsolete("Deprecated in Community Forums. Removing in 10.00.00. Not Needed.")] public bool GetUserIsAdmin(int portalId, int moduleId, int userId) { return this.GetByUserId(portalId, userId).IsAdmin; } + [Obsolete("Deprecated in Community Forums. Removing in 10.00.00. Not Needed.")] public bool GetUserIsSuperUser(int portalId, int moduleId, int userId) { return this.GetByUserId(portalId, userId).IsSuperUser; @@ -526,17 +542,30 @@ internal static string GetAvatar(PortalSettings portalSettings, int userId, int internal static void UpdateUserTopicCount(int portalId, int userId) { - string sSql = "UPDATE {databaseOwner}{objectQualifier}activeforums_UserProfiles SET TopicCount = ISNULL((Select Count(t.TopicId) FROM "; - sSql += "{databaseOwner}{objectQualifier}activeforums_Topics as t INNER JOIN "; - sSql += "{databaseOwner}{objectQualifier}activeforums_Content as c ON t.ContentId = c.ContentId AND c.AuthorId = @1 INNER JOIN "; - sSql += "{databaseOwner}{objectQualifier}activeforums_ForumTopics as ft ON ft.TopicId = t.TopicId INNER JOIN "; - sSql += "{databaseOwner}{objectQualifier}activeforums_Forums as f ON ft.ForumId = f.ForumId "; + string sSql = "UPDATE {databaseOwner}{objectQualifier}activeforums_UserProfiles SET TopicCount = ISNULL((SELECT COUNT(t.TopicId) "; + sSql += "FROM {databaseOwner}{objectQualifier}activeforums_Topics as t "; + sSql += "INNER JOIN {databaseOwner}{objectQualifier}activeforums_Content as c ON c.ContentId = t.ContentId AND c.AuthorId = @1 "; + sSql += "INNER JOIN {databaseOwner}{objectQualifier}activeforums_ForumTopics as ft ON ft.TopicId = t.TopicId "; + sSql += "INNER JOIN {databaseOwner}{objectQualifier}activeforums_Forums as f ON f.ForumId = ft.ForumId "; sSql += "WHERE c.AuthorId = @1 AND t.IsApproved = 1 AND t.IsDeleted=0 AND f.PortalId=@0),0) "; sSql += "WHERE UserId = @1 AND PortalId = @0"; DataContext.Instance().Execute(System.Data.CommandType.Text, sSql, portalId, userId); DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.ClearCache(portalId, userId); } + internal static void UpdateUserReplyCount(int portalId, int userId) + { + string sSql = "UPDATE {databaseOwner}{objectQualifier}activeforums_UserProfiles SET ReplyCount = ISNULL((SELECT COUNT(r.ReplyId) "; + sSql += "FROM {databaseOwner}{objectQualifier}activeforums_Replies as r "; + sSql += "INNER JOIN {databaseOwner}{objectQualifier}activeforums_Content as c ON c.ContentId = r.ContentId AND c.AuthorId = @1 "; + sSql += "INNER JOIN {databaseOwner}{objectQualifier}activeforums_ForumTopics as ft ON ft.TopicId = r.TopicId "; + sSql += "INNER JOIN {databaseOwner}{objectQualifier}activeforums_Forums as f ON f.ForumId = ft.ForumId "; + sSql += "WHERE c.AuthorId = @1 AND r.IsApproved = 1 AND r.IsDeleted=0 AND f.PortalId=@0),0) "; + sSql += "WHERE UserId = @1 AND PortalId = @0"; + DataContext.Instance().Execute(System.Data.CommandType.Text, sSql, portalId, userId); + DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.ClearCache(portalId, userId); + } + internal string GetUsersOnline(DotNetNuke.Entities.Portals.PortalSettings portalSettings, DotNetNuke.Modules.ActiveForums.ModuleSettings mainSettings, int moduleId, DotNetNuke.Modules.ActiveForums.Entities.ForumUserInfo forumUser) { bool isAdmin = forumUser.IsAdmin || forumUser.IsSuperUser; diff --git a/Dnn.CommunityForums/Controllers/LikeController.cs b/Dnn.CommunityForums/Controllers/LikeController.cs index 6f1e91257..7b0f38dbd 100644 --- a/Dnn.CommunityForums/Controllers/LikeController.cs +++ b/Dnn.CommunityForums/Controllers/LikeController.cs @@ -157,6 +157,7 @@ public int Like(int contentId, int userId, int authorId, int tabId, int forumGro contentId: contentId, authorId: authorId, userId: userId, + badgeId: DotNetNuke.Common.Utilities.Null.NullInteger, requestUrl: requestUrl); } diff --git a/Dnn.CommunityForums/Controllers/ProcessQueueController.cs b/Dnn.CommunityForums/Controllers/ProcessQueueController.cs index 8755c5955..447189f54 100644 --- a/Dnn.CommunityForums/Controllers/ProcessQueueController.cs +++ b/Dnn.CommunityForums/Controllers/ProcessQueueController.cs @@ -29,7 +29,12 @@ namespace DotNetNuke.Modules.ActiveForums.Controllers internal class ProcessQueueController : DotNetNuke.Modules.ActiveForums.Controllers.RepositoryControllerBase { - public bool Add(ProcessType processType, int portalId, int tabId, int moduleId, int forumGroupId, int forumId, int topicId, int replyId, int contentId, int authorId, int userId, string requestUrl) + public bool Add(ProcessType processType, int portalId, int tabId, int moduleId, int forumGroupId, int forumId, int topicId, int replyId, int contentId, int authorId, int userId, int badgeId, string requestUrl) + { + return this.Add(processType: processType, portalId: portalId, tabId: tabId, moduleId: moduleId, forumGroupId: forumGroupId, forumId: forumId, topicId: topicId, replyId: replyId, contentId: contentId, authorId: authorId, userId: userId, badgeId: badgeId, dateCreated: DateTime.UtcNow, requestUrl: requestUrl); + } + + public bool Add(ProcessType processType, int portalId, int tabId, int moduleId, int forumGroupId, int forumId, int topicId, int replyId, int contentId, int authorId, int userId, int badgeId, DateTime dateCreated, string requestUrl) { try { @@ -46,7 +51,8 @@ public bool Add(ProcessType processType, int portalId, int tabId, int moduleId, ContentId = contentId, AuthorId = authorId, UserId = userId, - DateCreated = DateTime.UtcNow, + BadgeId = badgeId, + DateCreated = dateCreated, RequestUrl = requestUrl, }); return true; diff --git a/Dnn.CommunityForums/Controllers/ReplyController.cs b/Dnn.CommunityForums/Controllers/ReplyController.cs index 21c024985..b66ddbdde 100644 --- a/Dnn.CommunityForums/Controllers/ReplyController.cs +++ b/Dnn.CommunityForums/Controllers/ReplyController.cs @@ -28,6 +28,7 @@ namespace DotNetNuke.Modules.ActiveForums.Controllers using DotNetNuke.Collections; using DotNetNuke.Modules.ActiveForums.Enums; using DotNetNuke.Modules.ActiveForums.Services.ProcessQueue; + using DotNetNuke.Modules.ActiveForums.ViewModels; using DotNetNuke.Services.FileSystem; using DotNetNuke.Services.Log.EventLog; @@ -270,12 +271,12 @@ public DotNetNuke.Modules.ActiveForums.Entities.ReplyInfo ApproveReply(int porta internal static bool QueueApprovedReplyAfterAction(int portalId, int tabId, int moduleId, int forumGroupId, int forumId, int topicId, int replyId, int contentId, int authorId, int userId) { - return new DotNetNuke.Modules.ActiveForums.Controllers.ProcessQueueController().Add(ProcessType.ApprovedReplyCreated, portalId, tabId: tabId, moduleId: moduleId, forumGroupId: forumGroupId, forumId: forumId, topicId: topicId, replyId: replyId, contentId: contentId, authorId: authorId, userId: userId, requestUrl: HttpContext.Current.Request.Url.ToString()); + return new DotNetNuke.Modules.ActiveForums.Controllers.ProcessQueueController().Add(ProcessType.ApprovedReplyCreated, portalId, tabId: tabId, moduleId: moduleId, forumGroupId: forumGroupId, forumId: forumId, topicId: topicId, replyId: replyId, contentId: contentId, authorId: authorId, userId: userId, badgeId: DotNetNuke.Common.Utilities.Null.NullInteger, requestUrl: HttpContext.Current.Request.Url.ToString()); } internal static bool QueueUnapprovedReplyAfterAction(int portalId, int tabId, int moduleId, int forumGroupId, int forumId, int topicId, int replyId, int contentId, int authorId, int userId) { - return new DotNetNuke.Modules.ActiveForums.Controllers.ProcessQueueController().Add(ProcessType.UnapprovedReplyCreated, portalId, tabId: tabId, moduleId: moduleId, forumGroupId: forumGroupId, forumId: forumId, topicId: topicId, replyId: replyId, contentId: contentId, authorId: authorId, userId: userId, requestUrl: HttpContext.Current.Request.Url.ToString()); + return new DotNetNuke.Modules.ActiveForums.Controllers.ProcessQueueController().Add(ProcessType.UnapprovedReplyCreated, portalId, tabId: tabId, moduleId: moduleId, forumGroupId: forumGroupId, forumId: forumId, topicId: topicId, replyId: replyId, contentId: contentId, authorId: authorId, userId: userId, badgeId: DotNetNuke.Common.Utilities.Null.NullInteger, requestUrl: HttpContext.Current.Request.Url.ToString()); } internal static bool ProcessApprovedReplyAfterAction(int portalId, int tabId, int moduleId, int forumGroupId, int forumId, int topicId, int replyId, int contentId, int authorId, int userId, string requestUrl) @@ -315,10 +316,16 @@ internal static bool ProcessApprovedReplyAfterAction(int portalId, int tabId, in DataCache.CacheClearPrefix(reply.ModuleId, string.Format(CacheKeys.TopicViewPrefix, reply.ModuleId)); DataCache.CacheClearPrefix(reply.ModuleId, string.Format(CacheKeys.TopicsViewPrefix, reply.ModuleId)); var pqc = new DotNetNuke.Modules.ActiveForums.Controllers.ProcessQueueController(); - pqc.Add(ProcessType.UpdateForumTopicPointers, portalId, tabId: tabId, moduleId: moduleId, forumGroupId: forumGroupId, forumId: forumId, topicId: topicId, replyId: replyId, contentId: contentId, authorId: authorId, userId: userId, requestUrl: requestUrl); - pqc.Add(ProcessType.UpdateForumLastUpdated, portalId, tabId: tabId, moduleId: moduleId, forumGroupId: forumGroupId, forumId: forumId, topicId: topicId, replyId: replyId, contentId: contentId, authorId: authorId, userId: userId, requestUrl: requestUrl); + pqc.Add(ProcessType.UpdateForumTopicPointers, portalId, tabId: tabId, moduleId: moduleId, forumGroupId: forumGroupId, forumId: forumId, topicId: topicId, replyId: replyId, contentId: contentId, authorId: authorId, userId: userId, badgeId: DotNetNuke.Common.Utilities.Null.NullInteger, requestUrl: requestUrl); + pqc.Add(ProcessType.UpdateForumLastUpdated, portalId, tabId: tabId, moduleId: moduleId, forumGroupId: forumGroupId, forumId: forumId, topicId: topicId, replyId: replyId, contentId: contentId, authorId: authorId, userId: userId, badgeId: DotNetNuke.Common.Utilities.Null.NullInteger, requestUrl: requestUrl); Utilities.UpdateModuleLastContentModifiedOnDate(moduleId); + + if (reply.IsApproved && reply.Content.AuthorId > 0) + { + DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.UpdateUserReplyCount(portalId, reply.Content.AuthorId); + } + return true; } catch (Exception ex) diff --git a/Dnn.CommunityForums/Controllers/RepositoryControllerBase.cs b/Dnn.CommunityForums/Controllers/RepositoryControllerBase.cs index a1e420a38..654a7e05b 100644 --- a/Dnn.CommunityForums/Controllers/RepositoryControllerBase.cs +++ b/Dnn.CommunityForums/Controllers/RepositoryControllerBase.cs @@ -84,14 +84,14 @@ internal IPagedList Find(int pageIndex, int pageSize, string sqlCondition, pa internal void Update(T item) { + var property = typeof(T).GetProperty("DateUpdated"); + if (property != null && property.CanWrite && property.PropertyType == typeof(System.DateTime)) + { + property.SetValue(item, System.DateTime.UtcNow, null); + } this.repo.Update(item); } - public void Update(string sqlCondition, params object[] args) - { - this.repo.Update(sqlCondition, args); - } - internal void Insert(T item) { this.repo.Insert(item); diff --git a/Dnn.CommunityForums/Controllers/TopicController.cs b/Dnn.CommunityForums/Controllers/TopicController.cs index 92714a6f2..d9e5fdadf 100644 --- a/Dnn.CommunityForums/Controllers/TopicController.cs +++ b/Dnn.CommunityForums/Controllers/TopicController.cs @@ -231,8 +231,8 @@ public static void Move(int moduleId, int userId, int topicId, int newForumId) DotNetNuke.Modules.ActiveForums.Controllers.EmailController.SendEmail(TemplateType.ModMove, ti.Forum.GetTabId(), oldForum, topicId: ti.TopicId, replyId: -1, author: ti.Author); } - new DotNetNuke.Modules.ActiveForums.Controllers.ProcessQueueController().Add(ProcessType.UpdateForumLastUpdated, ti.PortalId, tabId: -1, moduleId: ti.ModuleId, forumGroupId: oldForum.ForumGroupId, forumId: oldForum.ForumID, topicId: topicId, replyId: -1, contentId: ti.ContentId, authorId: ti.Content.AuthorId, userId: userId, requestUrl: null); - new DotNetNuke.Modules.ActiveForums.Controllers.ProcessQueueController().Add(ProcessType.UpdateForumLastUpdated, ti.PortalId, tabId: -1, moduleId: ti.ModuleId, forumGroupId: newForum.ForumGroupId, forumId: newForum.ForumID, topicId: topicId, replyId: -1, contentId: ti.ContentId, authorId: ti.Content.AuthorId, userId: userId, requestUrl: null); + new DotNetNuke.Modules.ActiveForums.Controllers.ProcessQueueController().Add(ProcessType.UpdateForumLastUpdated, ti.PortalId, tabId: -1, moduleId: ti.ModuleId, forumGroupId: oldForum.ForumGroupId, forumId: oldForum.ForumID, topicId: topicId, replyId: -1, contentId: ti.ContentId, authorId: ti.Content.AuthorId, userId: userId, badgeId: DotNetNuke.Common.Utilities.Null.NullInteger, requestUrl: null); + new DotNetNuke.Modules.ActiveForums.Controllers.ProcessQueueController().Add(ProcessType.UpdateForumLastUpdated, ti.PortalId, tabId: -1, moduleId: ti.ModuleId, forumGroupId: newForum.ForumGroupId, forumId: newForum.ForumID, topicId: topicId, replyId: -1, contentId: ti.ContentId, authorId: ti.Content.AuthorId, userId: userId, badgeId: DotNetNuke.Common.Utilities.Null.NullInteger, requestUrl: null); Utilities.UpdateModuleLastContentModifiedOnDate(ti.ModuleId); DotNetNuke.Modules.ActiveForums.DataCache.ContentCacheClearForForum(moduleId, ti.ForumId); DotNetNuke.Modules.ActiveForums.DataCache.ContentCacheClearForTopic(moduleId, topicId); @@ -265,13 +265,6 @@ public static int Save(DotNetNuke.Modules.ActiveForums.Entities.TopicInfo ti) ti.Content.DateCreated = DateTime.UtcNow; } - if (ti.IsApproved && ti.Author.AuthorId > 0) - { - // TODO: put this in a better place and make it consistent with reply counter - DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.UpdateUserTopicCount(ti.Forum.PortalId, ti.Author.AuthorId); - } - - DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.ClearCache(ti.Forum.PortalId, ti.Content.AuthorId); Utilities.UpdateModuleLastContentModifiedOnDate(ti.ModuleId); DotNetNuke.Modules.ActiveForums.DataCache.ContentCacheClearForForum(ti.ModuleId, ti.ForumId); DotNetNuke.Modules.ActiveForums.DataCache.ContentCacheClearForTopic(ti.ModuleId, ti.TopicId); @@ -355,12 +348,12 @@ public void DeleteById(int topicId, DotNetNuke.Modules.ActiveForums.Enums.Delete internal static bool QueueApprovedTopicAfterAction(int portalId, int tabId, int moduleId, int forumGroupId, int forumId, int topicId, int replyId, int contentId, int authorId, int userId) { - return new DotNetNuke.Modules.ActiveForums.Controllers.ProcessQueueController().Add(ProcessType.ApprovedTopicCreated, portalId, tabId: tabId, moduleId: moduleId, forumGroupId: forumGroupId, forumId: forumId, topicId: topicId, replyId: replyId, contentId: contentId, authorId: authorId, userId: userId, requestUrl: HttpContext.Current.Request.Url.ToString()); + return new DotNetNuke.Modules.ActiveForums.Controllers.ProcessQueueController().Add(ProcessType.ApprovedTopicCreated, portalId, tabId: tabId, moduleId: moduleId, forumGroupId: forumGroupId, forumId: forumId, topicId: topicId, replyId: replyId, contentId: contentId, authorId: authorId, userId: userId, badgeId: DotNetNuke.Common.Utilities.Null.NullInteger, requestUrl: HttpContext.Current.Request.Url.ToString()); } internal static bool QueueUnapprovedTopicAfterAction(int portalId, int tabId, int moduleId, int forumGroupId, int forumId, int topicId, int replyId, int contentId, int authorId, int userId) { - return new DotNetNuke.Modules.ActiveForums.Controllers.ProcessQueueController().Add(ProcessType.UnapprovedTopicCreated, portalId, tabId: tabId, moduleId: moduleId, forumGroupId: forumGroupId, forumId: forumId, topicId: topicId, replyId: replyId, contentId: contentId, authorId: authorId, userId: userId, requestUrl: HttpContext.Current.Request.Url.ToString()); + return new DotNetNuke.Modules.ActiveForums.Controllers.ProcessQueueController().Add(ProcessType.UnapprovedTopicCreated, portalId, tabId: tabId, moduleId: moduleId, forumGroupId: forumGroupId, forumId: forumId, topicId: topicId, replyId: replyId, contentId: contentId, authorId: authorId, userId: userId, badgeId: DotNetNuke.Common.Utilities.Null.NullInteger, requestUrl: HttpContext.Current.Request.Url.ToString()); } internal static bool ProcessApprovedTopicAfterAction(int portalId, int tabId, int moduleId, int forumGroupId, int forumId, int topicId, int replyId, int contentId, int authorId, int userId, string requestUrl) @@ -386,11 +379,16 @@ internal static bool ProcessApprovedTopicAfterAction(int portalId, int tabId, in amas.AddTopicToJournal(portalId, moduleId, tabId, forumId, topicId, topic.Author.AuthorId, sUrl, topic.Content.Subject, string.Empty, topic.Content.Body, topic.Forum.Security.Read, topic.Forum.SocialGroupId); var pqc = new DotNetNuke.Modules.ActiveForums.Controllers.ProcessQueueController(); - pqc.Add(ProcessType.UpdateForumTopicPointers, portalId, tabId: tabId, moduleId: moduleId, forumGroupId: forumGroupId, forumId: forumId, topicId: topicId, replyId: replyId, contentId: contentId, authorId: authorId, userId: userId, requestUrl: requestUrl); - pqc.Add(ProcessType.UpdateForumLastUpdated, portalId, tabId: tabId, moduleId: moduleId, forumGroupId: forumGroupId, forumId: forumId, topicId: topicId, replyId: replyId, contentId: contentId, authorId: authorId, userId: userId, requestUrl: requestUrl); + pqc.Add(ProcessType.UpdateForumTopicPointers, portalId, tabId: tabId, moduleId: moduleId, forumGroupId: forumGroupId, forumId: forumId, topicId: topicId, replyId: replyId, contentId: contentId, authorId: authorId, userId: userId, badgeId: DotNetNuke.Common.Utilities.Null.NullInteger, requestUrl: requestUrl); + pqc.Add(ProcessType.UpdateForumLastUpdated, portalId, tabId: tabId, moduleId: moduleId, forumGroupId: forumGroupId, forumId: forumId, topicId: topicId, replyId: replyId, contentId: contentId, authorId: authorId, userId: userId, badgeId: DotNetNuke.Common.Utilities.Null.NullInteger, requestUrl: requestUrl); Utilities.UpdateModuleLastContentModifiedOnDate(moduleId); + if (topic.IsApproved && topic.Content.AuthorId > 0) + { + DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController.UpdateUserTopicCount(portalId, topic.Content.AuthorId); + } + return true; } catch (Exception ex) diff --git a/Dnn.CommunityForums/Controllers/TopicTrackingController.cs b/Dnn.CommunityForums/Controllers/TopicTrackingController.cs index f76dcb696..458878b88 100644 --- a/Dnn.CommunityForums/Controllers/TopicTrackingController.cs +++ b/Dnn.CommunityForums/Controllers/TopicTrackingController.cs @@ -20,6 +20,7 @@ namespace DotNetNuke.Modules.ActiveForums.Controllers { + using System; using System.Linq; using DotNetNuke.Data; @@ -53,5 +54,17 @@ internal int GetTopicsReadCountForUserForum(int moduleId, int userId, int forumI return (int)topicReadCount; } + + internal int GetTopicsReadCountByUser(int moduleId, int userId) + { + // this accommodates duplicates which may exist since currently no uniqueness applied in database + return DataContext.Instance().ExecuteQuery(System.Data.CommandType.Text, "SELECT COUNT(*) FROM {databaseOwner}{objectQualifier}activeforums_Topics_Tracking tt WHERE tt.UserId = @0", userId).FirstOrDefault(); + } + + internal int GetTopicsReadCountByUser(int moduleId, int userId, DateTime minDateTime) + { + // this accommodates duplicates which may exist since currently no uniqueness applied in database + return DataContext.Instance().ExecuteQuery(System.Data.CommandType.Text, "SELECT COUNT(*) FROM {databaseOwner}{objectQualifier}activeforums_Topics_Tracking tt WHERE tt.UserId = @0 AND DateAdded IS NOT NULL AND DateAdded >= @1", userId, minDateTime).FirstOrDefault(); + } } } diff --git a/Dnn.CommunityForums/Controllers/UserBadgeController.cs b/Dnn.CommunityForums/Controllers/UserBadgeController.cs new file mode 100644 index 000000000..d8b1bb401 --- /dev/null +++ b/Dnn.CommunityForums/Controllers/UserBadgeController.cs @@ -0,0 +1,280 @@ +// Copyright (c) by DNN Community +// +// DNN Community licenses this file to you under the MIT license. +// +// See the LICENSE file in the project root for more information. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +namespace DotNetNuke.Modules.ActiveForums.Controllers +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + + using DotNetNuke.Collections; + using DotNetNuke.Modules.ActiveForums.Services.ProcessQueue; + using DotNetNuke.Services.Log.EventLog; + using DotNetNuke.Services.Social.Notifications; + + internal partial class UserBadgeController : RepositoryControllerBase + { + private readonly int moduleId = -1; + private readonly int portalId = -1; + + internal override string cacheKeyTemplate => CacheKeys.UserBadgeInfo; + + internal UserBadgeController() + { + } + + internal UserBadgeController(int portalId, int moduleId) + { + this.portalId = portalId; + this.moduleId = moduleId; + } + + internal DotNetNuke.Modules.ActiveForums.Entities.UserBadgeInfo GetById(int id) + { + var cachekey = this.GetCacheKey(moduleId: this.moduleId, id: id); + DotNetNuke.Modules.ActiveForums.Entities.UserBadgeInfo UserBadge = DataCache.ContentCacheRetrieve(this.moduleId, cachekey) as DotNetNuke.Modules.ActiveForums.Entities.UserBadgeInfo; + if (UserBadge == null) + { + UserBadge = this.GetById(id, this.moduleId); + if (UserBadge != null) + { + UserBadge.ModuleId = this.moduleId; + UserBadge.PortalId = this.portalId; + UserBadge.GetBadge(); + UserBadge.GetForumUser(); + } + + DotNetNuke.Modules.ActiveForums.DataCache.ContentCacheStore(this.moduleId, cachekey, UserBadge); + } + + return UserBadge; + } + + internal IEnumerable GetForUser(int portalId, int userId) + { + var cachekey = string.Format(CacheKeys.UserBadges, this.moduleId, userId); + var UserBadges = (IEnumerable)DataCache.ContentCacheRetrieve(this.moduleId, cachekey); + + if (UserBadges == null) + { + UserBadges = this.Find("WHERE PortalId = @0 AND UserId = @1", portalId, userId); + DotNetNuke.Modules.ActiveForums.DataCache.ContentCacheStore(this.moduleId, cachekey, UserBadges); + } + + return UserBadges; + } + + internal IEnumerable GetDistinctForUser(int portalId, int userId) + { + var cachekey = string.Format(CacheKeys.UserBadges, this.moduleId, userId); + var distinctUserBadges = (IEnumerable)DataCache.ContentCacheRetrieve(this.moduleId, cachekey); + + if (distinctUserBadges == null) + { + distinctUserBadges = this.Find("WHERE PortalId = @0 AND UserId = @1", portalId, userId) + .GroupBy(b => b.BadgeId) + .Select(g => g.OrderByDescending(b => b.DateAssigned).First()) + .ToList(); + DotNetNuke.Modules.ActiveForums.DataCache.ContentCacheStore(this.moduleId, cachekey, distinctUserBadges); + } + + return distinctUserBadges; + } + + internal IEnumerable GetForUserAndBadge(int portalId, int userId, int badgeId) + { + return this.Find("WHERE PortalId = @0 AND UserId = @1 AND BadgeId = @2", portalId, userId, badgeId); + } + + internal DotNetNuke.Modules.ActiveForums.Entities.UserBadgeInfo GetForUserAndBadgeAndDateAssigned(int portalId, int userId, int badgeId, DateTime dateAssigned) + { + return this.Find("WHERE PortalId = @0 AND UserId = @1 AND BadgeId = @2 AND DateAssigned = @3", portalId, userId, badgeId, dateAssigned).FirstOrDefault(); + } + + internal DotNetNuke.Modules.ActiveForums.Entities.UserBadgeInfo GetLatestForUserAndBadge(int portalId, int userId, int badgeId) + { + return this.Find("WHERE PortalId = @0 AND UserId = @1 AND BadgeId = @2", portalId, userId, badgeId).OrderByDescending(b => b.DateAssigned).FirstOrDefault(); + } + + internal IEnumerable GetForBadge(int badgeId) + { + var cachekey = string.Format(CacheKeys.BadgeUsers, this.moduleId, badgeId); + var UserBadges = (IEnumerable)DataCache.ContentCacheRetrieve(this.moduleId, cachekey); + + if (UserBadges == null) + { + UserBadges = this.Find("WHERE BadgeId = @0", badgeId); + DotNetNuke.Modules.ActiveForums.DataCache.ContentCacheStore(this.moduleId, cachekey, UserBadges); + } + + return UserBadges; + } + + internal int BadgeCount(int portalId, int userId, int badgeId) + { + var cachekey = string.Format(CacheKeys.BadgeUserCount, this.moduleId, badgeId, userId); + var count = (int?)DataCache.ContentCacheRetrieve(this.moduleId, cachekey); + if (count == null) + { + count = this.Count("WHERE PortalId = @0 AND UserId = @1 AND BadgeId = @2", portalId, userId, badgeId); + DotNetNuke.Modules.ActiveForums.DataCache.ContentCacheStore(this.moduleId, cachekey, count); + } + + return (int)count; + } + + internal static void AssignUserBadge(int portalId, int moduleId, int userId, int badgeId, string requestUrl) + { + try + { + var award = true; + var userBadgeController = new DotNetNuke.Modules.ActiveForums.Controllers.UserBadgeController(portalId: portalId, moduleId: moduleId); + DotNetNuke.Modules.ActiveForums.Entities.UserBadgeInfo userBadge = null; + var badge = new DotNetNuke.Modules.ActiveForums.Controllers.BadgeController().GetById(badgeId); + if (badge.OneTimeAward) + { + userBadge = userBadgeController.GetLatestForUserAndBadge(portalId: portalId, userId: userId, badgeId: badgeId); + if (userBadge != null) + { + // If the badge is one-time award and already assigned, do not reassign. + award = false; + } + } + + if (award) + { + userBadge = new DotNetNuke.Modules.ActiveForums.Entities.UserBadgeInfo + { + BadgeId = badgeId, + UserId = userId, + PortalId = portalId, + ModuleId = moduleId, + DateAssigned = DateTime.UtcNow, + }; + userBadgeController.Insert(userBadge); + ClearBadgeCache(userBadge); + + new DotNetNuke.Modules.ActiveForums.Controllers.ProcessQueueController().Add( + processType: ProcessType.BadgeAssigned, + portalId: portalId, + tabId: DotNetNuke.Common.Utilities.Null.NullInteger, + moduleId: moduleId, + forumGroupId: DotNetNuke.Common.Utilities.Null.NullInteger, + forumId: DotNetNuke.Common.Utilities.Null.NullInteger, + topicId: DotNetNuke.Common.Utilities.Null.NullInteger, + replyId: DotNetNuke.Common.Utilities.Null.NullInteger, + contentId: DotNetNuke.Common.Utilities.Null.NullInteger, + authorId: DotNetNuke.Common.Utilities.Null.NullInteger, + userId: userId, + badgeId: badgeId, + dateCreated: userBadge.DateAssigned, + requestUrl: requestUrl); + } + } + catch (Exception e) + { + DotNetNuke.Modules.ActiveForums.Exceptions.LogException(e); + } + } + + private static void ClearBadgeCache(DotNetNuke.Modules.ActiveForums.Entities.UserBadgeInfo userBadge) + { + DotNetNuke.Modules.ActiveForums.DataCache.ContentCacheClear(userBadge.ModuleId, string.Format(CacheKeys.UserBadgeInfo, userBadge.ModuleId, userBadge.UserBadgeId)); + DotNetNuke.Modules.ActiveForums.DataCache.ContentCacheClear(userBadge.ModuleId, string.Format(CacheKeys.UserBadges, userBadge.ModuleId, userBadge.UserId)); + DotNetNuke.Modules.ActiveForums.DataCache.ContentCacheClear(userBadge.ModuleId, string.Format(CacheKeys.BadgeUsers, userBadge.ModuleId, userBadge.BadgeId)); + DotNetNuke.Modules.ActiveForums.DataCache.ContentCacheClear(userBadge.ModuleId, string.Format(CacheKeys.BadgeUserCount, userBadge.ModuleId, userBadge.BadgeId, userBadge.UserId)); + } + + internal void UnassignUserBadge(int portalId, int userId, int badgeId, DateTime dateAssigned) + { + try + { + var userBadge = this.GetForUserAndBadgeAndDateAssigned(portalId: portalId, userId: userId, badgeId: badgeId, dateAssigned: dateAssigned); + if (userBadge != null) + { + ClearBadgeCache(userBadge); + this.DeleteById(userBadge.UserBadgeId); + } + } + catch (Exception e) + { + DotNetNuke.Modules.ActiveForums.Exceptions.LogException(e); + } + } + + internal bool AssignUserBadgeAfterAction(int portalId, int userId, int badgeId, DateTime dateAssigned, string requestUrl) + { + try + { + var userBadge = this.GetForUserAndBadgeAndDateAssigned(portalId: portalId, userId: userId, badgeId: badgeId, dateAssigned: dateAssigned); + if (userBadge == null) + { + // If the user badge does not exist, cannot proceed but return true to indicate no error occurred; we just won't send a notification but need to clear the process action from the queue. + return true; + } + + // Check if badge notifications should be sent to the user. + // Conditions: + // - The badge is configured to send award notifications. + // - The forum user has enabled badge notifications. + // - Either notifications are not suppressed for backfill, or user was assigned badge after backfill completed date. + if (userBadge.ForumUser.BadgeNotificationsEnabled + && userBadge.Badge.SendAwardNotification + && (!userBadge.Badge.SuppresssAwardNotificationOnBackfill + || (userBadge.Badge.InitialBackfillCompletedDate.HasValue && userBadge.DateAssigned > userBadge.Badge.InitialBackfillCompletedDate.Value))) + { + var subject = DotNetNuke.Modules.ActiveForums.Controllers.TemplateController.Template_Get(this.moduleId, Enums.TemplateType.BadgeNotificationSubject, SettingsBase.GetModuleSettings(this.moduleId).DefaultFeatureSettings.TemplateFileNameSuffix); + subject = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceBadgeTokens(new StringBuilder(subject), userBadge, userBadge.ForumUser.PortalSettings, userBadge.ForumUser.ModuleSettings, new Services.URLNavigator().NavigationManager(), userBadge.ForumUser, string.IsNullOrEmpty(requestUrl) ? null : new Uri(requestUrl), string.IsNullOrEmpty(requestUrl) ? string.Empty : new Uri(requestUrl).PathAndQuery).ToString(); + subject = subject.Length > 400 ? subject.Substring(0, 400) : subject; + var body = DotNetNuke.Modules.ActiveForums.Controllers.TemplateController.Template_Get(this.moduleId, Enums.TemplateType.BadgeNotificationBody, SettingsBase.GetModuleSettings(this.moduleId).DefaultFeatureSettings.TemplateFileNameSuffix); + body = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.ReplaceBadgeTokens(new StringBuilder(body), userBadge, userBadge.ForumUser.PortalSettings, userBadge.ForumUser.ModuleSettings, new Services.URLNavigator().NavigationManager(), userBadge.ForumUser, string.IsNullOrEmpty(requestUrl) ? null : new Uri(requestUrl), string.IsNullOrEmpty(requestUrl) ? string.Empty : new Uri(requestUrl).PathAndQuery).ToString(); + + string notificationKey = BuildNotificationContextKey(this.portalId, this.moduleId, badgeId, userId, userBadge.DateAssigned); + + NotificationType notificationType = NotificationsController.Instance.GetNotificationType(Globals.BadgeNotificationType); + Notification notification = new Notification + { + NotificationTypeID = notificationType.NotificationTypeId, + Subject = subject, + Body = body, + IncludeDismissAction = true, + SenderUserID = userId, + Context = notificationKey, + }; + var users = new List { userBadge.ForumUser.UserInfo }; + NotificationsController.Instance.SendNotification(notification, this.portalId, null, users); + } + + return true; + } + catch (Exception e) + { + DotNetNuke.Modules.ActiveForums.Exceptions.LogException(e); + return false; + } + } + + private static string BuildNotificationContextKey(int portalId, int moduleId, int badgeId, int userId, DateTime dateAssigned) + { + return $"{portalId}:{moduleId}:{badgeId}:{userId}:{dateAssigned}"; + } + } +} diff --git a/Dnn.CommunityForums/DnnCommunityForums.csproj b/Dnn.CommunityForums/DnnCommunityForums.csproj index cca9bca27..e82234e5e 100644 --- a/Dnn.CommunityForums/DnnCommunityForums.csproj +++ b/Dnn.CommunityForums/DnnCommunityForums.csproj @@ -12,6 +12,8 @@ Discussion Forum Module for DNN dnncommunity.org dnncommunity.org + 09.01.01.00 + 09.01.01.00 09.02.00.00 09.02.00.00 @@ -25,15 +27,22 @@ + + + + + + + @@ -75,7 +84,6 @@ - @@ -88,6 +96,15 @@ + + + + ASPXCodeBehind + + + ASPXCodeBehind + + diff --git a/Dnn.CommunityForums/DnnCommunityForums.dnn b/Dnn.CommunityForums/DnnCommunityForums.dnn index 5fd38177c..069437234 100644 --- a/Dnn.CommunityForums/DnnCommunityForums.dnn +++ b/Dnn.CommunityForums/DnnCommunityForums.dnn @@ -75,7 +75,7 @@ DotNetNuke.Modules.ActiveForums.TopicsController, DotNetNuke.Modules.ActiveForums [DESKTOPMODULEID] - 07.00.07,07.00.11,07.00.12,08.00.00,08.01.00,08.02.00,08.02.02,08.02.03,08.02.04,08.02.08,09.00.00,09.01.00 + 07.00.07,07.00.11,07.00.12,08.00.00,08.01.00,08.02.00,08.02.02,08.02.03,08.02.04,08.02.08,09.00.00,09.01.00,09.02.00 @@ -434,11 +434,6 @@ 09.01.00.SqlDataProvider 09.01.00 - +
    +
    + [RESX:BadgeNew] +
    +
    +
    + [RESX:Badges] +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    [RESX:BadgeName]
    +
    +
    [RESX:SortOrder]
    +
    +
    [RESX:BadgeMetric]
    +
    +
    [RESX:BadgeThreshold]
    +
    + +
    +
    + + diff --git a/Dnn.CommunityForums/controls/admin_badges.ascx.cs b/Dnn.CommunityForums/controls/admin_badges.ascx.cs new file mode 100644 index 000000000..ce16be939 --- /dev/null +++ b/Dnn.CommunityForums/controls/admin_badges.ascx.cs @@ -0,0 +1,103 @@ +// Copyright (c) by DNN Community +// +// DNN Community licenses this file to you under the MIT license. +// +// See the LICENSE file in the project root for more information. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +namespace DotNetNuke.Modules.ActiveForums +{ + using System; + using System.Web.UI; + using System.Web.UI.WebControls; + + public partial class admin_badges : ActiveAdminBase + { + public string ImagePath => this.Page.ResolveUrl(string.Concat(this.MainSettings.ThemeLocation, "/images")); + + protected global::DotNetNuke.Modules.ActiveForums.Controls.ActiveGrid agBadges; + protected global::System.Web.UI.WebControls.DropDownList drpBadgeMetrics; + protected global::System.Web.UI.WebControls.DropDownList drpBadgeImages; + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + + this.agBadges.Callback += this.agBadges_Callback; + this.agBadges.ItemBound += this.AgBadgesItemBound; + + } + + protected override void OnLoad(EventArgs e) + { + if (!Page.IsPostBack) + { + base.OnLoad(e); + + this.BindBadgeMetrics(); + this.BindBadgeImages(); + } + } + + private void agBadges_Callback(object sender, Modules.ActiveForums.Controls.CallBackEventArgs e) + { + this.agBadges.Datasource = DataProvider.Instance().Badges_List(this.ModuleId); + this.agBadges.Refresh(e.Output); + } + + private void AgBadgesItemBound(object sender, Modules.ActiveForums.Controls.ItemBoundEventArgs e) + { + e.Item[8] = this.GetImageTag(Utilities.SafeConvertInt(e.Item[7].ToString()), e.Item[2].ToString()); + e.Item[5] = this.GetEnumName((DotNetNuke.Modules.ActiveForums.Enums.BadgeMetric)Utilities.SafeConvertInt(e.Item[4].ToString())); + } + + private string GetImageTag(int fileId, string badgeName) + { + if (fileId <= 0) + { + return string.Empty; + } + + var imgUrl = Utilities.ResolveUrl($"https://{this.PortalSettings.DefaultPortalAlias}/DnnImageHandler.ashx?mode=securefile&fileId={fileId}&h=16&w=16"); + return $"\"{badgeName}\""; + + } + + private string GetEnumName(DotNetNuke.Modules.ActiveForums.Enums.BadgeMetric badgeMetric) + { + return Utilities.GetSharedResource($"[RESX:{Enum.GetName(typeof(DotNetNuke.Modules.ActiveForums.Enums.BadgeMetric), badgeMetric)}]", isAdmin: true); + } + + private void BindBadgeMetrics() + { + Utilities.BindEnum(pDDL: this.drpBadgeMetrics, enumType: typeof(Enums.BadgeMetric), pColValue: string.Empty, addEmptyValue: false, localize: true, excludeIndex: -1); + } + + private void BindBadgeImages() + { + var folderInfo = DotNetNuke.Services.FileSystem.FolderManager.Instance.GetFolder(this.PortalId, Globals.DefaultBadgesFolderName); + foreach (var fileInfo in DotNetNuke.Services.FileSystem.FolderManager.Instance.GetFiles(folderInfo, recursive: true)) + { + if (fileInfo.ContentType.ToLowerInvariant().Contains("image/")) + { + this.drpBadgeImages.Items.Add(new ListItem(fileInfo.FileName, fileInfo.FileId.ToString())); + } + } + this.drpBadgeImages.Items.Insert(0, new ListItem("[RESX:DropDownDefault]", "-1")); + + } + } +} diff --git a/Dnn.CommunityForums/controls/admin_categories.ascx b/Dnn.CommunityForums/controls/admin_categories.ascx index 6deb92fd4..248caffa5 100644 --- a/Dnn.CommunityForums/controls/admin_categories.ascx +++ b/Dnn.CommunityForums/controls/admin_categories.ascx @@ -70,7 +70,7 @@ function amaf_deleteCategory(row){
    - + diff --git a/Dnn.CommunityForums/controls/admin_ranks.ascx.cs b/Dnn.CommunityForums/controls/admin_ranks.ascx.cs deleted file mode 100644 index 2e62bd7d6..000000000 --- a/Dnn.CommunityForums/controls/admin_ranks.ascx.cs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) by DNN Community -// -// DNN Community licenses this file to you under the MIT license. -// -// See the LICENSE file in the project root for more information. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and -// to permit persons to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or substantial portions -// of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF -// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -namespace DotNetNuke.Modules.ActiveForums -{ - using System; - using System.Web.UI.WebControls; - - public partial class admin_ranks_new : ActiveAdminBase - { - public string ImagePath => this.Page.ResolveUrl(string.Concat(this.MainSettings.ThemeLocation, "/images")); - - protected override void OnInit(EventArgs e) - { - base.OnInit(e); - - this.agRanks.Callback += this.agRanks_Callback; - this.agRanks.ItemBound += this.agRanks_ItemBound; - } - - protected override void OnLoad(EventArgs e) - { - base.OnLoad(e); - - this.BindRankImages(); - } - - private void agRanks_Callback(object sender, Modules.ActiveForums.Controls.CallBackEventArgs e) - { - this.agRanks.Datasource = DataProvider.Instance().Ranks_List(this.PortalId, this.ModuleId); - this.agRanks.Refresh(e.Output); - } - - private void agRanks_ItemBound(object sender, Modules.ActiveForums.Controls.ItemBoundEventArgs e) - { - e.Item[4] = this.GetDisplay(e.Item[4].ToString(), e.Item[1].ToString()); - } - - public string GetDisplay(string display, string rankName) - { - return "\"""; - } - - private void BindRankImages() - { - string[] fileCollection = null; - System.IO.FileInfo myFileInfo = null; - int i = 0; - - fileCollection = System.IO.Directory.GetFiles(Utilities.MapPath(Globals.ModulePath + "images/ranks")); - for (i = 0; i < fileCollection.Length; i++) - { - string path = null; - myFileInfo = new System.IO.FileInfo(fileCollection[i]); - path = "DesktopModules/ActiveForums/images/ranks/" + myFileInfo.Name; - this.drpRankImages.Items.Insert(i, new ListItem(myFileInfo.Name, path.ToLowerInvariant())); - } - - this.drpRankImages.Items.Insert(0, new ListItem("[RESX:DropDownDefault]", "-1")); - - // drpRankImages.Items.Insert(1, New ListItem(Utilities.GetSharedResource("RankCustom.Text"), "0")) - } - } -} diff --git a/Dnn.CommunityForums/controls/af_assign_badge_users.ascx b/Dnn.CommunityForums/controls/af_assign_badge_users.ascx new file mode 100644 index 000000000..10d291292 --- /dev/null +++ b/Dnn.CommunityForums/controls/af_assign_badge_users.ascx @@ -0,0 +1,31 @@ +<%@ control language="C#" autoeventwireup="false" codebehind="af_assign_badge_users.ascx.cs" inherits="DotNetNuke.Modules.ActiveForums.af_assign_badge_users" %> +<%@ Register TagPrefix="asp" Namespace="System.Web.UI" Assembly="System.Web" %> +

    + [RESX:BadgeUsersAssigned] +

    +
    + + + + + + + + + + + + + + + + + + +
    +
    +
    +
    +
    +
    diff --git a/Dnn.CommunityForums/controls/af_assign_badge_users.ascx.cs b/Dnn.CommunityForums/controls/af_assign_badge_users.ascx.cs new file mode 100644 index 000000000..6ab930c75 --- /dev/null +++ b/Dnn.CommunityForums/controls/af_assign_badge_users.ascx.cs @@ -0,0 +1,130 @@ +// Copyright (c) by DNN Community +// +// DNN Community licenses this file to you under the MIT license. +// +// See the LICENSE file in the project root for more information. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +namespace DotNetNuke.Modules.ActiveForums +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web.UI; + using System.Web.UI.WebControls; + + using DotNetNuke.Collections; + using DotNetNuke.Data; + using DotNetNuke.Modules.ActiveForums.Extensions.WebForms; + + using static log4net.Appender.RollingFileAppender; + + public partial class af_assign_badge_users : ForumBase + { + private int? badgeId { get; set; } + + private DotNetNuke.Modules.ActiveForums.Entities.BadgeInfo badge { get; set; } + + protected global::System.Web.UI.WebControls.Label lblBadgesAssigned; + protected global::System.Web.UI.WebControls.GridView dgrdBadgeUsers; + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + + this.badgeId = this.Request.QueryString[ParamKeys.BadgeId] != null ? Convert.ToInt32(this.Request.QueryString[ParamKeys.BadgeId]) : -1; + this.badge = new DotNetNuke.Modules.ActiveForums.Controllers.BadgeController().GetById((int)this.badgeId); + this.lblBadgesAssigned.Text = string.Format(DotNetNuke.Modules.ActiveForums.Utilities.GetSharedResource("[RESX:BadgeUsersAssigned]"), this.badge.Name); + this.dgrdBadgeUsers.Columns[3].HeaderText = DotNetNuke.Modules.ActiveForums.Utilities.GetSharedResource("[RESX:Username]"); + this.dgrdBadgeUsers.Columns[4].HeaderText = DotNetNuke.Modules.ActiveForums.Utilities.GetSharedResource("[RESX:Date]", isAdmin: true) + " (UTC)"; + + this.dgrdBadgeUsers.RowDataBound += this.OnBadgeUsersGridRowDataBound; + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + try + { + if (this.UserId > 0 && this.ForumUser.IsAdmin) + { + this.BindBadgeUsers(); + } + } + catch (Exception ex) + { + Exceptions.LogException(ex); + } + } + + private void BindBadgeUsers() + { + this.dgrdBadgeUsers.DataSource = this.GetBadges().ToList(); + this.dgrdBadgeUsers.DataBind(); + this.dgrdBadgeUsers.PageSize = this.dgrdBadgeUsers.Rows.Count; + this.dgrdBadgeUsers.WrapGridViewInDataTableNet(this.PortalSettings, this.UserInfo); + } + + private class UserList + { + public int UserId { get; set; } + + public string DisplayName { get; set; } + } + + private IEnumerable GetBadges() + { + var availableUsers = new DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController(this.ForumModuleId).GetActiveUsers(this.PortalId).Select(u => new UserList { UserId = u.UserId, DisplayName = u.DisplayName }).ToList(); + var assignedBadges = new DotNetNuke.Modules.ActiveForums.Controllers.UserBadgeController(this.PortalId, this.ForumModuleId).GetForBadge((int)this.badgeId); + var assignedBadgeIds = assignedBadges.Select(userBadge => + { + return new { userBadge.UserBadgeId, userBadge.UserId, userBadge.DateAssigned, }; + }); + var mergedBadges = from availUsers in availableUsers + join asgnedBadges in assignedBadgeIds on availUsers.UserId equals asgnedBadges.UserId into merged + from mrgdBadges in merged.DefaultIfEmpty() + select new DotNetNuke.Modules.ActiveForums.Entities.UserBadgeInfo(userBadgeId: mrgdBadges?.UserBadgeId ?? 0, userId: availUsers.UserId, userName: availUsers.DisplayName, badgeId: (int)this.badgeId, badgeName: this.badge.Name, portalId: this.PortalId, moduleId: this.ForumModuleId, dateAssigned: mrgdBadges?.DateAssigned, assigned: mrgdBadges != null); + return mergedBadges; + } + + protected void OnBadgeUsersGridRowDataBound(object sender, GridViewRowEventArgs e) + { + if (e.Row.RowType == DataControlRowType.DataRow) + { + DotNetNuke.Modules.ActiveForums.Entities.UserBadgeInfo userBadgeInfo = e.Row.DataItem as DotNetNuke.Modules.ActiveForums.Entities.UserBadgeInfo; + if (userBadgeInfo.DateAssigned.Equals(DotNetNuke.Common.Utilities.Null.NullDate)) + { + e.Row.Cells[4].Text = DotNetNuke.Modules.ActiveForums.Utilities.GetSharedResource("[RESX:BadgeNotAssigned]"); + } + foreach (TableCell cell in e.Row.Cells) + { + foreach (Control cellControl in cell.Controls) + { + if (cellControl is CheckBox) + { + var chkBox = cellControl as CheckBox; + if (!(chkBox == null)) + { + chkBox.Attributes.Add("onclick", $"amaf_badgeAssign({this.ForumModuleId},{userBadgeInfo.BadgeId},{userBadgeInfo.UserId},{userBadgeInfo.UserBadgeId},$('#{cellControl.ClientID}').is(':checked'));"); + chkBox.Enabled = true; + } + } + } + } + } + } + } +} diff --git a/Dnn.CommunityForums/controls/af_assign_user_badges.ascx b/Dnn.CommunityForums/controls/af_assign_user_badges.ascx new file mode 100644 index 000000000..52669e973 --- /dev/null +++ b/Dnn.CommunityForums/controls/af_assign_user_badges.ascx @@ -0,0 +1,32 @@ +<%@ control language="C#" autoeventwireup="false" codebehind="af_assign_user_badges.ascx.cs" inherits="DotNetNuke.Modules.ActiveForums.af_assign_user_badges" %> +<%@ Register TagPrefix="asp" Namespace="System.Web.UI" Assembly="System.Web" %> +

    + [RESX:UserBadgesAssigned] +

    +
    + + + + + + + + + + + + + + + + + + + +
    +
    +
    +
    +
    +
    diff --git a/Dnn.CommunityForums/controls/af_assign_user_badges.ascx.cs b/Dnn.CommunityForums/controls/af_assign_user_badges.ascx.cs new file mode 100644 index 000000000..3d8466f3b --- /dev/null +++ b/Dnn.CommunityForums/controls/af_assign_user_badges.ascx.cs @@ -0,0 +1,125 @@ +// Copyright (c) by DNN Community +// +// DNN Community licenses this file to you under the MIT license. +// +// See the LICENSE file in the project root for more information. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +namespace DotNetNuke.Modules.ActiveForums +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web.UI; + using System.Web.UI.WebControls; + + using DotNetNuke.Collections; + using DotNetNuke.Modules.ActiveForums.Extensions.WebForms; + + public partial class af_assign_user_badges : ForumBase + { + private int? userid { get; set; } + + private DotNetNuke.Modules.ActiveForums.Entities.ForumUserInfo forumUser { get; set; } + + protected global::System.Web.UI.WebControls.Label lblBadgesAssigned; + protected global::System.Web.UI.UpdatePanel upOptions; + protected global::System.Web.UI.WebControls.GridView dgrdUserBadges; + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + this.userid = this.Request.QueryString[ParamKeys.UserId] != null ? Convert.ToInt32(this.Request.QueryString[ParamKeys.UserId]) : -1; + this.forumUser = new DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController(this.ForumModuleId).GetByUserId(this.PortalId, (int)this.userid); + this.lblBadgesAssigned.Text = string.Format(DotNetNuke.Modules.ActiveForums.Utilities.GetSharedResource("[RESX:UserBadgesAssigned]"), this.forumUser.DisplayName); + this.dgrdUserBadges.Columns[3].HeaderText = DotNetNuke.Modules.ActiveForums.Utilities.GetSharedResource("[RESX:Badge]"); + this.dgrdUserBadges.Columns[4].HeaderText = DotNetNuke.Modules.ActiveForums.Utilities.GetSharedResource("[RESX:Date]", isAdmin: true) + " (UTC)"; + + this.dgrdUserBadges.RowDataBound += this.OnUserBadgesGridRowDataBound; + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + try + { + if (this.userid > 0 && this.ForumUser.IsAdmin) + { + this.BindUserBadges(); + } + } + catch (Exception ex) + { + Exceptions.LogException(ex); + } + } + + private void BindUserBadges() + { + this.dgrdUserBadges.DataSource = this.GetBadges().ToList(); + this.dgrdUserBadges.DataBind(); + this.dgrdUserBadges.PageSize = this.dgrdUserBadges.Rows.Count; + this.dgrdUserBadges.WrapGridViewInDataTableNet(this.PortalSettings, this.UserInfo); + } + + private IEnumerable GetBadges() + { + var availableBadges = new DotNetNuke.Modules.ActiveForums.Controllers.BadgeController().Get(this.ForumModuleId).Select(badge => + { + return new { badge.BadgeId, badge }; + }); + + var assignedBadges = new DotNetNuke.Modules.ActiveForums.Controllers.UserBadgeController(this.PortalId, this.ForumModuleId).GetForUser(this.PortalId, (int)this.userid); + var assignedBadgeIds = assignedBadges.Select(userBadge => + { + return new { userBadge.UserBadgeId, userBadge.BadgeId, userBadge.DateAssigned, }; + }); + var mergedBadges = from availBadges in availableBadges + join asgnedBadges in assignedBadgeIds + on availBadges.BadgeId equals asgnedBadges.BadgeId into merged + from mrgdBadges in merged.DefaultIfEmpty() + select new DotNetNuke.Modules.ActiveForums.Entities.UserBadgeInfo(userBadgeId: mrgdBadges?.UserBadgeId ?? 0, badgeId: availBadges.badge.BadgeId, badgeName: availBadges.badge.Name, userId: (int)this.userid, userName: this.forumUser.DisplayName, portalId: this.PortalId, moduleId: this.ForumModuleId, dateAssigned: mrgdBadges?.DateAssigned, assigned: mrgdBadges != null); + return mergedBadges; + } + + protected void OnUserBadgesGridRowDataBound(object sender, GridViewRowEventArgs e) + { + if (e.Row.RowType == DataControlRowType.DataRow) + { + DotNetNuke.Modules.ActiveForums.Entities.UserBadgeInfo userBadgeInfo = e.Row.DataItem as DotNetNuke.Modules.ActiveForums.Entities.UserBadgeInfo; + if (userBadgeInfo.DateAssigned.Equals(DotNetNuke.Common.Utilities.Null.NullDate)) + { + e.Row.Cells[4].Text = DotNetNuke.Modules.ActiveForums.Utilities.GetSharedResource("[RESX:BadgeNotAssigned]"); + } + foreach (TableCell cell in e.Row.Cells) + { + foreach (Control cellControl in cell.Controls) + { + if (cellControl is CheckBox) + { + var chkBox = cellControl as CheckBox; + if (!(chkBox == null)) + { + chkBox.Attributes.Add("onclick", $"amaf_badgeAssign({this.ForumModuleId},{userBadgeInfo.BadgeId},{userBadgeInfo.UserId},{userBadgeInfo.UserBadgeId},$('#{cellControl.ClientID}').is(':checked'));"); + chkBox.Enabled = true; + } + } + } + } + } + } + } +} diff --git a/Dnn.CommunityForums/controls/af_topicscripts.ascx b/Dnn.CommunityForums/controls/af_topicscripts.ascx index fcbfef217..1fe6c2385 100644 --- a/Dnn.CommunityForums/controls/af_topicscripts.ascx +++ b/Dnn.CommunityForums/controls/af_topicscripts.ascx @@ -39,7 +39,8 @@ // Create the user editor $.fn.afUserEditor({ openTriggerSelector: ".af-button-edituser", - servicesFramework: $.ServicesFramework(<%=ModuleId%>) + servicesFramework: $.ServicesFramework(<%=ModuleId%>), + baseUrl: '<%=GetBaseUrl()%>', }); // Split selected posts diff --git a/Dnn.CommunityForums/controls/af_topicscripts.ascx.cs b/Dnn.CommunityForums/controls/af_topicscripts.ascx.cs index d24d13d75..ec200ae22 100644 --- a/Dnn.CommunityForums/controls/af_topicscripts.ascx.cs +++ b/Dnn.CommunityForums/controls/af_topicscripts.ascx.cs @@ -23,17 +23,23 @@ namespace DotNetNuke.Modules.ActiveForums.Controls using System; using DotNetNuke.Framework; + using DotNetNuke.UI.Utilities; using DotNetNuke.Web.Client.ClientResourceManagement; public partial class af_topicscripts : SettingsBase { + public string GetBaseUrl() + { + return Utilities.NavigateURL(this.TabId, string.Empty); + } + protected override void OnLoad(EventArgs e) { base.OnLoad(e); ServicesFramework.Instance.RequestAjaxScriptSupport(); ServicesFramework.Instance.RequestAjaxAntiForgerySupport(); - ClientResourceManager.RegisterScript(this.Page, Globals.ModulePath + "scripts/usereditor.js"); + ClientResourceManager.RegisterScript(this.Page, DotNetNuke.Modules.ActiveForums.Globals.ModulePath + "scripts/usereditor.js"); } } } diff --git a/Dnn.CommunityForums/controls/profile_mypreferences.ascx b/Dnn.CommunityForums/controls/profile_mypreferences.ascx index 5900c1a26..a49e0f7c4 100644 --- a/Dnn.CommunityForums/controls/profile_mypreferences.ascx +++ b/Dnn.CommunityForums/controls/profile_mypreferences.ascx @@ -37,7 +37,11 @@
    - + +
    +
    + +
    diff --git a/Dnn.CommunityForums/controls/profile_mypreferences.ascx.cs b/Dnn.CommunityForums/controls/profile_mypreferences.ascx.cs index cd5de99b4..94ec70972 100644 --- a/Dnn.CommunityForums/controls/profile_mypreferences.ascx.cs +++ b/Dnn.CommunityForums/controls/profile_mypreferences.ascx.cs @@ -24,6 +24,20 @@ namespace DotNetNuke.Modules.ActiveForums public partial class profile_mypreferences : ForumBase { + protected global::System.Web.UI.UserControl lblHeader; + protected global::System.Web.UI.WebControls.DropDownList drpPrefDefaultSort; + protected global::System.Web.UI.WebControls.DropDownList drpPrefPageSize; + protected global::System.Web.UI.WebControls.CheckBox chkPrefJumpToLastPost; + protected global::System.Web.UI.WebControls.CheckBox chkPrefTopicSubscribe; + protected global::System.Web.UI.WebControls.CheckBox chkLikesNotificationsEnabled; + protected global::System.Web.UI.WebControls.CheckBox chkPinNotificationsEnabled; + protected global::System.Web.UI.WebControls.CheckBox chkBadgeNotificationsEnabled; + protected global::System.Web.UI.WebControls.CheckBox chkEnableNotificationsForOwnContent; + protected global::System.Web.UI.WebControls.CheckBox chkPrefBlockAvatars; + protected global::System.Web.UI.WebControls.CheckBox chkPrefBlockSignatures; + protected global::System.Web.UI.WebControls.TextBox txtSignature; + protected global::System.Web.UI.WebControls.LinkButton btnSave; + public int UID { get; set; } protected override void OnLoad(EventArgs e) @@ -53,6 +67,7 @@ protected override void OnLoad(EventArgs e) this.chkPrefBlockSignatures.Checked = ui.PrefBlockSignatures; this.chkLikesNotificationsEnabled.Checked = ui.LikeNotificationsEnabled; this.chkPinNotificationsEnabled.Checked = ui.PinNotificationsEnabled; + this.chkBadgeNotificationsEnabled.Checked = ui.BadgeNotificationsEnabled; this.chkEnableNotificationsForOwnContent.Checked = ui.EnableNotificationsForOwnContent; this.txtSignature.Text = ui.Signature; } @@ -78,6 +93,7 @@ private void btnSave_Click(object sender, System.EventArgs e) upi.PrefBlockSignatures = this.chkPrefBlockSignatures.Checked; upi.LikeNotificationsEnabled = this.chkLikesNotificationsEnabled.Checked; upi.PinNotificationsEnabled = this.chkPinNotificationsEnabled.Checked; + upi.BadgeNotificationsEnabled = this.chkBadgeNotificationsEnabled.Checked; upi.EnableNotificationsForOwnContent = this.chkEnableNotificationsForOwnContent.Checked; if (this.ModuleSettings.AllowSignatures == 1 || this.ModuleSettings.AllowSignatures == 0) { diff --git a/Dnn.CommunityForums/controls/profile_mypreferences.ascx.designer.cs b/Dnn.CommunityForums/controls/profile_mypreferences.ascx.designer.cs deleted file mode 100644 index 328115b6e..000000000 --- a/Dnn.CommunityForums/controls/profile_mypreferences.ascx.designer.cs +++ /dev/null @@ -1,111 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ -namespace DotNetNuke.Modules.ActiveForums -{ - - public partial class profile_mypreferences - { - /// - /// lblHeader control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.UserControl lblHeader; - /// - /// drpPrefDefaultSort control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.DropDownList drpPrefDefaultSort; - /// - /// drpPrefPageSize control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.DropDownList drpPrefPageSize; - /// - /// chkPrefJumpToLastPost control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBox chkPrefJumpToLastPost; - /// - /// chkPrefTopicSubscribe control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBox chkPrefTopicSubscribe; - /// - /// chkLikesNotificationsEnabled control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBox chkLikesNotificationsEnabled; - /// - /// chkPinNotificationsEnabled control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBox chkPinNotificationsEnabled; - /// - /// chkEnableNotificationsForOwnContent control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBox chkEnableNotificationsForOwnContent; - /// - /// chkPrefBlockAvatars control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBox chkPrefBlockAvatars; - /// - /// chkPrefBlockSignatures control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBox chkPrefBlockSignatures; - /// - /// txtSignature control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox txtSignature; - /// - /// btnSave control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.LinkButton btnSave; - } -} diff --git a/Dnn.CommunityForums/handlers/adminhelper.ashx.cs b/Dnn.CommunityForums/handlers/adminhelper.ashx.cs index 93e975818..200942313 100644 --- a/Dnn.CommunityForums/handlers/adminhelper.ashx.cs +++ b/Dnn.CommunityForums/handlers/adminhelper.ashx.cs @@ -18,11 +18,14 @@ // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +using DotNetNuke.Modules.ActiveForums.Enums; + namespace DotNetNuke.Modules.ActiveForums.Handlers { using System; using System.Text; using System.Web; + using Newtonsoft.Json.Linq; public class adminhelper : HandlerBase { @@ -41,6 +44,9 @@ public enum Actions : int FilterGet = 11, FilterSave = 12, FilterDelete = 13, + BadgeGet = 14, + BadgeSave = 15, + BadgeDelete = 16, } public override void ProcessRequest(HttpContext context) @@ -100,7 +106,15 @@ public override void ProcessRequest(HttpContext context) break; case Actions.FilterDelete: this.FilterDelete(); - + break; + case Actions.BadgeGet: + sOut = this.GetBadge(); + break; + case Actions.BadgeSave: + this.BadgeSave(); + break; + case Actions.BadgeDelete: + this.BadgeDelete(); break; } } @@ -276,6 +290,154 @@ private void RankDelete() rc.Reward_Delete(this.PortalId, this.ModuleId, rankId); } + private string GetBadge() + { + int badgeId = -1; + if (this.Params.ContainsKey("BadgeId")) + { + badgeId = Convert.ToInt32(this.Params["BadgeId"]); + } + + var badge = new DotNetNuke.Modules.ActiveForums.Controllers.BadgeController().GetById(badgeId, this.ModuleId); + var url = string.Empty; + if (badge.FileId > 0) + { + var objFileInfo = DotNetNuke.Services.FileSystem.FileManager.Instance.GetFile(badge.FileId); + if (!ReferenceEquals(objFileInfo, null)) + { + url = objFileInfo.Folder + objFileInfo.FileName; + } + } + + string sOut = "{"; + sOut += Utilities.JSON.Pair("BadgeId", badge.BadgeId.ToString()); + sOut += ","; + sOut += Utilities.JSON.Pair("Name", badge.Name); + sOut += ","; + sOut += Utilities.JSON.Pair("Description", badge.Description); + sOut += ","; + sOut += Utilities.JSON.Pair("SortOrder", badge.SortOrder.ToString()); + sOut += ","; + sOut += Utilities.JSON.Pair("BadgeMetric", Convert.ToInt32(Enum.Parse(typeof(DotNetNuke.Modules.ActiveForums.Enums.BadgeMetric), badge.BadgeMetric.ToString())).ToString()); + sOut += ","; + sOut += Utilities.JSON.Pair("BadgeMetricEnumName", badge.BadgeMetricEnumName); + sOut += ","; + sOut += Utilities.JSON.Pair("Threshold", badge.Threshold.ToString()); + sOut += ","; + sOut += Utilities.JSON.Pair("FileId", badge.FileId.ToString()); + sOut += ","; + sOut += Utilities.JSON.Pair("ImageMarkup", badge.ImageMarkup); + sOut += ","; + sOut += Utilities.JSON.Pair("ImageUrl", badge.GetBadgeImageUrl(portalId: this.PortalId, size: 16)); + sOut += ","; + sOut += Utilities.JSON.Pair("OneTimeAward", badge.OneTimeAward.ToString()); + sOut += ","; + sOut += Utilities.JSON.Pair("IntervalDays", badge.IntervalDays.ToString()); + sOut += ","; + sOut += Utilities.JSON.Pair("SendAwardNotification", badge.SendAwardNotification.ToString()); + sOut += ","; + sOut += Utilities.JSON.Pair("SuppresssAwardNotificationOnBackfill", badge.SuppresssAwardNotificationOnBackfill.ToString()); + sOut += "}"; + return sOut; + } + + private void BadgeSave() + { + var badgeController = new DotNetNuke.Modules.ActiveForums.Controllers.BadgeController(); + var badgeId = Utilities.SafeConvertInt(this.Params["BadgeId"]); + var badge = badgeController.GetById(badgeId, this.ModuleId); + if (badge == null) + { + badge = new DotNetNuke.Modules.ActiveForums.Entities.BadgeInfo(); + badge.ModuleId = this.ModuleId; + } + + if (this.Params.ContainsKey("BadgeId")) + { + badge.BadgeId = Utilities.SafeConvertInt(this.Params["BadgeId"]); + } + + if (this.Params.ContainsKey("Name")) + { + badge.Name = this.Params["Name"].ToString(); + } + + if (this.Params.ContainsKey("Description")) + { + badge.Description = this.Params["Description"].ToString(); + } + + if (this.Params.ContainsKey("SortOrder")) + { + badge.SortOrder = Utilities.SafeConvertInt(this.Params["SortOrder"]); + } + + if (this.Params.ContainsKey("BadgeMetric")) + { + badge.BadgeMetric = string.IsNullOrEmpty(this.Params["BadgeMetric"].ToString()) || this.Params["BadgeMetric"].ToString() == "null" ? BadgeMetric.BadgeMetricManual : (Enums.BadgeMetric)Enum.Parse(typeof(DotNetNuke.Modules.ActiveForums.Enums.BadgeMetric), this.Params["BadgeMetric"].ToString()); + } + + if (this.Params.ContainsKey("Threshold")) + { + badge.Threshold = Utilities.SafeConvertInt(this.Params["Threshold"]); + } + + if (this.Params.ContainsKey("IntervalDays")) + { + badge.IntervalDays = Utilities.SafeConvertInt(this.Params["IntervalDays"]); + } + + if (this.Params.ContainsKey("ImageMarkup")) + { + badge.ImageMarkup = this.Params["ImageMarkup"].ToString(); + } + + if (this.Params.ContainsKey("FileId")) + { + badge.FileId = Utilities.SafeConvertInt(this.Params["FileId"]); + } + + if (this.Params.ContainsKey("OneTimeAward")) + { + badge.OneTimeAward = Utilities.SafeConvertBool(this.Params["OneTimeAward"].ToString()); + } + + if (this.Params.ContainsKey("SendAwardNotification")) + { + badge.SendAwardNotification = Utilities.SafeConvertBool(this.Params["SendAwardNotification"].ToString()); + } + + if (this.Params.ContainsKey("SuppresssAwardNotificationOnBackfill")) + { + badge.SuppresssAwardNotificationOnBackfill = Utilities.SafeConvertBool(this.Params["SuppresssAwardNotificationOnBackfill"].ToString()); + } + + if (badge.BadgeId == -1) + { + badgeController.Insert(badge); + } + else + { + badgeController.Update(badge); + } + } + + private void BadgeDelete() + { + int badgeId = -1; + if (this.Params.ContainsKey("BadgeId")) + { + badgeId = Convert.ToInt32(this.Params["BadgeId"]); + } + + if (badgeId == -1) + { + return; + } + + new DotNetNuke.Modules.ActiveForums.Controllers.BadgeController().DeleteById(badgeId, this.ModuleId); + } + private void PropertySave() { DotNetNuke.Modules.ActiveForums.Entities.PropertyInfo pi = new DotNetNuke.Modules.ActiveForums.Entities.PropertyInfo(); diff --git a/Dnn.CommunityForums/images/badges/AvidPoster.png b/Dnn.CommunityForums/images/badges/AvidPoster.png new file mode 100644 index 0000000000000000000000000000000000000000..303824c0eb27e9af8d1e91cbac474ada00ad978f GIT binary patch literal 577 zcmV-H0>1r;P) z)p*No1sS3daPs>5OQO7+v(z`Mb? z0F3<>#1c3THnbChWusb~d*Z%>mmnl9PMaP=aDayy;P0nFEMc;^`0gQ{0@-2#5;#UI zf#blPKrV^E`4{|09_<=_WKbzbCW(O4wiy+U&v7S^M?rrm}d2Oas(XKjp%Sk1WqGxcC-eMvEWt#P9wnGaB#3x1y^i) z6!<#U(FridIe29{!EI;&*Pikld<|>p1fByt80VGXW4nZKAqkFY6&B8Myoxon0%rCY zWF@8G*ixZ@&MwB@%&6rnj literal 0 HcmV?d00001 diff --git a/Dnn.CommunityForums/images/badges/AvidReader.png b/Dnn.CommunityForums/images/badges/AvidReader.png new file mode 100644 index 0000000000000000000000000000000000000000..54bc4453d275e051e05b1ae6c48853c1566a4cc9 GIT binary patch literal 1306 zcmV+#1?BpQP))to!q>rS@VMZo*rbJ$8@K_YNm-H8a2C+S8^<-OYXA-t-e;Gj7II6?@d>oqwAmYCP z_8s4=1Q_KzTO*ZQceBdBcC*}k3*$O98!EqLo72N0Bj=sV$k|g^+tjH9y<26c9E*)E zWo1%H-d6T&?s7KwN8b3`*9qTnlmJ^}Pb*_m=QVycNiQHpI3}2koAJDK5kkuqa&&jX z<8gzCpwzT*rg67V7E<#Z`GCYj_J}0KQs}ME)1|@Yk zk=`x~vc!DvL<%GThcQ6rC?PzO0Fx9a++?pIp0a60_hn2Adj&>e0G^>XOdT4)%qdRF z7-_`O8W~QvD1ZSVK?NHA3=nxWA4LX4j#~`DS@9jA(m96?W$uQf$AQjH2YPx2aCYOX zxHd=98tWB#1@Kj`HJ4>T@y3bP42aC1dQCs0Ak-tk2N5xWM45Ee%Zx(+={42~=j%%gAotdo%LY4|o751#>Q#sW z+g@W#D7W+w&3zUCqIUqPJ3qb1_UXceuDsMV*I@q;4-&k3z29Xfp~0DjpO;c8s1-Gy^ipW~6|4gklP5om%qEn-VW zc2Dw~JNnXh?DKR#Xp$MJ>VwojEcL?DdKBN6Y({nO?*QzaVQ*K43APyI{O!4ydTJ|k=PV26y$i6)Afovl1;5`u81r&HHBC_xB*kuPY5uJ z9mUw#7>0(1(A3m~($Z2e0m#V67=Nq8QmJ%VZfqJ|4_k zFfZWf(W8inh~P*|OZ)t-ku!^ZBO@b!fB*h{R99DXvVed9zDGqxsey$Av9Ym8Nl6*> z6NIIKmYa+MEj0E9SZKH^%{CdbcCFiNO!_i?%qW~Vj}D{KMIoy%f693 zEG$g<@Zm$u&COwEW(M8e-AGDGA~OCQ7Z=AxRa8`fg$J&38DbnZ;atE@vQ#9ym8rnB zBnONn+T-WR%oC}O_%h82KRLJ)K^7X-i<0~M`#aRt)%}&o3D2HA<76>0F$>&I9>&JT@V3&#A7Ymhp-9kpWEb*1 z4Dlh`vt0Gn$O$KXj1g|D`RDdfON8#;ULp$U?Cks_k@ofVfp$tlssa*_nVCto&dFJ6 z5;=#&*a*Xim!s56S0o_vrr=%N`bvK;Ohk2{6vu3~-(YC{Df7%}f0MaDqb=`q0avbE z!R+iTm=KCRk#m%nm!qVlgzBFQu(PuxauIe?J*3MwqT!G^CoW{fM3&~F#|U@Mle6z; zh_v4^d%%2ycIfVHmn(cF=#RF=5vy&{T)@D`h{BWfj8qtMdY; z@7}!&HdJu$-aS!3O-&7lv$Hd0JrOPnYD5ukR=ngsVFHfZY7!|~jX0S$Qk`|lE9_b8 zpG?R<%Jxg}d5R1l9y0&kd=3muPEMkwr3F({Q=)(i7cQW_zJA{I3t(bm!o8E9pO4%i z8NOtVs3X*h6DP8AQzBv^)uA>e~RvrFL3?(bw2%AhZM;v6gfFLD9Ou4p!!p6 z$nVDH6Kz;uI)s3xQIwUH@mcTVyNHkw-jtHu zq!dHm<*uhWakMiLWF-lpSwNLg>}^b*AOU3c0s#~b>Wq2r2D1WR!RL0KAA1DV1km#Y zxIF_THuD<~5)u-~&2-~IvbPPD95og?h`Y8XNJ{UR^$HTehfgazJl;{81kkfcOwZJ+ zsZ*+)b-!kn(JSN%!jeXpB`GN#*N`v{WKRMkPhKHA+zoY#WsiBt2$J*OtABYaFA`O!a}nzA_%hu^ z`xX7to!5tQOy;<7OXK&MeeGi>oeH(pyumDa#;kggqR@HC!a=1-@ue!DJHUeYQ^UH$ z&KZo|LnT|PHk#|@f?uDfa7C#v1clga|4r*r`U4q}i|C88MTxgDn|ceAi~4-Nry;MB zJP$(>qV}EU1rtg0gOc>VyWyI(!XoQk2Hiv_?MbTD@oZ-`0YhHoW(ajzFF88`it*<`Q4-EBP12|7zSG zx@M7kMed zmEZgBZg#E#!xn}gGAtAR+d62m(Ky~odxUi^HFuW3CjW{N>{+p5#royTmv5k*AgmD9 zeP0mP2rGpj{fB5J!*Ygq$YOp?f72Ccu3-{lvo)K=?Q*KK-p>wOZ7ot7uU+%)KdWzJ Z{Ttcd4b?_W4g~-J002ovPDHLkV1j(23y1&! literal 0 HcmV?d00001 diff --git a/Dnn.CommunityForums/images/badges/EngagedPoster.png b/Dnn.CommunityForums/images/badges/EngagedPoster.png new file mode 100644 index 0000000000000000000000000000000000000000..18fff43573f4ae09810a891c40a085b3ce48e5ed GIT binary patch literal 969 zcmV;)12+7LP)C7q$3w7T#Z&MQtU$2fvOx$D z1qnoELSQnJxxfs>7Y4_6yQ_*;$!fLLR?>=OCnf#v>b9)!{Qo&F**xtfzV{xJwT|`g z;)t2=vP9+!;3k0hzi$A%jL{!KmRQ8{lA`(!@U8fENZ><|j~5g=L5@#=4-^3BYm0;j zsRpJl92}&RE9m0jN-ohHt&4Ro1-Jn~7Y8popLYUf*JZfQCxOSfHcSh2o{_u37~30_ z2T)9o)_F|2M@hE+q5ste{ckq0-63E=o*)6ATI}(ts`KD_@ZIl>e%S{L@r5(!$t92{ zY{Bs7gUrb$qu-7m3HJ!e{Wkrt?_eMFL4^7%7pT8_5z(jsjXX5aM1^GIFUI@b znQ%9<41T!B@TXm{4opPzjrHua=a2x)-RE#Ow$%zSC!56UtKdDuTf5ly!y-H@s+YOm z#2y|aB1p4A>+P#Vt1BQ{a9wmBLHDTo5XNg~(C1pr00`zpllqmjcm&^1@S`+uLwxmoR^TPX6o<`}QV4JhcKcTlsak;Ks$E(o zI<*8cd1efa*Dq6FdjToHO3o#?$9u)zy@gNuIaw>hgG7|(o0r4aD_%R74cj$pXHNxK z*?BaTf=?3s{swmEE)tuZ5aIkRaQTFja77{|zW99MoX-cWeAq|;<2t*@=wH(9ZA3g0 z888Y!Gz(q~rwA{q44>?Y01fx9{~zw)52S8z?KZC0!7MkCngJC6qUt{&gdCVZGbQJF za_~C$bX9sE3pix6=r3ADLuI_whA-;D==yjTqZf=GYv>Bs~2top-7F2QR^@5vCI;gNp^2>dw8#x9{V7ZR}o%9cfGy+-Fh&iZh^U zLCUVn&Wro9^KpXPyNx^Af$;!cX`!)!n#ubvI^lpV6u_4_`3N+c2`;;+VUa%d0;cs!p^{u{o}WL?L^H^9UopiyD+3w!Hv*23^OQx}d8fiZ|q rYSq96aO4fnBX@#TmCt}rc^20Hm_RPF=#_RW00000NkvXXu0mjf004R>004l5008;`004mK004C`008P>0026e000+ooVrmw000E$ zNkl9(E6vzMPzBg}XI@7T&q>@rVgh~^E)--5PKHOkp1SN3+?nI%$MzhqTiHHoE99^Uuwj z(m>yY&d;{9*{_u{k}VHqKxXa|OBn_auVn!3xqt`2HDZlSChJVQwqRm3Xog~e zoNHE1D7ZkqQ!G&|)*r2Jc-2ZIz=EKCuldN=gEj!UtbvC82Lk|XL|~1eSVXMx2f**S zZ-RiL`EPJ!7$AY|Q6Df62q1(aB~^XP<{?W<6a$8q(kR$OEb0JEFJFZ9DJxlUk zo%VWr;NBR5%H?XU+9#e_whJ=3QlK<1q?+i#2&|!$1kYb8X3rxm!K}8^@ion3(Pn3T z#Im7$kF@7*SvCXX7tULg7k)(c=Wb*#{)CxdF2SD|4~@(Pgj+1|yaS~G*JWN}Zpha5 zf*VZ?Y0D1xhn*nAIVpiRN+krQ4*cn<)?jin1t44HUBIMV7b*x4dtwH#Z-kM^2ej508Xketj25X(P(nOK zAOfNmkSk!GVsFnaT`FmSh1Lopk!-4Yc57oL17W)`Ggt-y5rpG}qu2ZZ9Xbo=e@#3N z&zB&dKw5)X0ZbrfSY_uB-_$Y)%bI2AI@a0)Q2?NB(Gk3U;KPk~CP$lZb${EMSi6BR z2ZJyya!9HOv?fR*j85Dn538XW=)e6p-N|Z*fB*uRZKQQ1n?(7B87=W8}VE+dRfWC0u{A-0`R+A7G%CMjyps`SAkq5e# zRDg0cNK2y!T8Hlm41xfW0LUhy^OhAkbk9Hpz%ipX)><*RO0)CB326 d3as#-^Do14X-IQj4;BCb002ovPDHLkV1lKwWHkT) literal 0 HcmV?d00001 diff --git a/Dnn.CommunityForums/images/badges/HelpfulReplier.png b/Dnn.CommunityForums/images/badges/HelpfulReplier.png new file mode 100644 index 0000000000000000000000000000000000000000..3eb5d6a8e7f3939e94f7ed7d6de2a3a9d1589c25 GIT binary patch literal 1409 zcmV-{1%CR8P)Px#AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBU$|4BqaRCwCumwQlDRUF5chrC9H1mv|m3IZ{}BpD;ls`ote+v-Pv>R_j`VibMEqM*CQ$w0EGPwLixW2%=xJMrHTwFe(z;ED=;QR0G~Uc0>Fj9iN%)@y^ z*E`s`JKs*9MkI>4Ztzyl06)Y65Bbi+Cy{P6*O2@%6J2M|la+JyFjFTm;^XKZ`+ILi zInlLtl6TaRe?S@&i7`ZJvofn!M}d8@XKyCLpG+Qa{?kN+D2FbUvQhX0b6vTPiC(|y z(3q^UV&25|U1@|xh!LTciW<;C`$_A>XK1vmfqf8bqUDhZJ-di0RSQurBE_D1C`5Ih zad3?D>v3aOYpRH@GA3%tZx}!Py2@T+WQ>Un(u_#ML_y0iT@D5fq+g(;h@du6*Rx#@B zn>1ckaGKn=CXB&}30(0Pi=Rh*BWA9zH&&S6vW#U0^3u^$iFlFr$Go+{ib07on z0WSy#BG9 zfgB8iHXs4*pc%LVb&v;ISi>080}>aA-kKYbFb3EfxKLP3y0+mxr~y4iYd{-xfIXa; z7KbL#;KJSsY`Hevh}HMb^tZ9%jEO7NmGm-N6Tj_M<|RZ06mTM9@HsdIia<5!2J1O- zCq3Kn>lOK@Sz*9dKhs6{Erw}PW#5Dh!4V+mu8|;$!-+cw%vM;6I+(3^0g%1Kv^%HjE}A zZe|W)BlVdn)K`#Bmp{#>n~jz9+c!;Uw?|dqSpowuhD*_QOZ!@m&|5MqXT(QKv*_2# zV>Bgepczhl`3Px#AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBU#x=BPqRCwC$S6fRIVHnO%TNj2B5rL>bAZSa`3kh{a=wRvM9^3`R z19*{S5K&P|)?FH9c}(&w;gJfhEDv{~bd|YN?zZdBY=x#qn0M;V*YhqD$U5$fWQE|s z1H;Vsz0dP~^S$r;%(ks-Q(nA9uK^AL5d`U8v!Nt=qs*Z|22i$3YrJzH+H|h|OnR!v zqQ42U=YRtcBsipJ^e!6M{io!6fVw@$OoN&z^Yv5KOWn14%aYBcUlc5Q5d>^aWTefy zv#o9R?x#_=84J>AjkJ&min$&E;UIq#uFKQ%GYh#BlheGbsbz`JG>RYyM9%n36LU1R zun(>&clqPjb-^*#SBN!&nAJe2Dgi-<^&$IWt^GA!!@VDcxp^Bu%WSS`5rG#$KqA&6 z7ah&5OEi|loKa3-Rh@%9VTpNKh!}tXlPUoR<19fH?E?=f0LRZTn;Vc7Ax}cwDT8+PmZ=C&esjK)}0&hr(B+xyc-Nn1vRf3&UqN~1P z`9YdRL?-2{$?+I$=^PFmqwV$+@eYUwcKFYuXFwA0ekHl1zQK2RIb;x}u^IulR(@AW zgm2{toS-xxV{|kY1rpAKmx)6L8i!fc=OpvwE}1?&5?;C5Xb)) zu>MbA{+pjb`4FPWh&JT8+Cylwf2p8@D^s?6727sar9`H@GO5TUsYt_Q8cTCz%JyZ& z?W;*iPaQ|mkgM%dkx2|th?0Tv)xE>$Yt!Tv6b0;u@u))YceS)G2PnlAbS8Mi=|}?I z)3(c&V#J`b?#{6`3Mb>0jS9J+6XuH@@BmJmY%`(?*C_foBdk=m8F9R?8BI<+={>5} zjFbXJ?&+Vo)JmzP%G7q*cI@9fXznQIVbz^OmoPb@Y6XM004R>004l5008;`004mK004C`008P>0026e000+ooVrmw000IV zNkl0EgdU2KXhj;@$T*q^?}^zwyoa>C$x*9eTtkTcOcvz!(8U;MJ>6)i%b(Kx;^b z5S4=Hahb5%EifB+7$qRbDpdXVrh?`pyQ^02cp%FSRXd`A>arL&M?)_k{_@nSv)w~A z6$Lt5!Z-TZHm54UktFJkJWMEZ{DeC3* zEAreC4P-fE|7Ee7sizOs2M_hnZ~wZ#TO)+$jnoh5f&p9zj=LbkLRZFEDB|?Mz<|Gd z)7oA0*EGIg?fF@T(PXNKXh7hJV;t{+q&eK(7w94)AJ0YxoSoC+*5zdX|*~RKafHEAx&>9tG z!7OS8W50K(E206fPiYsmq9!>>m(}BgU-pw3V5D} z$cL<8*wnzFf^*%yki93N1iIn({fNFE5Bk;o={|y1C-B?X6;z9H=J|&@J+BUHUy1>A z{V@2{4ko6i@kLNrBLw*Pv2^wwq7CAsTb1sPQI(l%r^9y)?J^;_L&vBx& zTg@x@>V$$fzF@AS-lz>99|^p@eaDff@Mq8qkW$C-MFmMh>+;zKI=c5iboyXDwJfz# zxkCt@bd^ql8r9RV^_~RvM0C(w>yzoeYxPu?E>OCOQF07xwd(mI022Nx6U@vp(}!g3&7IEn{iqZ#}P@Y4WcFhHR*gJamC71$PxCN@1wh>vEQEzzuZN&-*w z>^v>X;ORb>Kno@alpV{_@LGb7ZB8|ER$L*3!bE=cvv+0Eg9|LQXo^U?H?L= zUrTm9R>wti0vBKXa#sf3SgfT_cg&%kn`hAMZ0UnUJ*HtSs4p?pwXVzV zU#4!){V&X=dmGaFlcG?Eu|fp2&8wW-HZDq`osYYzdaB_$s5y)!Pv1NFiRMNJ?SE-5 z)fAhW@E74O>vfn2N-zK-!q^+&7zlu(C?Nx5$~a*BLyOX0XcwI!DAk1cg5%PWlZS?dg1e@mv4m7sgkZg&=DII`oN6Z5%I{R@&( zoHn)7YZzni8Fbp+-<~ln*z={t4)rA9wOs=^cs!ahLrSeiquDKrn)d}!^FU6n+lJA? zk(#kI&vg}*S5#4PaXIDX7EylgRa7#yl&UJL=>PRMQhoi+G;2;BU0pJZTzS(dXOe3f zMvDS_OvMfV&S}}Sw&BftZmZl^mghX+a%Q%*&pfu`leKqVx38)+ z_pRKF~A|w*UYD07*qoM6N<$f+F8Dr2qf` literal 0 HcmV?d00001 diff --git a/Dnn.CommunityForums/images/badges/MostLiked.png b/Dnn.CommunityForums/images/badges/MostLiked.png new file mode 100644 index 0000000000000000000000000000000000000000..d8f90828e2e69f3bcfe1d911905697aa294b5aee GIT binary patch literal 1633 zcmV-n2A=teP)Px#AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBU%-$_J4RCwC8R%uLBR}>y&(l%+6rb%NHW9yHmf7;sE#Hujwy?N{G zE5i(+h$xy=3M#gCVG%4!ix5(+N=2mZwt(VR7esNvt*9_>=Jeb* zz+f0EGtGe&2lO+;fjA)L;emTPBfO9;c;i7aN$n$wmzhKA?dU)?OYF_=KBv4MbL=}ImXU?Y>HC|ljUu0mKCu!*loj@hvoL7P?LK8o45UKdN zdZuBkjq^1|3eXlM!aq?G+{5PumjD%Z4w4MaRTPpU2-K@&ohVRmBT3;pv*y9U2p+Dx zaZT5{Tljv=DZpk6`#3>ISE5K7g$(OM&hhFO93qvr)~sp29 zs2{DYFGixbA-QRmjy}52!NcR|z;`*;2;RvC@RE0&>vIdr`w0~Cse!qo7br^~0ciQ0 zY%}}tK~#Xu+Y23t`Unnc>@0MD??jZMOY`*1{gX~1xCRO3>{TGAFAWIz+5>V%G78dz zAHQ96i6opCML|8jha6-2&Qknmt6S_tPEc;=Va2RCSUztC6xg`H#)yX~rr9O-neR=A z0Pl2rU|#Zk@cmW^zOo|l##_-LQE?((OPAA1PJA$aSfoT{>_rRx!A*Kd?qJ;4&WMJV zh8k$8-w&yAPPm4-A$QLSAsAgibP03w;GJqw1o*ZWfOnE!aWvP=wrd3{S{2T#M}4Gc z>TkHkKAZUv7o8mBESU@5YYpISsRz%Z*>J+a2Amowh?oQi_-pqON0gj6jxJ2r(%V!l zuV&YnGPpx6Xj?dLyh)UHJb5AgTPxOw5N0@WvXIV~TY`RtbXIjRGFa zA;@oH{5{j$(Arq5IM9CS1fz#0I9NS< zDsms}63_&@OSeFpks%@I!I7?Ki%S@=2tT3@D`vDr=c~*T?Xc^)rZlSv*>({M?K~X7 z4L$KLXsFq#5JT%JMZ}@1V%U(r3^sd`dhm^BIeeMC0Fq*?u;0NCNW>!qCjLFFqGpvT z%H1kue97;?@2CU5>@Y|xvtVa_4#4fRgmhrIaS9$a{|OoM6X3Elqzl2sb}Pwu zRp>6o#%U;^cpvbkwTcL7MJ7}h2fXK^CfpV(`{Qdm;J(!@_GyKd6 z)JVcRbOO+Ra#5vCjf56*NrfPx6U21(f8iffBUW7b51Bb`G!;D%bGp z(W+2GIR(Ylz;8c@0{%b&Sx{NHVPK~KV}F%g(O5ICVDkBTk+(-l@RN{X_rM%r>7=sU%LoY=7FYGUJ}JhP^k^I&sWsYuK1K ztm?5ZGvVWgX(o()Q^!ou8@Mn_5BTuaQzWXb$il)g2M5iO{1aUfcEsd@Ij6(+JdCvM zLp`u%AC5&NB2mvY)*xATX}ymQ6j?bxme*gg!o9D0)&q~zyLhIz|6pZ1No$pX7mHn_ fR-xr12D{h4qV^eVJvt=M00000NkvXXu0mjf-ud;e literal 0 HcmV?d00001 diff --git a/Dnn.CommunityForums/images/badges/NewMember.png b/Dnn.CommunityForums/images/badges/NewMember.png new file mode 100644 index 0000000000000000000000000000000000000000..60783a8b9269fd389f6611d9a1288fbcb26abd64 GIT binary patch literal 1393 zcmV-%1&;cOP)Px#AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBU$?@2^KRCwCeRcla`Wfb03uu*6tG^&}{AB=yjsXv;P2>fDnbb(zE zG$4(jC}ZQMILMSE!Ze`}7YT&88H30`H8wUwG>#MqhLqePuIpYuu9>XJvUNJ=%UO5# z+ix$ZKRh$f%)94(&hwo2^1Ul~A|tIqyY5(n)(auJkLM`&SWVGnBbrE#Uex9tsn`CP zd_mKnRHu;>XiPbpLtZe#^HCamqH#jX1ZJyq!5#n}6 zCDf`_(YUfu6gGtfO~b!ZKwOoIfMYht;ZZGWC{QcncoQRZxB)DP{;)}j%TVMUX0rEdoKqUGi^awfo*26>=YFsA{0L~{2P6Nw*^ zLOG;X4}yA5$6fvGA|zD~upFCWmo6H z)`cc7@-#NEJ-&Q>Nd9OG-?rzs%)*lXUvM;to7X(cdmQ9No&wXr+g;4*6hVKjy^1Ap zHhQpzYNggL@#(%?fo1GE*&Zn^n$lame)PZ2{`oi=RD-qLXPG>9pX%7pX<%zifhag{ z_@-q8@io+dVHFJ+u$J2Zdi=31rqEkpC4{?9wtW^_B>%_k2uh})b7UTzjrO5Asx>Laib!X2{Oa7q3cW43KyjzVyD2c%VWLEV)x=o*;@Idcb?g}W@KaEv*e8--)Y z3CixonlUidKuztAgm1z)tLKEPi<^IHQ?jIBV$S07z}}nz*nR3ch%^6xf}?T>?3i*m z_ZxADYi?dJKD#ryL59{F1dfF3vtAy4DUGRE$e13-{V^KI@mn5;5L_jT{0YjjbC!Hs z`Oc*JL>G^Z&j_4}wQf&)y#9X4L2*uRCyE(Nh3$jo8pJt$o!jDyqt|S3L-W$_mOI?895ECvk*TQv!09gU$^02BcleqFT}rJY=jDtPyyk*c)$sT$6;KQI$BS zr#&QZWSq8_fa5XB1)jKC@#f*`PhRp3-%d4b?IR2la~D44`l7qfYg004R>004l5008;`004mK004C`008P>0026e000+ooVrmw000DM zNklLL$#S`!*|}0U6J+&Ft=7nJq_Oct?qLz;(U;R@=_B z9T%4IfO}TmD9q>WkLA=`pT>IzKw$w5Rv|`b9#TrZ;VE?xBwL!gZp_~;48^kR45d^@ zvm*2%dY^Oa!U-*we9dz`517+5?Gu5|06VOKzeP?YlgZb&4sRimh*P#3SW2Vi>d?V} z019Y28oilhZe(I-E|t!)uyAk3?b+G=o)2&;tbt*r)X`l##yE25X+(ti#d#(dYb;hh zgw7}+?Fl1;Cj0h1L&8i`$S?BwmtSP^#lrJ`CQbuR7y|<$l3U-K!@mjNJiR@=JQcIB zohGXzB+Yfccq+KhFbv}HI6yyOgf$=pv5cv8nG}BtXLMV>jFY| zRFJuJD&67w2nKB1W_soin$0GNgwe+^VvKFyjsQqR10sSS!5Z$}Gr?L>3QDaicpeyu zjQ!-xgTPE^1F3Y9RLaD%YC%f75p)^>!S(q_3(=-F|Lb1rXpU>0K<9HK~BZH4N6#O7iTT=}v6e1eg zYzEVD5IW1V-p9j;GJ(LXXmerS}NB?ou5MEdHF)aw3#M!t`O*GU}k*>7{;)cPV ziJhxvK!A!KMhd7h|Ey;Y@=~xhz4( zQISV+FocrH1eR5$;zxUV4xkjc=@dnK17|#)JGPK6FNtSR2&#*CxD2SE2G}vS9TEB0 z1p4mM3|Hy%MN{{QcOjgCTCG8&-o*116{~#TZYTofa)sH;lRP#$&hFec2GSkHqZ@D? z7bl1gyP*PI*EoFe02>Adf(fV;k%-ZS)pkP>`Ddw!j0VwB-IP_d^MDPwj^kms-JsW_ z;5r^4!4FVtF>njGedFfs@xcv)!7dktpinCntg3~GOe4}<%a_q{5jmMkCVRRZM!Fv7 znyuDvz%k&b&_yW1M@p%i)mrTc5GNV}%!|lr;L3mYOZzX72@7+CN#FGV0000Px#AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBU#v`IukRCwCemd$HiRT##9&->mPjiKx)wLB2rhIdSVRyMT-xZyg$Z; zWCZ)dk9#=hdFOe~nKPH+e_cn9KRXsQ{?6pFna0@Nk2QwxI?<@#`AB2%=tGU#)PwPS zxN*m^QENOO|SDaIBE1(xPI8k9)AZ^mbh?l^#C2PJ2fno3{xo{;Rojst)bD4-%ka>BI4EuI!AAteoX7j_yzSr;57 zGt8DIgR0K&UMVCtBAqB?;D|6n&K;9XH=NJW}UM&0{%aS44JGQ3L&w&~f` zCG1WzOLV)0-mgpOYr*w^iewU|BvKGhA%F~ZE@H)Eu(9(1a9!9L$v=^@EhTg4dIwUN z&U(^jP02qM_8hRVn*acp!JZDD3BCa@gd?gDUR}ZzAT(g#l6p=8p8@PP0KhWvF0v;i zKac#E07y_8r!e5xN=;~icYq~sP#L|~&-2a6SNHS7M}z3}NX?%baq1wJn`|z(?ERHy z`}K|N-tT~ds`?gyrN=)u6{;<4+S>e@nkj&>(z30IVg5W^zdBIpM+4gQSXz2{h8}B_ zf)|5XVB7>asdC5zU;%M4cmr6Whq4~esg83#c!?V0y2apDN4F<9?38mg4&j_Fwb9eJ z0CJrSW;LkH4mmdNXvCl%3>q;m=VA?oMy{FQ$-V^8J{`n4MMhl*9F01-O7f+Ge5HU) z;40Tb0~td&vt{p|17u7G_iI>TV06ri7UaLR$$xEAG)bYdq$#x-$K_1#IRMUm<&K68 z27)%^^DXkLO=uO+EQoPAN1LP>3Zf^N>cZ{1;pgx>{ zuHmHJnV@di)IjH$6EU{QTH3jb1dyrdLjbk6j#FwSDS wl+6FbTKVvKtz0@Y7Bos?y!ycl;%2PB0IRL^Q0$c_aR2}S07*qoM6N<$f 0 AND ForumId = @ForumId) @@ -1916,7 +1915,7 @@ SELECT * FROM {databaseOwner}{objectQualifier}activeforums_Categories WHERE Port (@ForumGroupId > 0 AND ForumGroupId = @ForumGroupId) OR (ForumId = -1 AND ForumGroupId = -1) - ) + ) ORDER BY CategoryName GO @@ -2774,3 +2773,4 @@ GO /* issue 1557 - end - forum viewer issues */ /* --------------------- */ + diff --git a/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider b/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider index 3e162ab57..097f38057 100644 --- a/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider +++ b/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider @@ -1,5 +1,6 @@ SET NOCOUNT ON GO + /* issue 1582 - begin - settings table overhaul */ @@ -822,43 +823,6 @@ SELECT DISTINCT userid, email, topicsubscriber FROM @subs GO -/* activeforums_SettingsTable */ -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_SettingsTable]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT')) -DROP FUNCTION {databaseOwner}[{objectQualifier}activeforums_SettingsTable] -GO -CREATE FUNCTION {databaseOwner}[{objectQualifier}activeforums_SettingsTable]( -@SettingsKey nvarchar(255) -) -RETURNS TABLE -AS -RETURN -( -SELECT pvt.SettingKey, [ALLOWATTACH],[ALLOWEMOTICONS],[ALLOWHTML],[ALLOWPOSTICON],[ALLOWRSS],[ALLOWSCRIPT],[ALLOWTAGS],[ATTACHCOUNT],[ATTACHMAXHEIGHT],[ATTACHMAXSIZE],[ATTACHMAXWIDTH],[ATTACHSTORE],[ATTACHTYPEALLOWED],[ATTACHUNIQUEFILENAMES],[AUTOSUBSCRIBEENABLED],[AUTOSUBSCRIBENEWTOPICSONLY],[AUTOSUBSCRIBEROLES],[ATTACHINSERTALLOWED],[MAXATTACHHEIGHT],[MAXATTACHWIDTH],[CONVERTINGTOJPEGALLOWED],[AUTOTRUSTLEVEL],[DEFAULTTRUSTLEVEL],[EDITORHEIGHT],[EDITORPERMITTEDUSERS],[EDITORSTYLE],[EDITORTOOLBAR],[EDITORTYPE],[EDITORWIDTH],[EMAILADDRESS],[INDEXCONTENT],[ISMODERATED],[MCADDRESS],[MCADMINNOTIFY],[MCAUTOCREATEUSERS],[MCAUTORESPONSE],[MCENABLED],[MCEOMTAG],[MCEOMTAGREQ],[MCMODTYPE],[MCPOPPASSWORD],[MCPOPSERVER],[MCPOPUSERNAME],[MCREJECTNOTIFY],[MCRESTRICTALIAS],[MCSTRIPHTML],[MCSUBNOTIFY],[MCURL],[MODAPPROVETEMPLATEID],[MODDELETETEMPLATEID],[MODMOVETEMPLATEID],[MODNOTIFYTEMPLATEID],[MODREJECTTEMPLATEID],[PROFILETEMPLATEID],[QUICKREPLYFORMID],[REPLYFORMID],[TOPICFORMID],[TOPICSTEMPLATEID],[TOPICTEMPLATEID],[USEFILTER] from - ( - SELECT SettingKey, SettingName, SettingValue FROM [dbo].activeforums_Settings - ) s PIVOT (MAX(SettingValue) FOR SettingName IN ([ALLOWATTACH],[ALLOWEMOTICONS],[ALLOWHTML],[ALLOWPOSTICON],[ALLOWRSS],[ALLOWSCRIPT],[ALLOWTAGS],[ATTACHCOUNT],[ATTACHMAXHEIGHT],[ATTACHMAXSIZE],[ATTACHMAXWIDTH],[ATTACHSTORE],[ATTACHTYPEALLOWED],[ATTACHUNIQUEFILENAMES],[AUTOSUBSCRIBEENABLED],[AUTOSUBSCRIBENEWTOPICSONLY],[AUTOSUBSCRIBEROLES],[ATTACHINSERTALLOWED],[MAXATTACHHEIGHT],[MAXATTACHWIDTH],[CONVERTINGTOJPEGALLOWED],[AUTOTRUSTLEVEL],[DEFAULTTRUSTLEVEL],[EDITORHEIGHT],[EDITORPERMITTEDUSERS],[EDITORSTYLE],[EDITORTOOLBAR],[EDITORTYPE],[EDITORWIDTH],[EMAILADDRESS],[INDEXCONTENT],[ISMODERATED],[MCADDRESS],[MCADMINNOTIFY],[MCAUTOCREATEUSERS],[MCAUTORESPONSE],[MCENABLED],[MCEOMTAG],[MCEOMTAGREQ],[MCMODTYPE],[MCPOPPASSWORD],[MCPOPSERVER],[MCPOPUSERNAME],[MCREJECTNOTIFY],[MCRESTRICTALIAS],[MCSTRIPHTML],[MCSUBNOTIFY],[MCURL],[MODAPPROVETEMPLATEID],[MODDELETETEMPLATEID],[MODMOVETEMPLATEID],[MODNOTIFYTEMPLATEID],[MODREJECTTEMPLATEID],[PROFILETEMPLATEID],[QUICKREPLYFORMID],[REPLYFORMID],[TOPICFORMID],[TOPICSTEMPLATEID],[TOPICTEMPLATEID],[USEFILTER])) as pvt -) - -GO - - -/*activeforums_ForumsList*/ -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_ForumsList]') AND type in (N'P', N'PC')) -DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_ForumsList] -GO -CREATE PROCEDURE {databaseOwner}[{objectQualifier}activeforums_ForumsList] -@PortalId int, -@ModuleId int -AS -SELECT F.*,P.*,s.*,G.GroupName,G.Active as GroupActive, G.Hidden as GroupHidden,ISNULL(g.PrefixURL,'') as GroupPrefixURL,GETUTCDATE() as LastRead from {databaseOwner}{objectQualifier}activeforums_Forums as f INNER JOIN - {databaseOwner}{objectQualifier}activeforums_Groups as G ON F.ForumGroupId = G.ForumGroupId INNER JOIN - {databaseOwner}{objectQualifier}activeforums_Permissions as P ON P.PermissionsId = f.PermissionsId INNER JOIN - {databaseOwner}{objectQualifier}activeforums_SettingsTable('F') as s ON s.SettingKey = f.ForumSettingsKey -WHERE F.PortalId = @PortalId AND (F.ModuleId = @ModuleId OR @ModuleId=-1) -ORDER BY G.SortOrder, F.SortOrder - -GO - /* activeforums_Forums_List */ IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Forums_List]') AND type in (N'P', N'PC')) @@ -1096,6 +1060,132 @@ GO /* --------------------- */ + +/* issue 1599 - begin - don't update UserProfile Reply count from activeforums_Reply_Save */ + +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Reply_Save]') AND type in (N'P', N'PC')) +DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Reply_Save] +GO + +CREATE PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Reply_Save] +@PortalId int, +@TopicId int, +@ReplyId int, +@ReplyToId int, +@StatusId int, +@IsApproved bit, +@IsDeleted bit, +@Subject nvarchar(255), +@Body nvarchar(max), +@DateCreated datetime, +@DateUpdated datetime, +@AuthorId int, +@AuthorName nvarchar(150), +@IPAddress nvarchar(50) +AS +DECLARE @ContentId int +DECLARE @IsEdit bit +SET @IsEdit = 0 +DECLARE @ApprovedStatus bit +SET @ApprovedStatus = @IsApproved + +-- This part is a work around for Quick Reply feature not working for Tapatalk STARTS + +DECLARE @TopicSubject NVARCHAR(255) = ( + SELECT top 1 afc.Subject FROM {databaseOwner}[{objectQualifier}activeforums_Topics] aft + JOIN {databaseOwner}[{objectQualifier}activeforums_Content] afc ON aft.ContentId = afc.ContentId + WHERE TopicId = @TopicId + ) + +SET @Subject = ISNULL(NULLIF(@Subject, ''), 'RE: ' + @TopicSubject) + +IF (@Subject NOT LIKE 'RE:%') +BEGIN + SET @Subject = 'RE: ' + @Subject +END +-- This part is a work around for Quick Reply feature not working for Tapatalk ENDS + + +IF EXISTS(SELECT ContentId FROM {databaseOwner}{objectQualifier}activeforums_Replies WHERE ReplyId = @ReplyId) +BEGIN + SELECT @ContentId = ContentId, @ApprovedStatus = IsApproved FROM {databaseOwner}{objectQualifier}activeforums_Replies WHERE ReplyId = @ReplyId + + BEGIN + SET @IsEdit = 1 + UPDATE {databaseOwner}{objectQualifier}activeforums_Content + SET Subject = @Subject, + Body = @Body, + DateCreated = @DateCreated, + DateUpdated = @DateUpdated, + AuthorId = @AuthorId, + AuthorName = @AuthorName, + IsDeleted = @IsDeleted, + IPAddress = @IPAddress + WHERE ContentId = @ContentId + UPDATE {databaseOwner}{objectQualifier}activeforums_Replies + SET StatusId = @StatusId, + TopicId = @TopicId, + IsApproved = @IsApproved, + IsDeleted = @IsDeleted, + ReplyToId = @ReplyToId + WHERE ReplyId = @ReplyId +END + END +ELSE +--INSERT +BEGIN + BEGIN + INSERT INTO {databaseOwner}{objectQualifier}activeforums_Content + (Subject, Body, DateCreated, DateUpdated, AuthorId, AuthorName, IsDeleted, IPAddress) + VALUES + (@Subject, @Body, @DateCreated, @DateUpdated, @AuthorId, @AuthorName, @IsDeleted, @IPAddress) + SET @ContentId = SCOPE_IDENTITY() + END + BEGIN + INSERT INTO {databaseOwner}{objectQualifier}activeforums_Replies + (ContentId, TopicId, StatusId, IsApproved, IsDeleted, ReplyToId) + VALUES + (@ContentId, @TopicId, @StatusId, @IsApproved, @IsDeleted, @ReplyToId) + SET @ReplyId = SCOPE_IDENTITY() + + END + + +END +IF @IsApproved = 1 + BEGIN + DECLARE @ForumId int + SELECT @ForumId = ForumId FROM {databaseOwner}{objectQualifier}activeforums_ForumTopics WHERE TopicId = @TopicId + DECLARE @TotalReplies int + SET @TotalReplies = (SELECT Count(ReplyId) from {databaseOwner}{objectQualifier}activeforums_replies as r inner join {databaseOwner}{objectQualifier}activeforums_topics as t on t.topicid = r.topicid and r.isapproved = 1 and r.isdeleted = 0 INNER JOIN {databaseOwner}{objectQualifier}activeforums_forumtopics as ft on t.topicid = ft.topicid WHERE ft.forumid = @ForumId) + UPDATE {databaseOwner}{objectQualifier}activeforums_Forums + SET LastTopicId = IsNull(@TopicId,0), LastReplyId = IsNull(@ReplyId,0), TotalReplies = ISNULL(@TotalReplies,0) + WHERE ForumId = @ForumId + UPDATE {databaseOwner}{objectQualifier}activeforums_Topics + SET ReplyCount = (Select Count(ReplyId) from {databaseOwner}{objectQualifier}activeforums_Replies WHERE TopicId = @TopicId AND IsDeleted = 0 AND IsApproved = 1) + WHERE TopicId = @TopicId + END + + +/* populate ModuleId in activeforums_Content */ +UPDATE c +SET c.ModuleId = f.ModuleId +FROM {databaseOwner}[{objectQualifier}activeforums_Content] c +LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Replies] r +ON r.ContentId = c.ContentId +LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_ForumTopics] ft +ON ft.TopicId = r.TopicId +LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f +ON f.ForumId = ft.ForumId +WHERE c.ModuleId IS NULL AND r.ReplyId = @ReplyId + + +SELECT @ReplyId +GO +/* issue 1599 - end - don't update UserProfile Reply count from activeforums_Reply_Save */ +/* --------------------- */ + + /* Issue 1594 - Begin - update activeforums_Topics_Move procedure to remove previously-removed LastPostId from activeforums_Forums */ IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Topics_Move]') AND type in (N'P', N'PC')) DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Topics_Move] @@ -1136,3 +1226,1035 @@ GO /* Issue 1594 - End - update activeforums_Topics_Move procedure to remove previously-removed LastPostId from activeforums_Forums */ /* --------------------- */ + +/* issue 1479 - begin - add badge notification option to user profile */ + +/* add BadgeNotificationsEnabled to activeforums_UserProfiles */ +IF NOT EXISTS(SELECT * FROM SYS.COLUMNS WHERE Name = N'BadgeNotificationsEnabled' and Object_ID = Object_ID(N'{databaseOwner}[{objectQualifier}activeforums_UserProfiles]')) +BEGIN + ALTER TABLE {databaseOwner}[{objectQualifier}activeforums_UserProfiles] ADD + [BadgeNotificationsEnabled] [bit] NOT NULL CONSTRAINT [DF_{objectQualifier}activeforums_UserProfiles_BadgeNotificationsEnabled] DEFAULT(1) +END +GO + +/* issue 1479 - end - add badge notification option to user profile */ + +/* --------------------- */ + +/* issue 1480 - begin - badges */ + + +/* activeforums_Badges */ +IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Badges]') AND type in (N'U')) +CREATE TABLE {databaseOwner}[{objectQualifier}activeforums_Badges] ( + BadgeId INT IDENTITY(1,1) NOT NULL, + ModuleId INT NOT NULL, + Name NVARCHAR(100) NOT NULL, + Description NVARCHAR(MAX) NULL, + ImageMarkup NVARCHAR(MAX) NULL, + FileId INT NOT NULL, + BadgeMetric INT NOT NULL, + SortOrder INT NOT NULL, + Threshold INT NOT NULL, + IntervalDays INT NOT NULL, + OneTimeAward BIT NOT NULL CONSTRAINT DF_{objectQualifier}activeforums_Badges_OneTimeAward DEFAULT(1), + SendAwardNotification BIT NOT NULL CONSTRAINT DF_{objectQualifier}activeforums_Badges_SendAwardNotification DEFAULT(1), + SuppresssAwardNotificationOnBackfill BIT NOT NULL CONSTRAINT DF_{objectQualifier}activeforums_Badges_SuppresssAwardNotificationOnBackfill DEFAULT(1), + InitialBackfillCompletedDate DATETIME NULL, + CONSTRAINT PK_{objectQualifier}activeforums_Badges PRIMARY KEY CLUSTERED (BadgeId ASC) +) +GO + +/* activeforums_UserBadges */ +IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_UserBadges]') AND type in (N'U')) +CREATE TABLE {databaseOwner}[{objectQualifier}activeforums_UserBadges] ( + UserBadgeId INT IDENTITY(1,1) NOT NULL, + PortalId INT NOT NULL, + ModuleId INT NOT NULL, + UserId INT NOT NULL, + BadgeId INT NOT NULL, + DateAssigned DATETIME NOT NULL, + CONSTRAINT PK_{objectQualifier}activeforums_UserBadges PRIMARY KEY CLUSTERED (UserBadgeId ASC) +); + +/*DF_activeforums_UserBadges_DateAssigned*/ +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}DF_{objectQualifier}activeforums_UserBadges_DateAssigned') AND type = 'D') + ALTER TABLE {databaseOwner}[{objectQualifier}activeforums_UserBadges] DROP CONSTRAINT [DF_{objectQualifier}activeforums_UserBadges_DateAssigned]; +GO +ALTER TABLE {databaseOwner}[{objectQualifier}activeforums_UserBadges] ADD CONSTRAINT [DF_{objectQualifier}activeforums_UserBadges_DateAssigned] DEFAULT (GETUTCDATE()) FOR [DateAssigned]; +GO + +/* activeforums_Badges - cascade delete from Modules */ +IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'{databaseOwner}[FK_{objectQualifier}activeforums_Badges_Modules]') AND parent_object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Badges]')) +ALTER TABLE {databaseOwner}[{objectQualifier}activeforums_Badges] DROP CONSTRAINT +[FK_{objectQualifier}activeforums_Badges_Modules] +GO +ALTER TABLE {databaseOwner}[{objectQualifier}activeforums_Badges] ADD CONSTRAINT + [FK_{objectQualifier}activeforums_Badges_Modules] FOREIGN KEY (ModuleId) + REFERENCES {databaseOwner}[{objectQualifier}Modules] (ModuleID) + ON DELETE CASCADE +GO + +/* activeforums_Badges - cascade delete from Modules */ +/* drop constraint */ +IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'{databaseOwner}[FK_{objectQualifier}activeforums_Badges_Modules]') AND parent_object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Badges]')) +ALTER TABLE {databaseOwner}[{objectQualifier}activeforums_Badges] DROP CONSTRAINT +[FK_{objectQualifier}activeforums_Badges_Modules] +GO + +/* activeforums_UserBadges - cascade delete from activeforums_UserProfiles */ +/* drop constraint */ +IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'{databaseOwner}[FK_{objectQualifier}activeforums_UserBadges_UserProfiles]') AND parent_object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_UserBadges]')) +ALTER TABLE {databaseOwner}[{objectQualifier}activeforums_UserBadges] DROP CONSTRAINT +[FK_{objectQualifier}activeforums_UserBadges_UserProfiles] +GO + +/* drop/create index IX_activeforums_UserProfiles_Opt3 -- Needs to be unique */ +IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'{objectQualifier}activeforums_UserProfiles') AND name = N'IX_{objectQualifier}activeforums_UserProfiles_Opt3') +DROP INDEX [IX_{objectQualifier}activeforums_UserProfiles_Opt3] ON {databaseOwner}{objectQualifier}activeforums_UserProfiles +GO +CREATE UNIQUE NONCLUSTERED INDEX [IX_{objectQualifier}activeforums_UserProfiles_Opt3] ON {databaseOwner}{objectQualifier}activeforums_UserProfiles + ( + [PortalId] ASC, + [UserId] ASC + ) +INCLUDE ( [ProfileId], +[TopicCount], +[ReplyCount], +[ViewCount], +[AnswerCount], +[RewardPoints], +[UserCaption], +[DateCreated], +[DateUpdated], +[DateLastActivity], +[Signature], +[SignatureDisabled], +[TrustLevel], +[AdminWatch], +[AttachDisabled], +[AvatarDisabled], +[PrefDefaultSort], +[PrefDefaultShowReplies], +[PrefJumpLastPost], +[PrefTopicSubscribe], +[PrefSubscriptionType], +[PrefEmailFormat], +[PrefBlockAvatars], +[PrefBlockSignatures], +[PrefPageSize], +[DateLastPost]) WITH (SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) +GO + +/* drop/create index IX_activeforums_UserBadges_Alt1 */ +IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'{databaseOwner}{objectQualifier}activeforums_UserBadges') AND name = N'IX_{objectQualifier}activeforums_UserBadges_Alt1') +DROP INDEX [IX_{objectQualifier}activeforums_UserBadges_Alt1] ON {databaseOwner}{objectQualifier}activeforums_UserBadges +GO +CREATE NONCLUSTERED INDEX IX_{objectQualifier}activeforums_UserBadges_Alt1 + ON {databaseOwner}[{objectQualifier}activeforums_UserBadges] + ( + PortalId ASC, + UserId ASC, + BadgeId ASC, + DateAssigned ASC + ) + +GO + +/* add constraint FK_activeforums_UserBadges_UserProfiles */ +ALTER TABLE {databaseOwner}[{objectQualifier}activeforums_UserBadges] ADD CONSTRAINT + [FK_{objectQualifier}activeforums_UserBadges_UserProfiles] FOREIGN KEY (PortalId, UserId) + REFERENCES {databaseOwner}[{objectQualifier}activeforums_UserProfiles] (PortalId, UserId) + ON DELETE CASCADE +GO + +/* activeforums_UserBadges - cascade delete from activeforums_Badges */ +/* drop constraint */ +IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'{databaseOwner}[FK_{objectQualifier}activeforums_UserBadges_Badges]') AND parent_object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_UserBadges]')) +ALTER TABLE {databaseOwner}[{objectQualifier}activeforums_UserBadges] DROP CONSTRAINT +[FK_{objectQualifier}activeforums_UserBadges_Badges] +GO + +/* drop/create index IX_activeforums_UserBadges_Alt2 */ +IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'{databaseOwner}{objectQualifier}activeforums_UserBadges') AND name = N'IX_{objectQualifier}activeforums_UserBadges_Alt2') +DROP INDEX [IX_{objectQualifier}activeforums_UserBadges_Alt2] ON {databaseOwner}{objectQualifier}activeforums_UserBadges +GO +CREATE NONCLUSTERED INDEX IX_{objectQualifier}activeforums_UserBadges_Alt2 + ON {databaseOwner}[{objectQualifier}activeforums_UserBadges] + ( + BadgeId ASC, + PortalId ASC, + UserId ASC, + DateAssigned ASC + ) +GO + +/* add constraint FK_activeforums_UserBadges_Badges */ +ALTER TABLE {databaseOwner}[{objectQualifier}activeforums_UserBadges] ADD CONSTRAINT + [FK_{objectQualifier}activeforums_UserBadges_Badges] FOREIGN KEY (BadgeId) + REFERENCES {databaseOwner}[{objectQualifier}activeforums_Badges] (BadgeId) + ON DELETE CASCADE +GO + + +/* update activeforums_URL_Search for new view types for badges */ + +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_URL_Search]') AND type in (N'P', N'PC')) +DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_URL_Search] +GO + +CREATE PROCEDURE {databaseOwner}[{objectQualifier}activeforums_URL_Search] +@PortalId int, +@Url nvarchar(max) +AS +DECLARE @views TABLE(id int,viewname nvarchar(50)) +INSERT INTO @views (id,viewname) VALUES (1,'unanswered'); +INSERT INTO @views (id,viewname) VALUES (2,'notread'); +INSERT INTO @views (id,viewname) VALUES (3,'mytopics'); +INSERT INTO @views (id,viewname) VALUES (4,'activetopics'); +INSERT INTO @views (id,viewname) VALUES (5,'afprofile'); +INSERT INTO @views (id,viewname) VALUES (6,'mostliked'); +INSERT INTO @views (id,viewname) VALUES (7,'mostreplies'); +INSERT INTO @views (id,viewname) VALUES (8,'afsubscriptions'); +INSERT INTO @views (id,viewname) VALUES (9,'announcements'); +INSERT INTO @views (id,viewname) VALUES (10,'unresolved'); +INSERT INTO @views (id,viewname) VALUES (11,'badgeusers'); +INSERT INTO @views (id,viewname) VALUES (12,'userbadges'); +INSERT INTO @views (id,viewname) VALUES (13,'recyclebin'); +SELECT TabId, ModuleID, ForumGroupId, ForumId, TopicId, Url,Archived,OtherId,UrlType FROM + ( + + /* this section handles topics on regular forum pages */ + + SELECT tb.TabID,m.ModuleId, g.ForumGroupId,f.ForumId,t.TopicId, + (CASE WHEN s.SettingValue <> '' THEN s.SettingValue + '/' Else '' END) + g.PrefixURL + '/' + f.PrefixURL + '/' + t.URL + '/' as URL, 0 as Archived,-1 as OtherId,0 as URLType + FROM {databaseOwner}[{objectQualifier}activeforums_Topics] as t + INNER JOIN {databaseOwner}[{objectQualifier}activeforums_ForumTopics] as ft ON ft.TopicId = t.TopicId + INNER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] as f ON f.ForumId = ft.ForumId + INNER JOIN {databaseOwner}[{objectQualifier}activeforums_Groups] as g ON g.ForumGroupId = f.ForumGroupId + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] as s ON s.ModuleId = f.ModuleId AND s.SettingName = 'URLBASE' + INNER JOIN {databaseOwner}[{objectQualifier}TabModules] as m ON m.ModuleID = f.ModuleId + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] as tb ON tb.TabId = m.TabID + WHERE tb.PortalID = @PortalId AND ISNULL(g.PrefixURL,'') <> '' AND ISNULL(f.PrefixURL,'') <> '' AND ISNULL(t.URL,'') <> '' + + UNION + + /* this section handles topics on forum viewer pages */ + + SELECT tb.TabID,tb.ModuleId, g.ForumGroupId,f.ForumId,t.TopicId, + (CASE WHEN TB.TabPath <> '' THEN TB.TabPath + '/' Else '' END) + g.PrefixURL + '/' + f.PrefixURL + '/' + t.URL + '/' as URL, 0 as Archived,-1 as OtherId,0 as URLType + FROM {databaseOwner}[{objectQualifier}activeforums_Topics] as t + INNER JOIN {databaseOwner}[{objectQualifier}activeforums_ForumTopics] as ft ON ft.TopicId = t.TopicId + INNER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] as f ON f.ForumId = ft.ForumId + INNER JOIN {databaseOwner}[{objectQualifier}activeforums_Groups] as g ON g.ForumGroupId = f.ForumGroupId + INNER JOIN ( + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(SUBSTRING(t.TabPath,3,LEN(t.TabPath)-2),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(REPLACE(t.TabName,' ','-'),'--','-') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(SUBSTRING(tu.Url,2,LEN(tu.Url)-1),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}TabUrls] tu ON tu.TabId = t.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(SUBSTRING(t.TabPath,3,LEN(t.TabPath)-2),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(REPLACE(t.TabName,' ','-'),'--','-') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(SUBSTRING(tu.Url,2,LEN(tu.Url)-1),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}TabUrls] tu ON tu.TabId = t.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0 ) TB + ON TB.ModuleId = f.ModuleId AND TB.ForumGroupId = f.ForumGroupId AND TB.ForumId = f.ForumId + WHERE tb.PortalID = @PortalId AND ISNULL(g.PrefixURL,'') <> '' AND ISNULL(f.PrefixURL,'') <> '' AND ISNULL(t.URL,'') <> '' + + UNION + + /* this section handles forums on regular forums pages */ + + SELECT tb.TabID,m.ModuleId,g.ForumGroupId,f.ForumId,-1, + (CASE WHEN s.SettingValue <> '' THEN s.SettingValue + '/' Else '' END) + g.PrefixURL + '/' + f.PrefixURL + '/' as URL, 0 as Archived,-1,0 + FROM {databaseOwner}[{objectQualifier}activeforums_Forums] as f + INNER JOIN {databaseOwner}[{objectQualifier}activeforums_Groups] as g ON g.ForumGroupId = f.ForumGroupId + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] as s ON s.ModuleId = f.ModuleId AND s.SettingName = 'URLBASE' + INNER JOIN {databaseOwner}[{objectQualifier}TabModules] as m ON m.ModuleID = f.ModuleId + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] as tb ON tb.TabId = m.TabID + WHERE tb.PortalID = @PortalId AND ISNULL(g.PrefixURL,'') <> '' AND ISNULL(f.PrefixURL,'') <> '' + + UNION + + /* this section handles forums on forum viewer pages */ + + SELECT tb.TabID,tb.ModuleId, g.ForumGroupId,f.ForumId,-1, + (CASE WHEN TB.TabPath <> '' THEN TB.TabPath + '/' Else '' END) + g.PrefixURL + '/' + f.PrefixURL + '/' as URL, 0 as Archived,-1 as OtherId,0 as URLType + FROM {databaseOwner}[{objectQualifier}activeforums_Forums] as f + INNER JOIN {databaseOwner}[{objectQualifier}activeforums_Groups] as g ON g.ForumGroupId = f.ForumGroupId + INNER JOIN ( + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(SUBSTRING(t.TabPath,3,LEN(t.TabPath)-2),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(REPLACE(t.TabName,' ','-'),'--','-') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(SUBSTRING(tu.Url,2,LEN(tu.Url)-1),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}TabUrls] tu ON tu.TabId = t.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(SUBSTRING(t.TabPath,3,LEN(t.TabPath)-2),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(REPLACE(t.TabName,' ','-'),'--','-') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(SUBSTRING(tu.Url,2,LEN(tu.Url)-1),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}TabUrls] tu ON tu.TabId = t.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0) TB + ON TB.ModuleId = f.ModuleId AND TB.ForumGroupId = f.ForumGroupId AND TB.ForumId = f.ForumId + WHERE tb.PortalID = @PortalId AND ISNULL(g.PrefixURL,'') <> '' AND ISNULL(f.PrefixURL,'') <> '' + + UNION + + /* this section handles forum groups on regular forums pages */ + + SELECT tb.TabID,m.ModuleId,g.ForumGroupId,-1,-1, + (CASE WHEN s.SettingValue <> '' THEN s.SettingValue + '/' Else '' END) + g.PrefixURL + '/' as URL, 0 as Archived,-1,0 + FROM {databaseOwner}[{objectQualifier}activeforums_Groups] as g + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] as s ON s.ModuleId = g.ModuleId AND s.SettingName = 'URLBASE' + INNER JOIN {databaseOwner}[{objectQualifier}TabModules] as m ON m.ModuleID = g.ModuleId + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] as tb ON tb.TabId = m.TabID + WHERE tb.PortalID = @PortalId AND ISNULL(g.PrefixURL,'') <> '' + + UNION + + /* this section handles forum groups on forum viewer pages */ + + SELECT tb.TabID,tb.ModuleId, g.ForumGroupId,-1,-1, + (CASE WHEN TB.TabPath <> '' THEN TB.TabPath + '/' Else '' END) + g.PrefixURL + '/' as URL, 0 as Archived,-1 as OtherId,0 as URLType + FROM {databaseOwner}[{objectQualifier}activeforums_Groups] as g + INNER JOIN ( + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(SUBSTRING(t.TabPath,3,LEN(t.TabPath)-2),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(REPLACE(t.TabName,' ','-'),'--','-') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(SUBSTRING(tu.Url,2,LEN(tu.Url)-1),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}TabUrls] tu ON tu.TabId = t.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(SUBSTRING(t.TabPath,3,LEN(t.TabPath)-2),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(REPLACE(t.TabName,' ','-'),'--','-') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(SUBSTRING(tu.Url,2,LEN(tu.Url)-1),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}TabUrls] tu ON tu.TabId = t.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0) TB + ON TB.ModuleId = g.ModuleId AND TB.ForumGroupId = g.ForumGroupId + WHERE tb.PortalID = @PortalId AND ISNULL(g.PrefixURL,'') <> '' + + UNION + SELECT tb.TabID,m.ModuleId,-1,-1,-1, + (CASE WHEN s.SettingValue <> '' THEN s.SettingValue + '/' Else '' END) as URL, 0 as Archived,-1,0 + FROM {databaseOwner}[{objectQualifier}ModuleSettings] as s + INNER JOIN {databaseOwner}[{objectQualifier}TabModules] as m ON m.ModuleID = s.ModuleId AND s.SettingName = 'URLBASE' + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] as tb ON tb.TabId = m.TabID + WHERE tb.PortalID = @PortalId AND s.SettingValue <> '' + UNION + + SELECT tb.TabID,tb.ModuleId, -1,-1,-1, + (CASE WHEN TB.TabPath <> '' THEN TB.TabPath + '/' Else '' END) as URL, 0 as Archived,-1 as OtherId,0 as URLType + FROM (SELECT t.PortalID, t.TabID, CAST(SettingValue as int) AS ModuleId, + REPLACE(SUBSTRING(t.TabPath,3,LEN(t.TabPath)-2),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms ON ms.ModuleID = m.ModuleID AND ms.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + UNION + SELECT t.PortalID, t.TabID, CAST(SettingValue as int) AS ModuleId, + REPLACE(REPLACE(t.TabName,' ','-'),'--','-') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms ON ms.ModuleID = m.ModuleID AND ms.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + UNION + SELECT t.PortalID, t.TabID, CAST(SettingValue as int) AS ModuleId, + REPLACE(SUBSTRING(tu.Url,2,LEN(tu.Url)-1),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms ON ms.ModuleID = m.ModuleID AND ms.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}TabUrls] tu ON tu.TabId = t.TabID + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0) TB + WHERE tb.PortalID = @PortalId + + UNION + + SELECT m.TabID,m.ModuleID,u.ForumGroupId,u.ForumId,u.TopicId,(CASE WHEN s.SettingValue <> '' THEN s.SettingValue + '/' Else '' END) + u.URL as URL, 1 as Archived,-1,0 + FROM {databaseOwner}[{objectQualifier}activeforums_URL] as u + INNER JOIN {databaseOwner}[{objectQualifier}activeforums_Groups] as g ON u.ForumGroupId = g.ForumGroupId + INNER JOIN {databaseOwner}[{objectQualifier}TabModules] as m ON m.ModuleID = g.ModuleId + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] as s ON s.ModuleId = g.ModuleId AND s.SettingName = 'URLBASE' + WHERE u.PortalId = @PortalId + + UNION + SELECT tb.TabID, tb.ModuleId, u.ForumGroupId,u.ForumId,u.TopicId, (CASE WHEN TB.TabPath <> '' THEN TB.TabPath + '/' Else '' END) + u.URL AS URL, 1 as Archived,-1,0 + FROM {databaseOwner}[{objectQualifier}activeforums_URL] as u + INNER JOIN {databaseOwner}[{objectQualifier}activeforums_Groups] as g ON u.ForumGroupId = g.ForumGroupId + INNER JOIN {databaseOwner}[{objectQualifier}TabModules] as m ON m.ModuleID = g.ModuleId + INNER JOIN ( + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(SUBSTRING(t.TabPath,3,LEN(t.TabPath)-2),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(REPLACE(t.TabName,' ','-'),'--','-') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(SUBSTRING(tu.Url,2,LEN(tu.Url)-1),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}TabUrls] tu ON tu.TabId = t.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(SUBSTRING(t.TabPath,3,LEN(t.TabPath)-2),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(REPLACE(t.TabName,' ','-'),'--','-') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(SUBSTRING(tu.Url,2,LEN(tu.Url)-1),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}TabUrls] tu ON tu.TabId = t.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0 ) TB + ON TB.ModuleId = g.ModuleId AND TB.ForumGroupId = u.ForumGroupId AND TB.ForumId = u.ForumId + WHERE u.PortalId = @PortalId + + UNION + + /* this section handles other url types on regular module page */ + + SELECT TabId, ModuleId,-1 as ForumGroupId,-1 as ForumId,-1 as TopicId, + (CASE WHEN UrlBase <> '' THEN UrlBase + '/' Else '' END) + UrlOther + '/' + v.viewname + '/' as URL,0 as Archived,v.id,1 from ( + SELECT m.TabId, ss.ModuleId, SettingValue,SettingName FROM {databaseOwner}[{objectQualifier}ModuleSettings] as ss + INNER JOIN {databaseOwner}[{objectQualifier}TabModules] as m ON m.ModuleID = ss.ModuleId + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] as tb ON tb.TabId = m.TabID + WHERE (SettingName = 'URLBASE' OR SettingName = 'URLOTHER') AND tb.PortalID = @PortalId + ) as s + PIVOT (MAX(SettingValue) for SettingName in (urlbase,UrlOther)) as pu,@views as v + + UNION + + /* this section handles other url types on viewer module page */ + + SELECT TabId, ModuleId,-1 as ForumGroupId,-1 as ForumId,-1 as TopicId, + (CASE WHEN UrlBase <> '' THEN UrlBase + '/' Else '' END) + UrlOther + '/' + v.viewname + '/' as URL,0 as Archived,v.id,1 from ( + SELECT m.TabId, ss.ModuleId, SettingValue,SettingName FROM {databaseOwner}[{objectQualifier}ModuleSettings] as ss + INNER JOIN {databaseOwner}[{objectQualifier}TabModules] as m ON m.ModuleID = ss.ModuleId + INNER JOIN ( + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(SUBSTRING(t.TabPath,3,LEN(t.TabPath)-2),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(REPLACE(t.TabName,' ','-'),'--','-') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(SUBSTRING(tu.Url,2,LEN(tu.Url)-1),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}TabUrls] tu ON tu.TabId = t.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(SUBSTRING(t.TabPath,3,LEN(t.TabPath)-2),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(REPLACE(t.TabName,' ','-'),'--','-') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(SUBSTRING(tu.Url,2,LEN(tu.Url)-1),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}TabUrls] tu ON tu.TabId = t.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0 ) TB + ON TB.ModuleId = m.ModuleId + WHERE (SettingName = 'URLBASE' OR SettingName = 'URLOTHER') AND tb.PortalID = @PortalId + ) as s + PIVOT (MAX(SettingValue) for SettingName in (urlbase,UrlOther)) as pu,@views as v + + UNION + + /* this section handles categories on regular module page */ + + SELECT TabId, pu.ModuleId,-1 as ForumGroupId,-1 as ForumId,-1 as TopicId, + (CASE WHEN UrlBase <> '' THEN UrlBase + '/' Else '' END) + URLCATS + '/' + REPLACE(LOWER(t.TagName),' ','-') + '/' as URL,0 as Archived,t.TagId,2 from ( + SELECT m.TabId, ss.ModuleId, SettingValue,SettingName FROM {databaseOwner}[{objectQualifier}ModuleSettings] as ss + INNER JOIN {databaseOwner}[{objectQualifier}TabModules] as m ON m.ModuleID = ss.ModuleId + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] as tb ON tb.TabId = m.TabID + WHERE (SettingName = 'URLBASE' OR SettingName = 'URLCATS') AND tb.PortalID = @PortalId + ) as s + PIVOT (MAX(SettingValue) for SettingName in (urlbase,URLCATS)) as pu + INNER JOIN {databaseOwner}[{objectQualifier}activeforums_Tags] as t ON t.ModuleId = pu.ModuleId + + UNION + + /* this section handles categories on viewer module pages */ + + SELECT TabId, pu.ModuleId,-1 as ForumGroupId,-1 as ForumId,-1 as TopicId, + (CASE WHEN TabPath <> '' THEN TabPath + '/' Else '' END) + URLCATS + '/' + REPLACE(LOWER(t.TagName),' ','-') + '/' as URL,0 as Archived,t.TagId,2 from ( + SELECT m.TabId, ss.ModuleId, SettingValue,SettingName,tb.TabPath FROM {databaseOwner}[{objectQualifier}ModuleSettings] as ss + INNER JOIN {databaseOwner}[{objectQualifier}TabModules] as m ON m.ModuleID = ss.ModuleId + INNER JOIN ( + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(SUBSTRING(t.TabPath,3,LEN(t.TabPath)-2),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(REPLACE(t.TabName,' ','-'),'--','-') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(SUBSTRING(tu.Url,2,LEN(tu.Url)-1),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}TabUrls] tu ON tu.TabId = t.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(SUBSTRING(t.TabPath,3,LEN(t.TabPath)-2),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(REPLACE(t.TabName,' ','-'),'--','-') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(SUBSTRING(tu.Url,2,LEN(tu.Url)-1),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}TabUrls] tu ON tu.TabId = t.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0 ) TB + ON TB.ModuleId = m.ModuleId + WHERE (SettingName = 'URLBASE' OR SettingName = 'URLCATS') AND tb.PortalID = @PortalId + ) as s + PIVOT (MAX(SettingValue) for SettingName in (urlbase,URLCATS)) as pu + INNER JOIN {databaseOwner}[{objectQualifier}activeforums_Tags] as t ON t.ModuleId = pu.ModuleId + + UNION + + /* this section handles tags on forums module pages */ + + SELECT TabId, pu.ModuleId,-1 as ForumGroupId,-1 as ForumId,-1 as TopicId, + (CASE WHEN UrlBase <> '' THEN UrlBase + '/' Else '' END) + URLTAGS + '/' + REPLACE(LOWER(t.TagName),' ','-') + '/' as URL,0 as Archived,t.TagId,3 from ( + SELECT m.TabId, ss.ModuleId, SettingValue,SettingName FROM {databaseOwner}[{objectQualifier}ModuleSettings] as ss + INNER JOIN {databaseOwner}[{objectQualifier}TabModules] as m ON m.ModuleID = ss.ModuleId + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] as tb ON tb.TabId = m.TabID + WHERE (SettingName = 'URLBASE' OR SettingName = 'URLTAGS') AND tb.PortalID = @PortalId + ) as s + PIVOT (MAX(SettingValue) for SettingName in (urlbase,URLTAGS)) as pu + INNER JOIN {databaseOwner}[{objectQualifier}activeforums_Tags] as t ON t.ModuleId = pu.ModuleId + + UNION + + /* this section handles tags on viewer module pages */ + + SELECT TabId, pu.ModuleId,-1 as ForumGroupId,-1 as ForumId,-1 as TopicId, + (CASE WHEN TabPath <> '' THEN TabPath + '/' Else '' END) + URLTAGS + '/' + REPLACE(LOWER(t.TagName),' ','-') + '/' as URL,0 as Archived,t.TagId,3 from ( + SELECT m.TabId, ss.ModuleId, SettingValue,SettingName, TB.TabPath FROM {databaseOwner}[{objectQualifier}ModuleSettings] as ss + INNER JOIN {databaseOwner}[{objectQualifier}TabModules] as m ON m.ModuleID = ss.ModuleId + INNER JOIN ( + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(SUBSTRING(t.TabPath,3,LEN(t.TabPath)-2),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(REPLACE(t.TabName,' ','-'),'--','-') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(SUBSTRING(tu.Url,2,LEN(tu.Url)-1),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}TabUrls] tu ON tu.TabId = t.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(SUBSTRING(t.TabPath,3,LEN(t.TabPath)-2),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(REPLACE(t.TabName,' ','-'),'--','-') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(SUBSTRING(tu.Url,2,LEN(tu.Url)-1),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}TabUrls] tu ON tu.TabId = t.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0 ) TB + ON TB.ModuleId = m.ModuleId + WHERE (SettingName = 'URLBASE' OR SettingName = 'URLTAGS') AND tb.PortalID = @PortalId + ) as s + PIVOT (MAX(SettingValue) for SettingName in (urlbase,URLTAGS)) as pu + INNER JOIN {databaseOwner}[{objectQualifier}activeforums_Tags] as t ON t.ModuleId = pu.ModuleId + + UNION + + /* this section handles likes on forums module pages */ + + SELECT DISTINCT tb.TabID,m.ModuleId, g.ForumGroupId,f.ForumId ,COALESCE(t.TopicId, r.TopicId) AS TopicId, + (CASE WHEN s1.SettingValue <> '' THEN s1.SettingValue + '/' Else '' END) + g.PrefixURL + '/' + f.PrefixURL + '/' + ISNULL(ISNULL(rt.URL,t.URL),'') + '/' + COALESCE('likes',s2.SettingValue) + '/' + LTRIM(STR(c.ContentId)) + '/' as URL, 0 as Archived,c.ContentId AS OtherId,4 as URLType + FROM {databaseOwner}[{objectQualifier}activeforums_Content] as c + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Topics] as t ON t.ContentId = c.ContentId + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Replies] as r ON r.ContentId = c.ContentId + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Topics] as rt ON rt.TopicId = r.TopicId + INNER JOIN {databaseOwner}[{objectQualifier}activeforums_ForumTopics] as ft ON ft.TopicId = COALESCE(t.TopicId, r.TopicId) + INNER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] as f ON f.ForumId = ft.ForumId + INNER JOIN {databaseOwner}[{objectQualifier}activeforums_Groups] as g ON g.ForumGroupId = f.ForumGroupId + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] as s1 ON s1.ModuleId = f.ModuleId AND s1.SettingName = 'URLBASE' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] as s2 ON s2.ModuleId = f.ModuleId AND s2.SettingName = 'URLLIKES' + INNER JOIN {databaseOwner}[{objectQualifier}TabModules] as m ON m.ModuleID = f.ModuleId + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] as tb ON tb.TabId = m.TabID + WHERE c.IsDeleted = 0 AND tb.PortalID = @PortalId AND ISNULL(ISNULL(rt.URL,t.URL),'') <> '' AND ISNULL(f.PrefixURL,'') <> '' + + UNION + + /* this section handles likes on viewer module pages */ + + SELECT DISTINCT tb.TabID,f.ModuleId, f.ForumGroupId,f.ForumId ,COALESCE(t.TopicId, r.TopicId) AS TopicId, + (CASE WHEN TB.TabPath <> '' THEN TB.TabPath + '/' Else '' END) + g.PrefixURL + '/' + f.PrefixURL + '/' + ISNULL(ISNULL(rt.URL,t.URL),'') + '/' + COALESCE('likes',s2.SettingValue) + '/' + LTRIM(STR(c.ContentId)) + '/' as URL, 0 as Archived,c.ContentId AS OtherId,4 as URLType + FROM {databaseOwner}[{objectQualifier}activeforums_Content] as c + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Topics] as t ON t.ContentId = c.ContentId + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Replies] as r ON r.ContentId = c.ContentId + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Topics] as rt ON rt.TopicId = r.TopicId + INNER JOIN {databaseOwner}[{objectQualifier}activeforums_ForumTopics] as ft ON ft.TopicId = COALESCE(t.TopicId, r.TopicId) + INNER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] as f ON f.ForumId = ft.ForumId + INNER JOIN {databaseOwner}[{objectQualifier}activeforums_Groups] as g ON g.ForumGroupId = f.ForumGroupId + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] as s1 ON s1.ModuleId = f.ModuleId AND s1.SettingName = 'URLBASE' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] as s2 ON s2.ModuleId = f.ModuleId AND s2.SettingName = 'URLLIKES' + INNER JOIN {databaseOwner}[{objectQualifier}TabModules] as m ON m.ModuleID = f.ModuleId + INNER JOIN ( + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(SUBSTRING(t.TabPath,3,LEN(t.TabPath)-2),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(REPLACE(t.TabName,' ','-'),'--','-') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, COALESCE(f.ForumGroupId, -1) AS ForumGroupId, CAST(ms3.SettingValue as int) AS ForumId, + REPLACE(SUBSTRING(tu.Url,2,LEN(tu.Url)-1),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}TabUrls] tu ON tu.TabId = t.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' AND ms2.SettingValue = 'TOPICS' + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}activeforums_Forums] f ON f.ForumId = CAST(ms3.SettingValue as int) + WHERE m.DefinitionName = 'Active Forums Viewer' AND t.IsDeleted = 0 and m.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(SUBSTRING(t.TabPath,3,LEN(t.TabPath)-2),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(REPLACE(t.TabName,' ','-'),'--','-') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0 + + UNION + SELECT t.PortalID, t.TabID, CAST(ms1.SettingValue as int) AS ModuleId, CAST(ms3.SettingValue as int) ForumGroupId, -1 AS ForumId, + REPLACE(SUBSTRING(tu.Url,2,LEN(tu.Url)-1),'//','/') AS TabPath + FROM {databaseOwner}[{objectQualifier}vw_Modules] m + INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = m.TabID + LEFT OUTER JOIN {databaseOwner}[{objectQualifier}TabUrls] tu ON tu.TabId = t.TabID + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms1 ON ms1.ModuleID = m.ModuleID AND ms1.SettingName = 'AFForumModuleID' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms2 ON ms2.ModuleID = m.ModuleID AND ms2.SettingName = 'AFViewType' AND ms2.SettingValue = 'AFGROUP' + INNER JOIN {databaseOwner}[{objectQualifier}ModuleSettings] ms3 ON ms3.ModuleID = m.ModuleID AND ms3.SettingName = 'AFForumGroupID' + WHERE m.DefinitionName = 'Active Forums Viewer' and m.IsDeleted = 0 AND t.IsDeleted = 0 ) TB + ON TB.ModuleId = g.ModuleId AND TB.ForumGroupId = f.ForumGroupId AND TB.ForumId = f.ForumId + WHERE c.IsDeleted = 0 AND tb.PortalID = @PortalId AND ISNULL(ISNULL(rt.URL,t.URL),'') <> '' AND ISNULL(f.PrefixURL,'') <> '' + ) as urls + WHERE LOWER(urls.URL) = @URL +GO + +/* issue 1480 - end - badges */ + +/* --------------------- */ + +/* issue 1487 - begin - add BadgeId to activeforums_ProcessQueue */ + +IF NOT EXISTS(SELECT * FROM SYS.COLUMNS WHERE Name = N'BadgeId' and Object_ID = Object_ID(N'{databaseOwner}[{objectQualifier}activeforums_ProcessQueue]')) +BEGIN + ALTER TABLE {databaseOwner}[{objectQualifier}activeforums_ProcessQueue] ADD + [BadgeId] [int] NOT NULL CONSTRAINT [DF_{objectQualifier}activeforums_ProcessQueue_BadgeId] DEFAULT(-1) +END +GO + +/* issue 1487 - end - add BadgeId to activeforums_ProcessQueue */ +/* --------------------- */ + + + +/* issue 1483 - begin - add badge UI to control panel */ +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Badges_List]') AND type in (N'P', N'PC')) +DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Badges_List] +GO +CREATE PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Badges_List] + @ModuleId int +AS +BEGIN + SELECT Count(*) FROM {databaseOwner}{objectQualifier}activeforums_Badges WHERE ModuleId = @ModuleId +END +BEGIN + SELECT *, '' AS ImageUrl, '' AS BadgeMetricEnumName FROM {databaseOwner}{objectQualifier}activeforums_Badges WHERE ModuleId = @ModuleId ORDER BY SortOrder +END +GO +/* issue 1483 - end - add badge UI to control panel */ +/* --------------------- */ + + +/* issue 1484 start -- create scheduler entry for badge award queue */ + +IF NOT EXISTS (Select * From {databaseOwner}{objectQualifier}Schedule WHERE TypeFullName = 'DotNetNuke.Modules.ActiveForums.Services.Badges.BadgeAwardQueue, DotNetNuke.Modules.ActiveForums') + INSERT INTO {databaseOwner}{objectQualifier}Schedule (TypeFullName,TimeLapse,TimeLapseMeasurement,RetryTimeLapse,RetryTimeLapseMeasurement,RetainHistoryNum,AttachToEvent,CatchUpEnabled,Enabled,ObjectDependencies,Servers,FriendlyName) + VALUES('DotNetNuke.Modules.ActiveForums.Services.Badges.BadgeAwardQueue, DotNetNuke.Modules.ActiveForums',1,'d',1,'d',100,'',1,1,'','','DNN Community Forums Badge Award Queue') + +/* issue 1484 end -- create scheduler entry for badge award queue */ + +/* issue 1535 - start -- add DateCreated to activeforums_Likes and set default for existing records to created date from content; set default for future records to GETUTCDATE() */ + +DECLARE @addDateCreated bit = 0 +SET @addDateCreated = (SELECT COUNT(*) FROM SYS.COLUMNS WHERE Name = N'DateCreated' and Object_ID = Object_ID(N'{databaseOwner}[{objectQualifier}activeforums_Likes]')) + +/* issue 1535 - start -- add DateCreated to activeforums_Likes */ +IF @addDateCreated = 0 +BEGIN + ALTER TABLE {databaseOwner}[{objectQualifier}activeforums_Likes] ADD DateCreated datetime NULL +END +GO +DECLARE @addDateCreated bit = 0 +SET @addDateCreated = (SELECT COUNT(*) FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[DF_{objectQualifier}activeforums_Likes_DateCreated]') AND type = 'D') +IF @addDateCreated = 0 +BEGIN + UPDATE l SET DateCreated = c.DateCreated + FROM {databaseOwner}[{objectQualifier}activeforums_Likes] l + INNER JOIN {databaseOwner}[{objectQualifier}activeforums_Content] c ON c.ContentId = l.PostId +END +IF @addDateCreated = 0 +BEGIN + ALTER TABLE {databaseOwner}[{objectQualifier}activeforums_Likes] ADD CONSTRAINT [DF_{objectQualifier}activeforums_Likes_DateCreated] DEFAULT (GETUTCDATE()) FOR [DateCreated] +END +IF @addDateCreated = 0 +BEGIN + ALTER TABLE {databaseOwner}[{objectQualifier}activeforums_Likes] + ALTER COLUMN [DateCreated] [datetime] NOT NULL +END +GO +/* issue 1535 - end -- add DateCreated to activeforums_Likes */ + +/* --------------------- */ \ No newline at end of file diff --git a/Dnn.CommunityForums/sql/Uninstall.SqlDataProvider b/Dnn.CommunityForums/sql/Uninstall.SqlDataProvider index 3d8f14183..d894b9b6e 100644 --- a/Dnn.CommunityForums/sql/Uninstall.SqlDataProvider +++ b/Dnn.CommunityForums/sql/Uninstall.SqlDataProvider @@ -772,16 +772,21 @@ GO IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Topics]') AND type in (N'U')) DROP TABLE {databaseOwner}[{objectQualifier}activeforums_Topics] GO +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_UserBadges]') AND type in (N'U')) +DROP TABLE {databaseOwner}[{objectQualifier}activeforums_UserBadges] +GO IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_UserProfiles]') AND type in (N'U')) DROP TABLE {databaseOwner}[{objectQualifier}activeforums_UserProfiles] GO +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Badges]') AND type in (N'U')) +DROP TABLE {databaseOwner}[{objectQualifier}activeforums_Badges] +GO IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Queue]') AND type in (N'U')) DROP TABLE {databaseOwner}[{objectQualifier}activeforums_Queue] GO IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Content]') AND type in (N'U')) DROP TABLE {databaseOwner}[{objectQualifier}activeforums_Content] GO - IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Security]') AND type in (N'U')) DROP TABLE {databaseOwner}[{objectQualifier}activeforums_Security] GO @@ -1014,3 +1019,13 @@ IF EXISTS (Select * From {databaseOwner}{objectQualifier}Schedule WHERE TypeFull GO /* end 09.01.00 */ + +/* begin 09.02.00 */ +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Badges_List]') AND type in (N'P', N'PC')) + DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Badges_List] +GO +IF EXISTS (Select * From {databaseOwner}{objectQualifier}Schedule WHERE TypeFullName = 'DotNetNuke.Modules.ActiveForums.Services.Badges.BadgeAwardQueue, DotNetNuke.Modules.ActiveForums') + DELETE FROM {databaseOwner}{objectQualifier}Schedule WHERE TypeFullName = 'DotNetNuke.Modules.ActiveForums.Services.Badges.BadgeAwardQueue, DotNetNuke.Modules.ActiveForums' +GO + +/* end 09.02.00 */ \ No newline at end of file diff --git a/Dnn.CommunityForums/themes/community-bootstrap/templates/ProfileInfo.ascx b/Dnn.CommunityForums/themes/community-bootstrap/templates/ProfileInfo.ascx index 3c3bebe08..5f4a96ebf 100644 --- a/Dnn.CommunityForums/themes/community-bootstrap/templates/ProfileInfo.ascx +++ b/Dnn.CommunityForums/themes/community-bootstrap/templates/ProfileInfo.ascx @@ -28,5 +28,8 @@
    [FORUMAUTHOR:RANKDISPLAY]
    +
    + [FORUMAUTHOR:BADGES:10] +
    \ No newline at end of file diff --git a/Dnn.CommunityForums/themes/community-default/templates/ProfileInfo.ascx b/Dnn.CommunityForums/themes/community-default/templates/ProfileInfo.ascx index 388327743..a97043adb 100644 --- a/Dnn.CommunityForums/themes/community-default/templates/ProfileInfo.ascx +++ b/Dnn.CommunityForums/themes/community-default/templates/ProfileInfo.ascx @@ -28,5 +28,8 @@
    [FORUMAUTHOR:RANKDISPLAY]
    +
    + [FORUMAUTHOR:BADGES:10] +
    \ No newline at end of file diff --git a/DnnCommunityForums.sln b/DnnCommunityForums.sln index 690a35bb7..c97fe3a63 100644 --- a/DnnCommunityForums.sln +++ b/DnnCommunityForums.sln @@ -18,11 +18,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DnnCommunityForums", "Dnn.C EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DnnCommunityForumsTests", "Dnn.CommunityForumsTests\DnnCommunityForumsTests.csproj", "{B268075A-B369-4B84-8AB9-D338AD41C6D6}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8EC462FD-D22E-90A8-E5CE-7E832BA40C5D}" - ProjectSection(SolutionItems) = preProject - .github\copilot-instructions.md = .github\copilot-instructions.md - EndProjectSection -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU From 400c9baefa9e8985e5cbd9af554d11b895a78559 Mon Sep 17 00:00:00 2001 From: John Henley Date: Fri, 10 Oct 2025 20:00:03 +0000 Subject: [PATCH 12/20] TASK: Remove colon ":" from SettingsKey --- .../Controllers/ForumController.cs | 6 +- .../Controllers/ForumGroupController.cs | 6 +- .../SqlDataProvider/SqlDataProvider.cs | 2 +- Dnn.CommunityForums/class/ForumsConfig.cs | 8 +- Dnn.CommunityForums/class/ModuleSettings.cs | 2 +- .../admin_manageforums_forumeditor.ascx.cs | 6 +- .../sql/09.02.00.SqlDataProvider | 108 +++++++++++++++++- 7 files changed, 122 insertions(+), 16 deletions(-) diff --git a/Dnn.CommunityForums/Controllers/ForumController.cs b/Dnn.CommunityForums/Controllers/ForumController.cs index a86eeb6d6..420cf00a2 100644 --- a/Dnn.CommunityForums/Controllers/ForumController.cs +++ b/Dnn.CommunityForums/Controllers/ForumController.cs @@ -260,14 +260,14 @@ public int Forums_Save(int portalId, DotNetNuke.Modules.ActiveForums.Entities.Fo copyDownGroupSettings = true; } - forumInfo.ForumSettingsKey = useGroupFeatures ? (forumGroupInfo != null ? forumGroupInfo.GroupSettingsKey : string.Empty) : (forumInfo.ForumID > 0 ? $"F:{forumInfo.ForumID}" : string.Empty); + forumInfo.ForumSettingsKey = useGroupFeatures ? (forumGroupInfo != null ? forumGroupInfo.GroupSettingsKey : string.Empty) : (forumInfo.ForumID > 0 ? $"F{forumInfo.ForumID}" : string.Empty); // TODO: When this method is updated to use DAL2 for update, uncomment Cacheable attribute on ForumInfo var forumId = Convert.ToInt32(DotNetNuke.Modules.ActiveForums.DataProvider.Instance().Forum_Save(portalId, forumInfo.ForumID, forumInfo.ModuleId, forumInfo.ForumGroupId, forumInfo.ParentForumId, forumInfo.ForumName, forumInfo.ForumDesc, forumInfo.SortOrder, forumInfo.Active, forumInfo.Hidden, forumInfo.ForumSettingsKey, forumInfo.PermissionsId, forumInfo.PrefixURL, forumInfo.SocialGroupId, forumInfo.HasProperties)); forumInfo = this.GetById(forumId, forumInfo.ModuleId); if (!useGroupFeatures && string.IsNullOrEmpty(forumInfo.ForumSettingsKey)) { - forumInfo.ForumSettingsKey = $"F:{forumId}"; + forumInfo.ForumSettingsKey = $"F{forumId}"; this.Update(forumInfo); } @@ -287,7 +287,7 @@ public int Forums_Save(int portalId, DotNetNuke.Modules.ActiveForums.Entities.Fo // if now inheriting group settings, remove any previously-defined forum settings if (forumInfo.InheritSettings) { - new DotNetNuke.Modules.ActiveForums.Controllers.SettingsController().DeleteForModuleIdSettingsKey(forumInfo.ModuleId, $"F:{forumInfo.ForumID}"); + new DotNetNuke.Modules.ActiveForums.Controllers.SettingsController().DeleteForModuleIdSettingsKey(forumInfo.ModuleId, $"F{forumInfo.ForumID}"); } // Clear the caches diff --git a/Dnn.CommunityForums/Controllers/ForumGroupController.cs b/Dnn.CommunityForums/Controllers/ForumGroupController.cs index 438d49a82..73b673968 100644 --- a/Dnn.CommunityForums/Controllers/ForumGroupController.cs +++ b/Dnn.CommunityForums/Controllers/ForumGroupController.cs @@ -120,7 +120,7 @@ public int Groups_Save(int portalId, DotNetNuke.Modules.ActiveForums.Entities.Fo if (!isNew || forumGroupInfo.InheritSettings) { // reset any forum settings keys previously mapped to the module default to map to new settings key - forumGroupInfo.GroupSettingsKey = $"G:{forumGroupInfo.ForumGroupId}"; + forumGroupInfo.GroupSettingsKey = $"G{forumGroupInfo.ForumGroupId}"; foreach (var forum in fc.GetForums(moduleId: forumGroupInfo.ModuleId).Where(f => f.ForumGroupId == forumGroupInfo.ForumGroupId && f.ForumSettingsKey == SettingsBase.GetModuleSettings(forumGroupInfo.ModuleId).DefaultSettingsKey)) { forum.ForumSettingsKey = forumGroupInfo.GroupSettingsKey; @@ -135,7 +135,7 @@ public int Groups_Save(int portalId, DotNetNuke.Modules.ActiveForums.Entities.Fo forumGroupInfo = this.GetById(forumGroupInfo.ForumGroupId, forumGroupInfo.ModuleId); if (string.IsNullOrEmpty(forumGroupInfo.GroupSettingsKey)) { - forumGroupInfo.GroupSettingsKey = $"G:{forumGroupInfo.ForumGroupId}"; + forumGroupInfo.GroupSettingsKey = $"G{forumGroupInfo.ForumGroupId}"; this.Update(forumGroupInfo); } @@ -155,7 +155,7 @@ public int Groups_Save(int portalId, DotNetNuke.Modules.ActiveForums.Entities.Fo /* if now using default module settings, remove group settings */ if (useDefaultFeatures) { - new DotNetNuke.Modules.ActiveForums.Controllers.SettingsController().DeleteForModuleIdSettingsKey(forumGroupInfo.ModuleId, $"G:{forumGroupInfo.ForumGroupId}"); + new DotNetNuke.Modules.ActiveForums.Controllers.SettingsController().DeleteForModuleIdSettingsKey(forumGroupInfo.ModuleId, $"G{forumGroupInfo.ForumGroupId}"); } ClearSettingsCache(forumGroupInfo.ModuleId); diff --git a/Dnn.CommunityForums/Providers/DataProviders/SqlDataProvider/SqlDataProvider.cs b/Dnn.CommunityForums/Providers/DataProviders/SqlDataProvider/SqlDataProvider.cs index 9bd2c9eea..fad1d9319 100644 --- a/Dnn.CommunityForums/Providers/DataProviders/SqlDataProvider/SqlDataProvider.cs +++ b/Dnn.CommunityForums/Providers/DataProviders/SqlDataProvider/SqlDataProvider.cs @@ -243,7 +243,7 @@ public override void Groups_Move(int ModuleId, int ForumGroupId, int SortDirecti [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. No longer used.")] public override int Groups_Save(int PortalId, int ModuleId, int ForumGroupId, string GroupName, int SortOrder, bool Active, bool Hidden, int PermissionsId, string PrefixURL) { - return Convert.ToInt32(SqlHelper.ExecuteScalar(this.ConnectionString, this.DatabaseOwner + this.ObjectQualifier + "activeforums_Groups_Save", PortalId, ModuleId, ForumGroupId, GroupName, SortOrder, Active, Hidden, PermissionsId, PrefixURL, $"G:{ForumGroupId}")); + return Convert.ToInt32(SqlHelper.ExecuteScalar(this.ConnectionString, this.DatabaseOwner + this.ObjectQualifier + "activeforums_Groups_Save", PortalId, ModuleId, ForumGroupId, GroupName, SortOrder, Active, Hidden, PermissionsId, PrefixURL, $"G{ForumGroupId}")); } public override int Groups_Save(int PortalId, int ModuleId, int ForumGroupId, string GroupName, int SortOrder, bool Active, bool Hidden, int PermissionsId, string PrefixURL, string GroupSettingsKey) diff --git a/Dnn.CommunityForums/class/ForumsConfig.cs b/Dnn.CommunityForums/class/ForumsConfig.cs index 2d4016dd7..493e0bc6f 100644 --- a/Dnn.CommunityForums/class/ForumsConfig.cs +++ b/Dnn.CommunityForums/class/ForumsConfig.cs @@ -179,7 +179,7 @@ private void LoadDefaultForums(int portalId, int moduleId) Active = xNodeList[i].Attributes["active"].Value == "1", Hidden = xNodeList[i].Attributes["hidden"].Value == "1", SortOrder = i, - GroupSettingsKey = $"M:{moduleId}", + GroupSettingsKey = $"M{moduleId}", PermissionsId = SettingsBase.GetModuleSettings(moduleId).DefaultPermissionId, }; var gc = new DotNetNuke.Modules.ActiveForums.Controllers.ForumGroupController(); @@ -204,7 +204,7 @@ private void LoadDefaultForums(int portalId, int moduleId) Active = cNodes[c].Attributes["active"].Value == "1", Hidden = cNodes[c].Attributes["hidden"].Value == "1", SortOrder = c, - ForumSettingsKey = $"G:{groupId}", + ForumSettingsKey = $"G{groupId}", PermissionsId = SettingsBase.GetModuleSettings(moduleId).DefaultPermissionId, }; new DotNetNuke.Modules.ActiveForums.Controllers.ForumController().Forums_Save(portalId, fi, true, true, true); @@ -572,7 +572,7 @@ internal static void Upgrade_EmailNotificationSubjectTokens_080200() } templateInfo.Subject = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyEmailNotificationTokenSynonyms(new StringBuilder(templateInfo.Subject), portalSettings, portalSettings.DefaultLanguage).ToString(); - DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(module.ModuleID, $"M:{module.ModuleID}", ForumSettingKeys.EmailNotificationSubjectTemplate, templateInfo.Subject); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(module.ModuleID, $"M{module.ModuleID}", ForumSettingKeys.EmailNotificationSubjectTemplate, templateInfo.Subject); DotNetNuke.Modules.ActiveForums.DataCache.ClearAllCache(module.ModuleID); } catch (Exception ex) @@ -669,7 +669,7 @@ internal static void Install_Upgrade_ForumDefaultSettingsAndSecurity(int portalI var permissions = new DotNetNuke.Modules.ActiveForums.Controllers.PermissionController().CreateDefaultPermissions(portalSettings, moduleId); DotNetNuke.Entities.Modules.ModuleController.Instance.UpdateModuleSetting(moduleId, SettingKeys.DefaultPermissionId, permissions.PermissionsId.ToString()); - string sKey = $"M:{moduleId}"; + string sKey = $"M{moduleId}"; DotNetNuke.Entities.Modules.ModuleController.Instance.UpdateModuleSetting(moduleId, SettingKeys.DefaultSettingsKey, sKey); if (string.IsNullOrEmpty(SettingsBase.GetModuleSettings(moduleId).DefaultFeatureSettings.EmailNotificationSubjectTemplate)) { diff --git a/Dnn.CommunityForums/class/ModuleSettings.cs b/Dnn.CommunityForums/class/ModuleSettings.cs index 99f801d17..c265aee64 100644 --- a/Dnn.CommunityForums/class/ModuleSettings.cs +++ b/Dnn.CommunityForums/class/ModuleSettings.cs @@ -183,7 +183,7 @@ public ProfileVisibilities ProfileVisibility public int DefaultPermissionId => this.MainSettings.GetInt(SettingKeys.DefaultPermissionId); - public string DefaultSettingsKey => this.MainSettings.GetString(SettingKeys.DefaultSettingsKey) ?? $"M:{this.ModuleId}"; + public string DefaultSettingsKey => this.MainSettings.GetString(SettingKeys.DefaultSettingsKey) ?? $"M{this.ModuleId}"; public FeatureSettings DefaultFeatureSettings { diff --git a/Dnn.CommunityForums/controls/admin_manageforums_forumeditor.ascx.cs b/Dnn.CommunityForums/controls/admin_manageforums_forumeditor.ascx.cs index 04ac77ee0..29a845e4f 100644 --- a/Dnn.CommunityForums/controls/admin_manageforums_forumeditor.ascx.cs +++ b/Dnn.CommunityForums/controls/admin_manageforums_forumeditor.ascx.cs @@ -438,7 +438,7 @@ private void cbEditorAction_Callback(object sender, Controls.CallBackEventArgs e case "modulesettingssave": { - var sKey = $"M:{this.ModuleId}"; + var sKey = $"M{this.ModuleId}"; this.SaveSettings(sKey, e.Parameters); this.hidEditorResult.Value = this.ModuleId.ToString(); @@ -449,7 +449,7 @@ private void cbEditorAction_Callback(object sender, Controls.CallBackEventArgs e case "forumsettingssave": { var forumId = Utilities.SafeConvertInt(e.Parameters[1]); - var sKey = $"F:{forumId}"; + var sKey = $"F{forumId}"; this.SaveSettings(sKey, e.Parameters); this.hidEditorResult.Value = forumId.ToString(); @@ -460,7 +460,7 @@ private void cbEditorAction_Callback(object sender, Controls.CallBackEventArgs e case "groupsettingssave": { var groupId = Utilities.SafeConvertInt(e.Parameters[1]); - var sKey = $"G:{groupId}"; + var sKey = $"G{groupId}"; this.SaveSettings(sKey, e.Parameters); this.hidEditorResult.Value = groupId.ToString(); diff --git a/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider b/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider index 097f38057..1e3ac69df 100644 --- a/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider +++ b/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider @@ -2257,4 +2257,110 @@ END GO /* issue 1535 - end -- add DateCreated to activeforums_Likes */ -/* --------------------- */ \ No newline at end of file +/* --------------------- */ + +/* issue 1547 - begin - remove colon from settings keys */ + +UPDATE {databaseOwner}[{objectQualifier}activeforums_Forums] SET ForumSettingsKey = REPLACE(ForumSettingsKey, ':', '') +GO + +UPDATE {databaseOwner}[{objectQualifier}activeforums_Groups] SET GroupSettingsKey = REPLACE(GroupSettingsKey, ':', '') +GO + +UPDATE ms +SET SettingValue = REPLACE(SettingValue, ':', '') +FROM {databaseOwner}[{objectQualifier}ModuleSettings] ms +INNER JOIN {databaseOwner}{objectQualifier}Modules] m +ON m.ModuleID = ms.ModuleID +INNER JOIN {databaseOwner}{objectQualifier}ModuleDefinitions] md +ON md.ModuleDefID = m.ModuleDefID +WHERE md.DefinitionName = 'DNN Community Forums' +AND ms.SettingName = 'DEFAULTSETTINGSKEY' +GO + +UPDATE {databaseOwner}[{objectQualifier}activeforums_Settings] SET Settings = REPLACE(Settings, ':', '') +GO + +/* remove any orphaned settings */ + +DELETE s +FROM {databaseOwner}[{objectQualifier}activeforums_Settings] s +LEFT OUTER JOIN +( +SELECT +DISTINCT Settings FROM +( +SELECT ForumSettingsKey AS Settings FROM {databaseOwner}[{objectQualifier}activeforums_Forums] +UNION +SELECT GroupSettingsKey AS Settings FROM {databaseOwner}[{objectQualifier}activeforums_Groups] +UNION +SELECT SettingValue AS Settings +FROM {databaseOwner}[{objectQualifier}ModuleSettings] ms +INNER JOIN {databaseOwner}[{objectQualifier}Modules] m +ON m.ModuleID = ms.ModuleID +INNER JOIN {databaseOwner}[{objectQualifier}ModuleDefinitions] md +ON md.ModuleDefID = m.ModuleDefID +WHERE md.DefinitionName = 'DNN Community Forums' +AND ms.SettingName = 'DEFAULTSETTINGSKEY' +) x +) used +ON s.Settings = used.Settings +WHERE used.Settings IS NULL +GO + +/* activeforums_Groups_Save --remove colon from settings keys */ +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Groups_Save]') AND type in (N'P', N'PC')) +DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Groups_Save] +GO +CREATE PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Groups_Save] +@PortalId int, +@ModuleId int, +@ForumGroupId int, +@GroupName nvarchar(150), +@SortOrder int, +@Active bit, +@Hidden bit, +@PermissionsId int, +@PrefixURL nvarchar(50), +@GroupSettingsKey varchar(255) = '' +AS +IF @PrefixURL <> '' AND @ForumGroupId >0 + BEGIN + DECLARE @currURL nvarchar(1000) + SET @currURL = {databaseOwner}{objectQualifier}fn_activeforums_GetURL(@ModuleId,@ForumGroupId, -1,-1,-1,-1) + DECLARE @newURL nvarchar(1000) + SET @currURL = {databaseOwner}{objectQualifier}fn_activeforums_GetURL(@ModuleId,-1, -1,-1,-1,-1) + @PrefixURL + '/' + IF LTRIM(RTRIM(LOWER(@newURL))) <> LTRIM(RTRIM(LOWER(@currURL))) + BEGIN + exec {databaseOwner}{objectQualifier}activeforums_URL_Archive @PortalId,@ForumGroupId, -1, -1, @currURL + END + END +IF EXISTS(Select ForumGroupId FROM {databaseOwner}{objectQualifier}activeforums_Groups WHERE ForumGroupId = @ForumGroupId AND ModuleId = @ModuleId) + UPDATE {databaseOwner}{objectQualifier}activeforums_Groups + SET GroupName=@GroupName, Active=@Active,Hidden=@Hidden, PermissionsId = @PermissionsId,PrefixURL = @PrefixURL + WHERE ForumGroupId = @ForumGroupId and ModuleId = @ModuleId +ELSE + BEGIN + BEGIN + SELECT @SortOrder = Max(SortOrder) + 1 From {databaseOwner}{objectQualifier}activeforums_Groups WHERE ModuleID=@ModuleID + If @SortOrder IS NULL + SET @SortOrder = 1 + END + INSERT INTO {databaseOwner}{objectQualifier}activeforums_Groups + (ModuleId, GroupName, SortOrder,GroupSettingsKey,Active,Hidden, PermissionsId,PrefixURL) + VALUES + (@ModuleId, @GroupName, @SortOrder,'',@Active,@Hidden, @PermissionsId,@PrefixURL) + SET @ForumGroupId = SCOPE_IDENTITY() + END +BEGIN + IF @GroupSettingsKey = '' + UPDATE {databaseOwner}{objectQualifier}activeforums_Groups SET GroupSettingsKey = 'G' + CAST(@ForumGroupId as varchar(50)) WHERE ForumGroupId = @ForumGroupId + ELSE + UPDATE {databaseOwner}{objectQualifier}activeforums_Groups SET GroupSettingsKey = @GroupSettingsKey WHERE ForumGroupId = @ForumGroupId + END +SELECT @ForumGroupId +GO + +/* issue 1547 - end - remove colon from settings keys */ + +/* --------------------- */ From 1c4f1f5e0fb2151c8aa638c7650ef66f3d324184 Mon Sep 17 00:00:00 2001 From: John Henley Date: Fri, 10 Oct 2025 20:00:03 +0000 Subject: [PATCH 13/20] TASK: Remove colon ":" from SettingsKey --- .../Controllers/ForumController.cs | 6 +- .../Controllers/ForumGroupController.cs | 6 +- .../SqlDataProvider/SqlDataProvider.cs | 2 +- Dnn.CommunityForums/class/ForumsConfig.cs | 8 +- Dnn.CommunityForums/class/ModuleSettings.cs | 2 +- .../admin_manageforums_forumeditor.ascx.cs | 6 +- .../sql/09.02.00.SqlDataProvider | 108 +++++++++++++++++- 7 files changed, 122 insertions(+), 16 deletions(-) diff --git a/Dnn.CommunityForums/Controllers/ForumController.cs b/Dnn.CommunityForums/Controllers/ForumController.cs index a86eeb6d6..420cf00a2 100644 --- a/Dnn.CommunityForums/Controllers/ForumController.cs +++ b/Dnn.CommunityForums/Controllers/ForumController.cs @@ -260,14 +260,14 @@ public int Forums_Save(int portalId, DotNetNuke.Modules.ActiveForums.Entities.Fo copyDownGroupSettings = true; } - forumInfo.ForumSettingsKey = useGroupFeatures ? (forumGroupInfo != null ? forumGroupInfo.GroupSettingsKey : string.Empty) : (forumInfo.ForumID > 0 ? $"F:{forumInfo.ForumID}" : string.Empty); + forumInfo.ForumSettingsKey = useGroupFeatures ? (forumGroupInfo != null ? forumGroupInfo.GroupSettingsKey : string.Empty) : (forumInfo.ForumID > 0 ? $"F{forumInfo.ForumID}" : string.Empty); // TODO: When this method is updated to use DAL2 for update, uncomment Cacheable attribute on ForumInfo var forumId = Convert.ToInt32(DotNetNuke.Modules.ActiveForums.DataProvider.Instance().Forum_Save(portalId, forumInfo.ForumID, forumInfo.ModuleId, forumInfo.ForumGroupId, forumInfo.ParentForumId, forumInfo.ForumName, forumInfo.ForumDesc, forumInfo.SortOrder, forumInfo.Active, forumInfo.Hidden, forumInfo.ForumSettingsKey, forumInfo.PermissionsId, forumInfo.PrefixURL, forumInfo.SocialGroupId, forumInfo.HasProperties)); forumInfo = this.GetById(forumId, forumInfo.ModuleId); if (!useGroupFeatures && string.IsNullOrEmpty(forumInfo.ForumSettingsKey)) { - forumInfo.ForumSettingsKey = $"F:{forumId}"; + forumInfo.ForumSettingsKey = $"F{forumId}"; this.Update(forumInfo); } @@ -287,7 +287,7 @@ public int Forums_Save(int portalId, DotNetNuke.Modules.ActiveForums.Entities.Fo // if now inheriting group settings, remove any previously-defined forum settings if (forumInfo.InheritSettings) { - new DotNetNuke.Modules.ActiveForums.Controllers.SettingsController().DeleteForModuleIdSettingsKey(forumInfo.ModuleId, $"F:{forumInfo.ForumID}"); + new DotNetNuke.Modules.ActiveForums.Controllers.SettingsController().DeleteForModuleIdSettingsKey(forumInfo.ModuleId, $"F{forumInfo.ForumID}"); } // Clear the caches diff --git a/Dnn.CommunityForums/Controllers/ForumGroupController.cs b/Dnn.CommunityForums/Controllers/ForumGroupController.cs index 438d49a82..73b673968 100644 --- a/Dnn.CommunityForums/Controllers/ForumGroupController.cs +++ b/Dnn.CommunityForums/Controllers/ForumGroupController.cs @@ -120,7 +120,7 @@ public int Groups_Save(int portalId, DotNetNuke.Modules.ActiveForums.Entities.Fo if (!isNew || forumGroupInfo.InheritSettings) { // reset any forum settings keys previously mapped to the module default to map to new settings key - forumGroupInfo.GroupSettingsKey = $"G:{forumGroupInfo.ForumGroupId}"; + forumGroupInfo.GroupSettingsKey = $"G{forumGroupInfo.ForumGroupId}"; foreach (var forum in fc.GetForums(moduleId: forumGroupInfo.ModuleId).Where(f => f.ForumGroupId == forumGroupInfo.ForumGroupId && f.ForumSettingsKey == SettingsBase.GetModuleSettings(forumGroupInfo.ModuleId).DefaultSettingsKey)) { forum.ForumSettingsKey = forumGroupInfo.GroupSettingsKey; @@ -135,7 +135,7 @@ public int Groups_Save(int portalId, DotNetNuke.Modules.ActiveForums.Entities.Fo forumGroupInfo = this.GetById(forumGroupInfo.ForumGroupId, forumGroupInfo.ModuleId); if (string.IsNullOrEmpty(forumGroupInfo.GroupSettingsKey)) { - forumGroupInfo.GroupSettingsKey = $"G:{forumGroupInfo.ForumGroupId}"; + forumGroupInfo.GroupSettingsKey = $"G{forumGroupInfo.ForumGroupId}"; this.Update(forumGroupInfo); } @@ -155,7 +155,7 @@ public int Groups_Save(int portalId, DotNetNuke.Modules.ActiveForums.Entities.Fo /* if now using default module settings, remove group settings */ if (useDefaultFeatures) { - new DotNetNuke.Modules.ActiveForums.Controllers.SettingsController().DeleteForModuleIdSettingsKey(forumGroupInfo.ModuleId, $"G:{forumGroupInfo.ForumGroupId}"); + new DotNetNuke.Modules.ActiveForums.Controllers.SettingsController().DeleteForModuleIdSettingsKey(forumGroupInfo.ModuleId, $"G{forumGroupInfo.ForumGroupId}"); } ClearSettingsCache(forumGroupInfo.ModuleId); diff --git a/Dnn.CommunityForums/Providers/DataProviders/SqlDataProvider/SqlDataProvider.cs b/Dnn.CommunityForums/Providers/DataProviders/SqlDataProvider/SqlDataProvider.cs index 9bd2c9eea..fad1d9319 100644 --- a/Dnn.CommunityForums/Providers/DataProviders/SqlDataProvider/SqlDataProvider.cs +++ b/Dnn.CommunityForums/Providers/DataProviders/SqlDataProvider/SqlDataProvider.cs @@ -243,7 +243,7 @@ public override void Groups_Move(int ModuleId, int ForumGroupId, int SortDirecti [Obsolete("Deprecated in Community Forums. Removed in 10.00.00. No longer used.")] public override int Groups_Save(int PortalId, int ModuleId, int ForumGroupId, string GroupName, int SortOrder, bool Active, bool Hidden, int PermissionsId, string PrefixURL) { - return Convert.ToInt32(SqlHelper.ExecuteScalar(this.ConnectionString, this.DatabaseOwner + this.ObjectQualifier + "activeforums_Groups_Save", PortalId, ModuleId, ForumGroupId, GroupName, SortOrder, Active, Hidden, PermissionsId, PrefixURL, $"G:{ForumGroupId}")); + return Convert.ToInt32(SqlHelper.ExecuteScalar(this.ConnectionString, this.DatabaseOwner + this.ObjectQualifier + "activeforums_Groups_Save", PortalId, ModuleId, ForumGroupId, GroupName, SortOrder, Active, Hidden, PermissionsId, PrefixURL, $"G{ForumGroupId}")); } public override int Groups_Save(int PortalId, int ModuleId, int ForumGroupId, string GroupName, int SortOrder, bool Active, bool Hidden, int PermissionsId, string PrefixURL, string GroupSettingsKey) diff --git a/Dnn.CommunityForums/class/ForumsConfig.cs b/Dnn.CommunityForums/class/ForumsConfig.cs index 2d4016dd7..493e0bc6f 100644 --- a/Dnn.CommunityForums/class/ForumsConfig.cs +++ b/Dnn.CommunityForums/class/ForumsConfig.cs @@ -179,7 +179,7 @@ private void LoadDefaultForums(int portalId, int moduleId) Active = xNodeList[i].Attributes["active"].Value == "1", Hidden = xNodeList[i].Attributes["hidden"].Value == "1", SortOrder = i, - GroupSettingsKey = $"M:{moduleId}", + GroupSettingsKey = $"M{moduleId}", PermissionsId = SettingsBase.GetModuleSettings(moduleId).DefaultPermissionId, }; var gc = new DotNetNuke.Modules.ActiveForums.Controllers.ForumGroupController(); @@ -204,7 +204,7 @@ private void LoadDefaultForums(int portalId, int moduleId) Active = cNodes[c].Attributes["active"].Value == "1", Hidden = cNodes[c].Attributes["hidden"].Value == "1", SortOrder = c, - ForumSettingsKey = $"G:{groupId}", + ForumSettingsKey = $"G{groupId}", PermissionsId = SettingsBase.GetModuleSettings(moduleId).DefaultPermissionId, }; new DotNetNuke.Modules.ActiveForums.Controllers.ForumController().Forums_Save(portalId, fi, true, true, true); @@ -572,7 +572,7 @@ internal static void Upgrade_EmailNotificationSubjectTokens_080200() } templateInfo.Subject = DotNetNuke.Modules.ActiveForums.Services.Tokens.TokenReplacer.MapLegacyEmailNotificationTokenSynonyms(new StringBuilder(templateInfo.Subject), portalSettings, portalSettings.DefaultLanguage).ToString(); - DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(module.ModuleID, $"M:{module.ModuleID}", ForumSettingKeys.EmailNotificationSubjectTemplate, templateInfo.Subject); + DotNetNuke.Modules.ActiveForums.Controllers.SettingsController.SaveSetting(module.ModuleID, $"M{module.ModuleID}", ForumSettingKeys.EmailNotificationSubjectTemplate, templateInfo.Subject); DotNetNuke.Modules.ActiveForums.DataCache.ClearAllCache(module.ModuleID); } catch (Exception ex) @@ -669,7 +669,7 @@ internal static void Install_Upgrade_ForumDefaultSettingsAndSecurity(int portalI var permissions = new DotNetNuke.Modules.ActiveForums.Controllers.PermissionController().CreateDefaultPermissions(portalSettings, moduleId); DotNetNuke.Entities.Modules.ModuleController.Instance.UpdateModuleSetting(moduleId, SettingKeys.DefaultPermissionId, permissions.PermissionsId.ToString()); - string sKey = $"M:{moduleId}"; + string sKey = $"M{moduleId}"; DotNetNuke.Entities.Modules.ModuleController.Instance.UpdateModuleSetting(moduleId, SettingKeys.DefaultSettingsKey, sKey); if (string.IsNullOrEmpty(SettingsBase.GetModuleSettings(moduleId).DefaultFeatureSettings.EmailNotificationSubjectTemplate)) { diff --git a/Dnn.CommunityForums/class/ModuleSettings.cs b/Dnn.CommunityForums/class/ModuleSettings.cs index 99f801d17..c265aee64 100644 --- a/Dnn.CommunityForums/class/ModuleSettings.cs +++ b/Dnn.CommunityForums/class/ModuleSettings.cs @@ -183,7 +183,7 @@ public ProfileVisibilities ProfileVisibility public int DefaultPermissionId => this.MainSettings.GetInt(SettingKeys.DefaultPermissionId); - public string DefaultSettingsKey => this.MainSettings.GetString(SettingKeys.DefaultSettingsKey) ?? $"M:{this.ModuleId}"; + public string DefaultSettingsKey => this.MainSettings.GetString(SettingKeys.DefaultSettingsKey) ?? $"M{this.ModuleId}"; public FeatureSettings DefaultFeatureSettings { diff --git a/Dnn.CommunityForums/controls/admin_manageforums_forumeditor.ascx.cs b/Dnn.CommunityForums/controls/admin_manageforums_forumeditor.ascx.cs index 04ac77ee0..29a845e4f 100644 --- a/Dnn.CommunityForums/controls/admin_manageforums_forumeditor.ascx.cs +++ b/Dnn.CommunityForums/controls/admin_manageforums_forumeditor.ascx.cs @@ -438,7 +438,7 @@ private void cbEditorAction_Callback(object sender, Controls.CallBackEventArgs e case "modulesettingssave": { - var sKey = $"M:{this.ModuleId}"; + var sKey = $"M{this.ModuleId}"; this.SaveSettings(sKey, e.Parameters); this.hidEditorResult.Value = this.ModuleId.ToString(); @@ -449,7 +449,7 @@ private void cbEditorAction_Callback(object sender, Controls.CallBackEventArgs e case "forumsettingssave": { var forumId = Utilities.SafeConvertInt(e.Parameters[1]); - var sKey = $"F:{forumId}"; + var sKey = $"F{forumId}"; this.SaveSettings(sKey, e.Parameters); this.hidEditorResult.Value = forumId.ToString(); @@ -460,7 +460,7 @@ private void cbEditorAction_Callback(object sender, Controls.CallBackEventArgs e case "groupsettingssave": { var groupId = Utilities.SafeConvertInt(e.Parameters[1]); - var sKey = $"G:{groupId}"; + var sKey = $"G{groupId}"; this.SaveSettings(sKey, e.Parameters); this.hidEditorResult.Value = groupId.ToString(); diff --git a/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider b/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider index 097f38057..ea0200c84 100644 --- a/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider +++ b/Dnn.CommunityForums/sql/09.02.00.SqlDataProvider @@ -2257,4 +2257,110 @@ END GO /* issue 1535 - end -- add DateCreated to activeforums_Likes */ -/* --------------------- */ \ No newline at end of file +/* --------------------- */ + +/* issue 1547 - begin - remove colon from settings keys */ + +UPDATE {databaseOwner}[{objectQualifier}activeforums_Forums] SET ForumSettingsKey = REPLACE(ForumSettingsKey, ':', '') +GO + +UPDATE {databaseOwner}[{objectQualifier}activeforums_Groups] SET GroupSettingsKey = REPLACE(GroupSettingsKey, ':', '') +GO + +UPDATE ms +SET SettingValue = REPLACE(SettingValue, ':', '') +FROM {databaseOwner}[{objectQualifier}ModuleSettings] ms +INNER JOIN {databaseOwner}[{objectQualifier}Modules] m +ON m.ModuleID = ms.ModuleID +INNER JOIN {databaseOwner}[{objectQualifier}ModuleDefinitions] md +ON md.ModuleDefID = m.ModuleDefID +WHERE md.DefinitionName = 'DNN Community Forums' +AND ms.SettingName = 'DEFAULTSETTINGSKEY' +GO + +UPDATE {databaseOwner}[{objectQualifier}activeforums_Settings] SET SettingsKey = REPLACE(SettingsKey, ':', '') +GO + +/* remove any orphaned settings */ + +DELETE s +FROM {databaseOwner}[{objectQualifier}activeforums_Settings] s +LEFT OUTER JOIN +( +SELECT +DISTINCT SettingsKey FROM +( +SELECT ForumSettingsKey AS SettingsKey FROM {databaseOwner}[{objectQualifier}activeforums_Forums] +UNION +SELECT GroupSettingsKey AS Settings FROM {databaseOwner}[{objectQualifier}activeforums_Groups] +UNION +SELECT SettingValue AS SettingsKey +FROM {databaseOwner}[{objectQualifier}ModuleSettings] ms +INNER JOIN {databaseOwner}[{objectQualifier}Modules] m +ON m.ModuleID = ms.ModuleID +INNER JOIN {databaseOwner}[{objectQualifier}ModuleDefinitions] md +ON md.ModuleDefID = m.ModuleDefID +WHERE md.DefinitionName = 'DNN Community Forums' +AND ms.SettingName = 'DEFAULTSETTINGSKEY' +) x +) used +ON s.SettingsKey = used.SettingsKey +WHERE used.SettingsKey IS NULL +GO + +/* activeforums_Groups_Save --remove colon from settings keys */ +IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}activeforums_Groups_Save]') AND type in (N'P', N'PC')) +DROP PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Groups_Save] +GO +CREATE PROCEDURE {databaseOwner}[{objectQualifier}activeforums_Groups_Save] +@PortalId int, +@ModuleId int, +@ForumGroupId int, +@GroupName nvarchar(150), +@SortOrder int, +@Active bit, +@Hidden bit, +@PermissionsId int, +@PrefixURL nvarchar(50), +@GroupSettingsKey varchar(255) = '' +AS +IF @PrefixURL <> '' AND @ForumGroupId >0 + BEGIN + DECLARE @currURL nvarchar(1000) + SET @currURL = {databaseOwner}{objectQualifier}fn_activeforums_GetURL(@ModuleId,@ForumGroupId, -1,-1,-1,-1) + DECLARE @newURL nvarchar(1000) + SET @currURL = {databaseOwner}{objectQualifier}fn_activeforums_GetURL(@ModuleId,-1, -1,-1,-1,-1) + @PrefixURL + '/' + IF LTRIM(RTRIM(LOWER(@newURL))) <> LTRIM(RTRIM(LOWER(@currURL))) + BEGIN + exec {databaseOwner}{objectQualifier}activeforums_URL_Archive @PortalId,@ForumGroupId, -1, -1, @currURL + END + END +IF EXISTS(Select ForumGroupId FROM {databaseOwner}{objectQualifier}activeforums_Groups WHERE ForumGroupId = @ForumGroupId AND ModuleId = @ModuleId) + UPDATE {databaseOwner}{objectQualifier}activeforums_Groups + SET GroupName=@GroupName, Active=@Active,Hidden=@Hidden, PermissionsId = @PermissionsId,PrefixURL = @PrefixURL + WHERE ForumGroupId = @ForumGroupId and ModuleId = @ModuleId +ELSE + BEGIN + BEGIN + SELECT @SortOrder = Max(SortOrder) + 1 From {databaseOwner}{objectQualifier}activeforums_Groups WHERE ModuleID=@ModuleID + If @SortOrder IS NULL + SET @SortOrder = 1 + END + INSERT INTO {databaseOwner}{objectQualifier}activeforums_Groups + (ModuleId, GroupName, SortOrder,GroupSettingsKey,Active,Hidden, PermissionsId,PrefixURL) + VALUES + (@ModuleId, @GroupName, @SortOrder,'',@Active,@Hidden, @PermissionsId,@PrefixURL) + SET @ForumGroupId = SCOPE_IDENTITY() + END +BEGIN + IF @GroupSettingsKey = '' + UPDATE {databaseOwner}{objectQualifier}activeforums_Groups SET GroupSettingsKey = 'G' + CAST(@ForumGroupId as varchar(50)) WHERE ForumGroupId = @ForumGroupId + ELSE + UPDATE {databaseOwner}{objectQualifier}activeforums_Groups SET GroupSettingsKey = @GroupSettingsKey WHERE ForumGroupId = @ForumGroupId + END +SELECT @ForumGroupId +GO + +/* issue 1547 - end - remove colon from settings keys */ + +/* --------------------- */ From b4527eadad489905eaa2356537af4c0385d4be41 Mon Sep 17 00:00:00 2001 From: Lars Wernlund Date: Sun, 12 Oct 2025 15:45:38 +0200 Subject: [PATCH 14/20] Encode non-latin characters in content-disposition --- Dnn.CommunityForums/viewer.aspx.cs | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/Dnn.CommunityForums/viewer.aspx.cs b/Dnn.CommunityForums/viewer.aspx.cs index fbac8808c..d56fcf1c6 100644 --- a/Dnn.CommunityForums/viewer.aspx.cs +++ b/Dnn.CommunityForums/viewer.aspx.cs @@ -24,6 +24,7 @@ namespace DotNetNuke.Modules.ActiveForums using System.Diagnostics; using System.IO; using System.Text.RegularExpressions; + using System.Net.Http.Headers; using DotNetNuke.Modules.ActiveForums.Extensions; using DotNetNuke.Services.FileSystem; @@ -91,20 +92,17 @@ protected override void OnLoad(EventArgs e) // Get the filename with the unique identifier prefix removed. var filename = Regex.Replace(attachment.FileName.TextOrEmpty(), @"__\d+__\d+__", string.Empty); + // Handle legacy inline attachments a bit differently + string contentDispositionType = (attachmentId > 0) ? "attachment" : "inline"; + var contentDispositionValue = new ContentDispositionHeaderValue(contentDispositionType); + contentDispositionValue.FileName = filename; + string contentDisposition = contentDispositionValue.ToString(); + // Some legacy attachments may still be stored in the DB. if (attachment.FileData != null) { this.Response.ContentType = attachment.ContentType; - - if (attachmentId > 0) - { - this.Response.AddHeader("Content-Disposition", "attachment; filename=" + this.Server.HtmlEncode(filename)); - } - else // Handle legacy inline attachments a bit differently - { - this.Response.AddHeader("Content-Disposition", "filename=" + this.Server.HtmlEncode(filename)); - } - + this.Response.AddHeader("Content-Disposition", contentDisposition); this.Response.BinaryWrite(attachment.FileData); this.Response.End(); return; @@ -154,15 +152,7 @@ protected override void OnLoad(EventArgs e) this.Response.Clear(); this.Response.ContentType = attachment.ContentType; - if (attachmentId > 0) - { - this.Response.AddHeader("Content-Disposition", "attachment; filename=" + this.Server.HtmlEncode(filename)); - } - else // Handle legacy inline attachments a bit differently - { - this.Response.AddHeader("Content-Disposition", "filename=" + this.Server.HtmlEncode(filename)); - } - + this.Response.AddHeader("Content-Disposition", contentDisposition); this.Response.AddHeader("Content-Length", length.ToString()); this.Response.WriteFile(filePath); this.Response.Flush(); From 88255cb7688f385ddf71eae21690018b0cd0bef2 Mon Sep 17 00:00:00 2001 From: John Henley Date: Tue, 14 Oct 2025 19:53:29 +0000 Subject: [PATCH 15/20] FIX: Datatables.NET paging --- .../controls/af_assign_badge_users.ascx.cs | 2 +- .../controls/af_assign_user_badges.ascx.cs | 2 +- .../controls/af_recycle_bin.ascx.cs | 20 ------- .../controls/profile_mysubscriptions.ascx | 6 +-- .../controls/profile_mysubscriptions.ascx.cs | 53 +++++++------------ 5 files changed, 25 insertions(+), 58 deletions(-) diff --git a/Dnn.CommunityForums/controls/af_assign_badge_users.ascx.cs b/Dnn.CommunityForums/controls/af_assign_badge_users.ascx.cs index 6ab930c75..fe2a9fa0b 100644 --- a/Dnn.CommunityForums/controls/af_assign_badge_users.ascx.cs +++ b/Dnn.CommunityForums/controls/af_assign_badge_users.ascx.cs @@ -74,7 +74,7 @@ private void BindBadgeUsers() { this.dgrdBadgeUsers.DataSource = this.GetBadges().ToList(); this.dgrdBadgeUsers.DataBind(); - this.dgrdBadgeUsers.PageSize = this.dgrdBadgeUsers.Rows.Count; + this.dgrdBadgeUsers.AllowPaging = false; this.dgrdBadgeUsers.WrapGridViewInDataTableNet(this.PortalSettings, this.UserInfo); } diff --git a/Dnn.CommunityForums/controls/af_assign_user_badges.ascx.cs b/Dnn.CommunityForums/controls/af_assign_user_badges.ascx.cs index 3d8466f3b..672b666bc 100644 --- a/Dnn.CommunityForums/controls/af_assign_user_badges.ascx.cs +++ b/Dnn.CommunityForums/controls/af_assign_user_badges.ascx.cs @@ -71,7 +71,7 @@ private void BindUserBadges() { this.dgrdUserBadges.DataSource = this.GetBadges().ToList(); this.dgrdUserBadges.DataBind(); - this.dgrdUserBadges.PageSize = this.dgrdUserBadges.Rows.Count; + this.dgrdUserBadges.AllowPaging = false; this.dgrdUserBadges.WrapGridViewInDataTableNet(this.PortalSettings, this.UserInfo); } diff --git a/Dnn.CommunityForums/controls/af_recycle_bin.ascx.cs b/Dnn.CommunityForums/controls/af_recycle_bin.ascx.cs index 8af2b7496..d4f0fc713 100644 --- a/Dnn.CommunityForums/controls/af_recycle_bin.ascx.cs +++ b/Dnn.CommunityForums/controls/af_recycle_bin.ascx.cs @@ -69,7 +69,6 @@ protected override void OnInit(EventArgs e) this.dgrdRestoreView.Columns[6].HeaderText = DotNetNuke.Modules.ActiveForums.Utilities.GetSharedResource("[RESX:Author]"); this.dgrdRestoreView.Columns[7].HeaderText = DotNetNuke.Modules.ActiveForums.Utilities.GetSharedResource("[RESX:DateCreated]"); - //this.dgrdRestoreView.PageIndexChanging += this.RestoreViewGridRowPageIndexChanging; this.dgrdRestoreView.RowCommand += this.RestoreViewGrid_OnRowCommand; this.dgrdRestoreView.RowDataBound += this.OnRestoreViewGridRowDataBound; this.btnEmptyRecycleBin.Click += this.btnEmptyRecycleBin_Click; @@ -125,18 +124,6 @@ protected override void OnLoad(EventArgs e) base.OnLoad(e); try { - int _pageSize = this.ModuleSettings.PageSize; - if (this.UserInfo.UserID > 0) - { - _pageSize = this.UserDefaultPageSize; - } - - if (_pageSize < 5) - { - _pageSize = 10; - } - - if (this.UserId > 0 && this.ForumUser.GetIsMod(this.ForumModuleId)) { this.BindRecycleData(); @@ -153,7 +140,6 @@ private void BindRecycleData() var recycleData = this.GetData().ToList(); this.dgrdRestoreView.DataSource = recycleData; this.dgrdRestoreView.DataBind(); - this.dgrdRestoreView.PageSize = this.dgrdRestoreView.Rows.Count; this.btnEmptyRecycleBin.Enabled = recycleData.Any(); this.btnRestoreAll.Enabled = recycleData.Any(); this.dgrdRestoreView.WrapGridViewInDataTableNet(this.PortalSettings, this.UserInfo); @@ -210,11 +196,5 @@ protected void OnRestoreViewGridRowDataBound(object sender, GridViewRowEventArgs } } } - - //protected void RestoreViewGridRowPageIndexChanging(object sender, GridViewPageEventArgs e) - //{ - // this.dgrdRestoreView.PageIndex = e.NewPageIndex; - // this.dgrdRestoreView.DataBind(); - //} } } diff --git a/Dnn.CommunityForums/controls/profile_mysubscriptions.ascx b/Dnn.CommunityForums/controls/profile_mysubscriptions.ascx index d8687eb37..580c8d120 100644 --- a/Dnn.CommunityForums/controls/profile_mysubscriptions.ascx +++ b/Dnn.CommunityForums/controls/profile_mysubscriptions.ascx @@ -7,8 +7,8 @@ [RESX:Topic] [RESX:Subscriptions]: - + @@ -36,7 +36,7 @@ [RESX:Forum] [RESX:Subscriptions]: - diff --git a/Dnn.CommunityForums/controls/profile_mysubscriptions.ascx.cs b/Dnn.CommunityForums/controls/profile_mysubscriptions.ascx.cs index 9b596fd11..afdc82739 100644 --- a/Dnn.CommunityForums/controls/profile_mysubscriptions.ascx.cs +++ b/Dnn.CommunityForums/controls/profile_mysubscriptions.ascx.cs @@ -49,8 +49,8 @@ protected override void OnInit(EventArgs e) this.dgrdForumSubs.Columns[4].HeaderText = DotNetNuke.Modules.ActiveForums.Utilities.GetSharedResource("[RESX:Forum].Text"); this.dgrdForumSubs.Columns[5].HeaderText = DotNetNuke.Modules.ActiveForums.Utilities.GetSharedResource("[RESX:LastPost].Text"); - this.dgrdTopicSubs.RowDataBound += this.OnTopicSubsGridRowDataBound; - this.dgrdForumSubs.RowDataBound += this.OnForumSubsGridRowDataBound; + this.dgrdTopicSubs.RowDataBound += this.GridRowDataBound; + this.dgrdForumSubs.RowDataBound += this.GridRowDataBound; this.btnSubscribeAll.Click += this.btnSubscribeAll_Click; } @@ -82,7 +82,7 @@ private void BindTopicSubs() }); this.dgrdTopicSubs.DataSource = subscribedTopics.ToList(); this.dgrdTopicSubs.DataBind(); - this.dgrdTopicSubs.PageSize = this.dgrdTopicSubs.Rows.Count; + this.dgrdTopicSubs.AllowPaging = false; this.dgrdTopicSubs.WrapGridViewInDataTableNet(this.PortalSettings, this.UserInfo); } @@ -90,7 +90,7 @@ private void BindForumSubs() { this.dgrdForumSubs.DataSource = this.GetSubscriptions().ToList(); this.dgrdForumSubs.DataBind(); - this.dgrdForumSubs.PageSize = this.dgrdForumSubs.Rows.Count; + this.dgrdForumSubs.AllowPaging = false; this.dgrdForumSubs.WrapGridViewInDataTableNet(this.PortalSettings, this.UserInfo); } @@ -105,12 +105,15 @@ private void btnSubscribeAll_Click(object sender, System.EventArgs e) private IEnumerable GetSubscriptions() { - var userPermSet = new DotNetNuke.Modules.ActiveForums.Controllers.ForumUserController(this.ForumModuleId).GetByUserId(this.PortalId, this.UID).UserPermSet; + var availableForums = new List(); var availableForumsString = DotNetNuke.Modules.ActiveForums.Controllers.ForumController.GetForumsForUser(this.PortalId, this.ForumModuleId, this.ForumUser); - var availableForums = availableForumsString.Split(separator: new[] { ';' }, options: StringSplitOptions.RemoveEmptyEntries).Select(forum => + availableForumsString.Split(separator: new[] { ';' }, options: StringSplitOptions.RemoveEmptyEntries).ForEach(forumId => { - var Forum = new DotNetNuke.Modules.ActiveForums.Controllers.ForumController().GetById(int.Parse(forum), this.ForumModuleId); - return new { ForumId = int.Parse(forum), Forum }; + var forum = new DotNetNuke.Modules.ActiveForums.Controllers.ForumController().GetById(int.Parse(forumId), this.ForumModuleId); + if (DotNetNuke.Modules.ActiveForums.Controllers.PermissionController.HasRequiredPerm(forum.Security.SubscribeRoleIds, this.ForumUser.UserRoleIds)) + { + availableForums.Add(new { ForumId = int.Parse(forumId), Forum = forum }); + } }); var forumSubscriptions = new DotNetNuke.Modules.ActiveForums.Controllers.SubscriptionController().SubscribedForums(this.PortalId, this.ForumModuleId, this.UID); @@ -127,30 +130,7 @@ from ms in merged.DefaultIfEmpty() return mergedSubscriptions; } - protected void OnForumSubsGridRowDataBound(object sender, GridViewRowEventArgs e) - { - if (e.Row.RowType == DataControlRowType.DataRow) - { - DotNetNuke.Modules.ActiveForums.Entities.SubscriptionInfo subscriptionInfo = e.Row.DataItem as DotNetNuke.Modules.ActiveForums.Entities.SubscriptionInfo; - foreach (TableCell cell in e.Row.Cells) - { - foreach (Control cellControl in cell.Controls) - { - if (cellControl is CheckBox) - { - var chkBox = cellControl as CheckBox; - if (!(chkBox == null)) - { - chkBox.Attributes.Add("onclick", "amaf_forumSubscribe(" + this.ForumModuleId + "," + subscriptionInfo.ForumId + ");"); - chkBox.Enabled = true; - } - } - } - } - } - } - - protected void OnTopicSubsGridRowDataBound(object sender, GridViewRowEventArgs e) + protected void GridRowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType == DataControlRowType.DataRow) { @@ -164,7 +144,14 @@ protected void OnTopicSubsGridRowDataBound(object sender, GridViewRowEventArgs e var chkBox = cellControl as CheckBox; if (!(chkBox == null)) { - chkBox.Attributes.Add("onclick", "amaf_topicSubscribe(" + this.ForumModuleId + "," + subscriptionInfo.ForumId + "," + subscriptionInfo.TopicId + ");"); + if (subscriptionInfo.TopicId > 0) + { + chkBox.Attributes.Add("onclick", "amaf_topicSubscribe(" + this.ForumModuleId + "," + subscriptionInfo.ForumId + "," + subscriptionInfo.TopicId + ");"); + } + else + { + chkBox.Attributes.Add("onclick", "amaf_forumSubscribe(" + this.ForumModuleId + "," + subscriptionInfo.ForumId + ");"); + } chkBox.Enabled = true; } } From cebe55237a0a44fa7931b4c4654ca78bf7f0ef8c Mon Sep 17 00:00:00 2001 From: John Henley Date: Wed, 15 Oct 2025 21:58:53 +0000 Subject: [PATCH 16/20] FIX: HTML Decode Email notification subject --- Dnn.CommunityForums/Controllers/EmailController.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dnn.CommunityForums/Controllers/EmailController.cs b/Dnn.CommunityForums/Controllers/EmailController.cs index 08da35fb8..12780ed04 100644 --- a/Dnn.CommunityForums/Controllers/EmailController.cs +++ b/Dnn.CommunityForums/Controllers/EmailController.cs @@ -105,7 +105,7 @@ internal static void SendTemplatedEmail(int topicId, int replyId, int moduleId, { topicSubscriber.Email, }, - Subject = Utilities.StripHTMLTag(TemplateUtils.ParseEmailTemplate(subjectTemplate, portalID: fi.PortalId, moduleID: moduleId, tabID: tabId, forumID: fi.ForumID, topicId: topicId, replyId: replyId, author: author, accessingUser: topicSubscriber.User, topicSubscriber: true, navigationManager: navigationManager, requestUrl: requestUrl, rawUrl: rawUrl)), + Subject = Utilities.StripHTMLTag(System.Net.WebUtility.HtmlDecode(TemplateUtils.ParseEmailTemplate(subjectTemplate, portalID: fi.PortalId, moduleID: moduleId, tabID: tabId, forumID: fi.ForumID, topicId: topicId, replyId: replyId, author: author, accessingUser: topicSubscriber.User, topicSubscriber: true, navigationManager: navigationManager, requestUrl: requestUrl, rawUrl: rawUrl))), Body = TemplateUtils.ParseEmailTemplate(bodyTemplate, portalID: fi.PortalId, moduleID: moduleId, tabID: tabId, forumID: fi.ForumID, topicId: topicId, replyId: replyId, author: author, accessingUser: topicSubscriber.User, topicSubscriber: true, navigationManager: navigationManager, requestUrl: requestUrl, rawUrl: rawUrl), }); } @@ -122,7 +122,7 @@ internal static void SendTemplatedEmail(int topicId, int replyId, int moduleId, { forumSubscriber.Email, }, - Subject = Utilities.StripHTMLTag(TemplateUtils.ParseEmailTemplate(subjectTemplate, portalID: fi.PortalId, moduleID: moduleId, tabID: tabId, forumID: fi.ForumID, topicId: topicId, replyId: replyId, author: author, accessingUser: forumSubscriber.User, topicSubscriber: false, navigationManager: navigationManager, requestUrl: requestUrl, rawUrl: rawUrl)), + Subject = Utilities.StripHTMLTag(System.Net.WebUtility.HtmlDecode(TemplateUtils.ParseEmailTemplate(subjectTemplate, portalID: fi.PortalId, moduleID: moduleId, tabID: tabId, forumID: fi.ForumID, topicId: topicId, replyId: replyId, author: author, accessingUser: forumSubscriber.User, topicSubscriber: false, navigationManager: navigationManager, requestUrl: requestUrl, rawUrl: rawUrl))), Body = TemplateUtils.ParseEmailTemplate(bodyTemplate, portalID: fi.PortalId, moduleID: moduleId, tabID: tabId, forumID: fi.ForumID, topicId: topicId, replyId: replyId, author: author, accessingUser: forumSubscriber.User, topicSubscriber: false, navigationManager: navigationManager, requestUrl: requestUrl, rawUrl: rawUrl), }); } From 207ac127c5c8cc1b30e938989bd1c81068710ab4 Mon Sep 17 00:00:00 2001 From: John Henley Date: Thu, 16 Oct 2025 21:54:42 +0000 Subject: [PATCH 17/20] FIX: Improve script removal --- Dnn.CommunityForums/class/Utilities.cs | 39 ++++- .../class/UtilitiesTests.cs | 137 ++++++++++++++++++ 2 files changed, 172 insertions(+), 4 deletions(-) diff --git a/Dnn.CommunityForums/class/Utilities.cs b/Dnn.CommunityForums/class/Utilities.cs index 3f5d4943f..1d03d783f 100644 --- a/Dnn.CommunityForums/class/Utilities.cs +++ b/Dnn.CommunityForums/class/Utilities.cs @@ -28,6 +28,7 @@ namespace DotNetNuke.Modules.ActiveForums using System.Linq; using System.Reflection; using System.Security.Cryptography; + using System.Security.Principal; using System.Text; using System.Text.RegularExpressions; using System.Web; @@ -487,6 +488,7 @@ public static string CleanString(int portalId, string text, bool allowHTML, Edit if (!allowScript) { + sClean = RemoveScriptTags(sClean); sClean = DecodeBrackets(sClean); sClean = XSSFilter(sClean); } @@ -533,10 +535,7 @@ private static string CleanTextBox(int portalId, string text, bool allowHTML, bo else { strMessage = EncodeFormTags(strMessage); - if (!allowHTML) - { - strMessage = System.Net.WebUtility.HtmlEncode(strMessage); - } + strMessage = System.Net.WebUtility.HtmlEncode(strMessage); if (useFilter) { @@ -739,6 +738,38 @@ public static string XSSFilter(string sText = "", bool removeHTML = false) return sText; } + internal static string RemoveScriptTags(string body = "") + { + if (!string.IsNullOrEmpty(body)) + { + var tryEncoded = false; + for (var i = 0; i < 2; i++) + { + var codeTagStartEndPositions = new List<(int Start, int End)>(); + + const string codeTagPattern = @"<(?:code|pre)\b[^>]*>(.*?)"; + foreach (Match m in RegexUtils.GetCachedRegex(tryEncoded ? System.Net.WebUtility.HtmlEncode(codeTagPattern) : codeTagPattern, RegexOptions.IgnoreCase).Matches(body)) + { + codeTagStartEndPositions.Add((m.Index, m.Index + m.Length)); + } + + const string scriptTagPattern = @"]*>(.*?)"; + foreach (Match m in RegexUtils.GetCachedRegex(tryEncoded ? System.Net.WebUtility.HtmlEncode(scriptTagPattern) : scriptTagPattern, RegexOptions.IgnoreCase).Matches(body)) + { + bool insideCodeTag = m.Index >= 0 && codeTagStartEndPositions.Any(t => m.Index >= t.Start && m.Index < t.End); + if (!insideCodeTag) + { + body = body.Replace(m.Value, string.Empty); + } + } + + tryEncoded = true; + } + } + + return body; + } + public static string StripExecCode(string sText) { var i = 0; diff --git a/Dnn.CommunityForumsTests/class/UtilitiesTests.cs b/Dnn.CommunityForumsTests/class/UtilitiesTests.cs index 17fd8351d..79a1c554c 100644 --- a/Dnn.CommunityForumsTests/class/UtilitiesTests.cs +++ b/Dnn.CommunityForumsTests/class/UtilitiesTests.cs @@ -512,5 +512,142 @@ public void EncodeCodeBlocks_MultipleCodeBlocks_EncodesAll() Assert.That(result.Contains(expected2), Is.True); }); } + + [Test] + public void RemoveScriptTags_NullInput_ReturnsNull() + { + // Arrange + string input = null; + + // Act + string result = Utilities.RemoveScriptTags(input); + + // Assert + Assert.That(result, Is.Null); + } + + [Test] + public void RemoveScriptTags_EmptyInput_ReturnsEmptyString() + { + // Arrange + string input = string.Empty; + + // Act + string result = Utilities.RemoveScriptTags(input); + + // Assert + Assert.That(result, Is.Empty); + } + + [Test] + public void RemoveScriptTags_NoScriptTags_ReturnsSameText() + { + // Arrange + string input = "This is regular text with

    some HTML

    but no script tags."; + + // Act + string result = Utilities.RemoveScriptTags(input); + + // Assert + Assert.That(result, Is.EqualTo(input)); + } + + [Test] + public void RemoveScriptTags_WithScriptTags_RemovesScriptTags() + { + // Arrange + string input = "Text before text after"; + string expected = "Text before text after"; + + // Act + string result = Utilities.RemoveScriptTags(input); + + // Assert + Assert.That(result, Is.EqualTo(expected)); + } + + [Test] + public void RemoveScriptTags_MultipleScriptTags_RemovesAllScriptTags() + { + // Arrange + string input = "middle"; + string expected = "middle"; + + // Act + string result = Utilities.RemoveScriptTags(input); + + // Assert + Assert.That(result, Is.EqualTo(expected)); + } + + [Test] + public void RemoveScriptTags_ScriptTagsWithAttributes_RemovesEntireTag() + { + // Arrange + string input = ""; + string expected = ""; + + // Act + string result = Utilities.RemoveScriptTags(input); + + // Assert + Assert.That(result, Is.EqualTo(expected)); + } + + [Test] + public void RemoveScriptTags_ScriptInsideCodeBlock_PreservesScript() + { + // Arrange + string input = "Before After"; + string expected = input; + + // Act + string result = Utilities.RemoveScriptTags(input); + + // Assert + Assert.That(result, Is.EqualTo(expected)); + } + + [Test] + public void RemoveScriptTags_ScriptInsidePreBlock_PreservesScript() + { + // Arrange + string input = "Before
    After"; + string expected = input; + + // Act + string result = Utilities.RemoveScriptTags(input); + + // Assert + Assert.That(result, Is.EqualTo(expected)); + } + + [Test] + public void RemoveScriptTags_EncodedScriptTags_RemovesEncodedTags() + { + // Arrange + string input = "Before <script>alert('test');</script> After"; + string expected = "Before After"; + + // Act + string result = Utilities.RemoveScriptTags(input); + + // Assert + Assert.That(result, Is.EqualTo(expected)); + } + + [Test] + public void RemoveScriptTags_MixedRegularAndEncodedTags_RemovesBoth() + { + // Arrange + string input = " normal <script>alert(2);</script>"; + string expected = " normal "; + + // Act + string result = Utilities.RemoveScriptTags(input); + + // Assert + Assert.That(result, Is.EqualTo(expected)); + } } } From 6154575007cae9558008615983985c0fcd3b7de2 Mon Sep 17 00:00:00 2001 From: John Henley Date: Fri, 17 Oct 2025 21:28:20 +0000 Subject: [PATCH 18/20] FIX: When saving module settings, only apply social group settings when in Social Groups mode, and if not, remove any settings associated with social group --- Dnn.CommunityForums/ForumSettings.ascx.cs | 37 ++++++++++++++++------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/Dnn.CommunityForums/ForumSettings.ascx.cs b/Dnn.CommunityForums/ForumSettings.ascx.cs index 4f89d0953..792f996ed 100644 --- a/Dnn.CommunityForums/ForumSettings.ascx.cs +++ b/Dnn.CommunityForums/ForumSettings.ascx.cs @@ -22,11 +22,13 @@ namespace DotNetNuke.Modules.ActiveForums.Controls { using System; using System.Linq; + using System.Reflection; using System.Text; using System.Web; using System.Web.UI.WebControls; using System.Xml; + using DotNetNuke.Collections; using DotNetNuke.Entities.Tabs; using DotNetNuke.Entities.Urls; using DotNetNuke.Framework; @@ -254,17 +256,30 @@ public override void UpdateSettings() this.TimeFormatString = !string.IsNullOrWhiteSpace(this.txtTimeFormat.Text) ? this.txtTimeFormat.Text : "h:mm tt"; this.DateFormatString = !string.IsNullOrWhiteSpace(this.txtDateFormat.Text) ? this.txtDateFormat.Text : "M/d/yyyy"; - this.ForumGroupTemplate = Utilities.SafeConvertInt(this.drpForumGroupTemplate.SelectedValue); - var adminSec = this.txtGroupModSec.Value.Split(','); - this.SaveForumSecurity("groupadmin", adminSec); - var memSec = this.txtGroupMemSec.Value.Split(','); - this.SaveForumSecurity("groupmember", memSec); - var regSec = this.txtGroupRegSec.Value.Split(','); - this.SaveForumSecurity("registereduser", regSec); - var anonSec = this.txtGroupAnonSec.Value.Split(','); - this.SaveForumSecurity("anon", anonSec); - - DotNetNuke.Modules.ActiveForums.Controllers.ForumController.UpdatePermissionsForSocialGroupForums(this.ModuleId); + if (this.Mode.Equals("SocialGroup")) + { + this.ForumGroupTemplate = Utilities.SafeConvertInt(this.drpForumGroupTemplate.SelectedValue); + var adminSec = this.txtGroupModSec.Value.Split(','); + this.SaveForumSecurity("groupadmin", adminSec); + var memSec = this.txtGroupMemSec.Value.Split(','); + this.SaveForumSecurity("groupmember", memSec); + var regSec = this.txtGroupRegSec.Value.Split(','); + this.SaveForumSecurity("registereduser", regSec); + var anonSec = this.txtGroupAnonSec.Value.Split(','); + this.SaveForumSecurity("anon", anonSec); + DotNetNuke.Modules.ActiveForums.Controllers.ForumController.UpdatePermissionsForSocialGroupForums(this.ModuleId); + } + else + { + DotNetNuke.Entities.Modules.ModuleController.Instance.DeleteModuleSetting(this.ModuleId, "ForumConfig"); + DotNetNuke.Entities.Modules.ModuleController.Instance.DeleteModuleSetting(this.ModuleId, "ForumGroupTemplate"); + var fc = new DotNetNuke.Modules.ActiveForums.Controllers.ForumController(); + fc.Get(this.ModuleId).Where(f => f.SocialGroupId != 0).ForEach(forum => + { + forum.SocialGroupId = 0; + fc.Update(forum); + }); + } try { From ca39a1573009fadb709171c87c0a0ee7cd9f7583 Mon Sep 17 00:00:00 2001 From: John Henley Date: Fri, 17 Oct 2025 21:38:39 +0000 Subject: [PATCH 19/20] FIX: Correct resource key --- Dnn.CommunityForums/controls/admin_tags.ascx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dnn.CommunityForums/controls/admin_tags.ascx b/Dnn.CommunityForums/controls/admin_tags.ascx index 52a1bd694..0fb512d7d 100644 --- a/Dnn.CommunityForums/controls/admin_tags.ascx +++ b/Dnn.CommunityForums/controls/admin_tags.ascx @@ -56,7 +56,7 @@ function amaf_deleteTag(row){
    [RESX:TagName]
    -
    [RESX:TagItems]
    +
    [RESX:Items]
     
    From 6df405462f7912ebe11fb09ecbfe2b8d881ace6f Mon Sep 17 00:00:00 2001 From: John Henley Date: Fri, 17 Oct 2025 22:07:24 +0000 Subject: [PATCH 20/20] TASK: Release Prep --- Dnn.CommunityForums/DnnCommunityForums.csproj | 2 -- Dnn.CommunityForums/ReleaseNotes.txt | 25 +++++++++++++------ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/Dnn.CommunityForums/DnnCommunityForums.csproj b/Dnn.CommunityForums/DnnCommunityForums.csproj index e82234e5e..22b5a0d63 100644 --- a/Dnn.CommunityForums/DnnCommunityForums.csproj +++ b/Dnn.CommunityForums/DnnCommunityForums.csproj @@ -12,8 +12,6 @@ Discussion Forum Module for DNN dnncommunity.org dnncommunity.org - 09.01.01.00 - 09.01.01.00 09.02.00.00 09.02.00.00 diff --git a/Dnn.CommunityForums/ReleaseNotes.txt b/Dnn.CommunityForums/ReleaseNotes.txt index 84bc3d957..93c1e4005 100644 --- a/Dnn.CommunityForums/ReleaseNotes.txt +++ b/Dnn.CommunityForums/ReleaseNotes.txt @@ -48,37 +48,46 @@

    09.02.00

    -

    New Features & Enhancements

      +
    • NEW: User Badges (PR# 1579)
    • +
    • UPDATE: Change User Setting "Subscribe to Topics" to "Auto-Subscribe to My Topics (Issue 1579)
    • +
    • UPDATE: Encode non-Latin characters in content-disposition for attachments (Issue 1604)
    • None at this time.
    • +-->

    Bug Fixes

      -
    • FIX: Error moving topics to another forum (Issue 1594)
    • +
    • FIX: Error moving topics to another forum (Issue 1594)
    • +
    • FIX: Forum permissions changing under certain rare conditions when updating module settings (Issue 1606)
    • +
    • FIX: Missing (resource) text when viewing tags in Control Panel (Issue 1593)
    • +
    • FIX: On "My Subscriptions" page, forums subscriptions not showing if not subscribed to any forums yet (Issue 1608)
    • +
    • FIX: Reserved HTML characters in topic subjects no longer are encoded in e-mail notification subjects (Issue 1607)
    • +