From ab134ced5fade523d5aeab53cf5f6b3aa232010c Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Sat, 22 Sep 2018 04:20:35 +0200
Subject: [PATCH 01/71] More work on PageBlocks (Storytelling)

---
 src/Libraries/SmartStore.Core/Data/IQueryableExtensions.cs   | 2 --
 .../SmartStore.Web.Framework/UI/Blocks/BlockMetadata.cs      | 5 ++---
 .../SmartStore.Web.Framework/UI/Blocks/IBlockEntity.cs       | 1 +
 3 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/src/Libraries/SmartStore.Core/Data/IQueryableExtensions.cs b/src/Libraries/SmartStore.Core/Data/IQueryableExtensions.cs
index b4426b1ec8..d9534c06ea 100644
--- a/src/Libraries/SmartStore.Core/Data/IQueryableExtensions.cs
+++ b/src/Libraries/SmartStore.Core/Data/IQueryableExtensions.cs
@@ -9,7 +9,6 @@ namespace SmartStore
 {
 	public static class IQueryableExtensions
 	{
-
 		/// <summary>
 		/// Instructs the repository to eager load entities that may be in the type's association path.
 		/// </summary>
@@ -40,6 +39,5 @@ public static IQueryable<T> Expand<T, TProperty>(this IQueryable<T> query, Expre
 
 			return query.Include(path);
 		}
-
 	}
 }
diff --git a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockMetadata.cs b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockMetadata.cs
index d816798c43..ca5b8a1a7b 100644
--- a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockMetadata.cs
+++ b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockMetadata.cs
@@ -14,7 +14,6 @@ public BlockAttribute(string systemName)
 
 		public string SystemName { get; set; }
 		public string FriendlyName { get; set; }
-		public string Description { get; set; }
 		public string Icon { get; set; }
 		public int DisplayOrder { get; set; }
 		public bool IsInternal { get; set; }
@@ -24,10 +23,10 @@ public class IBlockMetadata
 	{
 		string SystemName { get; }
 		string FriendlyName { get; }
-		string Description { get; }
 		string Icon { get; }
 		int DisplayOrder { get; }
 		bool IsInternal { get; }
+		bool IsInbuilt { get; }
 		Type BlockClrType { get; }
 		Type BlockHandlerClrType { get; }
 	}
@@ -36,10 +35,10 @@ public class BlockMetadata : IBlockMetadata
 	{
 		public string SystemName { get; set; }
 		public string FriendlyName { get; set; }
-		public string Description { get; set; }
 		public string Icon { get; set; }
 		public int DisplayOrder { get; set; }
 		public bool IsInternal { get; set; }
+		public bool IsInbuilt { get; set; }
 		public Type BlockClrType { get; set; }
 		public Type BlockHandlerClrType { get; set; }
 	}
diff --git a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockEntity.cs b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockEntity.cs
index aca7d86a3f..d465a2d0c8 100644
--- a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockEntity.cs
+++ b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockEntity.cs
@@ -8,6 +8,7 @@ namespace SmartStore.Web.Framework.UI.Blocks
 {
 	public interface IBlockEntity
 	{
+		int Id { get; set; }
 		string BlockType { get; set; }
 		string Model { get; set; }
 		string TagLine { get; set; }

From 60d231e8f2c6779b1615ff5b6cb448249e49535f Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Mon, 24 Sep 2018 09:58:36 +0200
Subject: [PATCH 02/71] Added a string resource

---
 changelog.md                                        |  1 +
 .../Migrations/MigrationsConfiguration.cs           |  4 ++++
 .../Controllers/ExternalAuthFacebookController.cs   |  3 ++-
 src/Plugins/SmartStore.FacebookAuth/Description.txt |  2 +-
 .../FacebookExternalAuthMethod.cs                   | 13 +++++--------
 .../Localization/resources.de-de.xml                |  2 +-
 .../Localization/resources.en-us.xml                |  2 +-
 .../Controllers/PayPalExpressController.cs          |  6 +++---
 8 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/changelog.md b/changelog.md
index 815963047d..6de6f5b983 100644
--- a/changelog.md
+++ b/changelog.md
@@ -56,6 +56,7 @@
 * Wrong order of featured products on category page.
 * #1504 Cart item price calculation wrong if attribute combinations with text types are involved.
 * #1485 Dropdown list for product sorting does not work with Internet Explorer 11.
+* #1468 Twitter authentication not working anymore.
 
 
 ## SmartStore.NET 3.1.5
diff --git a/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs b/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
index f4fa247bb7..3a75d87c08 100644
--- a/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
+++ b/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
@@ -509,6 +509,10 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder)
             builder.AddOrUpdate("Search.RelatedSearchTerms",
                 "Related search terms",
                 "Verwandte Suchbegriffe");
+
+            builder.AddOrUpdate("Plugins.CannotLoadModule",
+                "The plugin or provider \"{0}\" cannot be loaded.",
+                "Das Plugin oder der Provider \"{0}\" kann nicht geladen werden.");
         }
     }
 }
diff --git a/src/Plugins/SmartStore.FacebookAuth/Controllers/ExternalAuthFacebookController.cs b/src/Plugins/SmartStore.FacebookAuth/Controllers/ExternalAuthFacebookController.cs
index 96ed94260a..d7462cd9e5 100644
--- a/src/Plugins/SmartStore.FacebookAuth/Controllers/ExternalAuthFacebookController.cs
+++ b/src/Plugins/SmartStore.FacebookAuth/Controllers/ExternalAuthFacebookController.cs
@@ -103,7 +103,8 @@ private ActionResult LoginInternal(string returnUrl, bool verifyResponse)
 			var processor = _openAuthenticationService.LoadExternalAuthenticationMethodBySystemName(FacebookExternalAuthMethod.SystemName, _services.StoreContext.CurrentStore.Id);
 			if (processor == null || !processor.IsMethodActive(_externalAuthenticationSettings))
 			{
-				throw new SmartException("Facebook module cannot be loaded");
+                NotifyError(T("Plugins.CannotLoadModule", T("Plugins.FriendlyName.SmartStore.FacebookAuth")));
+                return new RedirectResult(Url.LogOn(returnUrl));
 			}
 
 			var viewModel = new LoginModel();
diff --git a/src/Plugins/SmartStore.FacebookAuth/Description.txt b/src/Plugins/SmartStore.FacebookAuth/Description.txt
index 514333f075..2c84b47230 100644
--- a/src/Plugins/SmartStore.FacebookAuth/Description.txt
+++ b/src/Plugins/SmartStore.FacebookAuth/Description.txt
@@ -1,4 +1,4 @@
-FriendlyName: Facebook
+FriendlyName: Facebook Login
 SystemName: SmartStore.FacebookAuth
 Group: Security
 Version: 3.1.5
diff --git a/src/Plugins/SmartStore.FacebookAuth/FacebookExternalAuthMethod.cs b/src/Plugins/SmartStore.FacebookAuth/FacebookExternalAuthMethod.cs
index 86ed1ab677..db68ea5d5c 100644
--- a/src/Plugins/SmartStore.FacebookAuth/FacebookExternalAuthMethod.cs
+++ b/src/Plugins/SmartStore.FacebookAuth/FacebookExternalAuthMethod.cs
@@ -1,22 +1,19 @@
 using System.Web.Routing;
 using SmartStore.Core.Plugins;
-using SmartStore.FacebookAuth.Core;
 using SmartStore.Services.Authentication.External;
 using SmartStore.Services.Localization;
 
 namespace SmartStore.FacebookAuth
 {
-	/// <summary>
-	/// Facebook externalAuth processor
-	/// </summary>
-	public class FacebookExternalAuthMethod : BasePlugin, IExternalAuthenticationMethod, IConfigurable
+    /// <summary>
+    /// Facebook externalAuth processor
+    /// </summary>
+    public class FacebookExternalAuthMethod : BasePlugin, IExternalAuthenticationMethod, IConfigurable
     {
-        private readonly FacebookExternalAuthSettings _facebookExternalAuthSettings;
         private readonly ILocalizationService _localizationService;
 
-        public FacebookExternalAuthMethod(FacebookExternalAuthSettings facebookExternalAuthSettings, ILocalizationService localizationService)
+        public FacebookExternalAuthMethod(ILocalizationService localizationService)
         {
-            _facebookExternalAuthSettings = facebookExternalAuthSettings;
             _localizationService = localizationService;
         }
 
diff --git a/src/Plugins/SmartStore.FacebookAuth/Localization/resources.de-de.xml b/src/Plugins/SmartStore.FacebookAuth/Localization/resources.de-de.xml
index 6839a4255c..f65160a398 100644
--- a/src/Plugins/SmartStore.FacebookAuth/Localization/resources.de-de.xml
+++ b/src/Plugins/SmartStore.FacebookAuth/Localization/resources.de-de.xml
@@ -1,6 +1,6 @@
 <Language Name="Deutsch" IsDefault="true" IsRightToLeft="false">
 	<LocaleResource Name="Plugins.FriendlyName.SmartStore.FacebookAuth" AppendRootKey="false">
-		<Value>Facebook</Value>
+		<Value>Facebook Login</Value>
 	</LocaleResource>
 	<LocaleResource Name="AdminInstruction">
 		<Value>
diff --git a/src/Plugins/SmartStore.FacebookAuth/Localization/resources.en-us.xml b/src/Plugins/SmartStore.FacebookAuth/Localization/resources.en-us.xml
index fdf0710bfa..0da7b1e2dd 100644
--- a/src/Plugins/SmartStore.FacebookAuth/Localization/resources.en-us.xml
+++ b/src/Plugins/SmartStore.FacebookAuth/Localization/resources.en-us.xml
@@ -1,6 +1,6 @@
 <Language Name="English" IsDefault="false" IsRightToLeft="false">
 	<LocaleResource Name="Plugins.FriendlyName.SmartStore.FacebookAuth" AppendRootKey="false">
-		<Value>Facebook</Value>
+		<Value>Facebook Login</Value>
 	</LocaleResource>
 	<LocaleResource Name="AdminInstruction">
 		<Value>
diff --git a/src/Plugins/SmartStore.PayPal/Controllers/PayPalExpressController.cs b/src/Plugins/SmartStore.PayPal/Controllers/PayPalExpressController.cs
index faed628e5e..1f09fdbfda 100644
--- a/src/Plugins/SmartStore.PayPal/Controllers/PayPalExpressController.cs
+++ b/src/Plugins/SmartStore.PayPal/Controllers/PayPalExpressController.cs
@@ -166,7 +166,7 @@ public ActionResult SubmitButton()
 				var provider = PaymentService.LoadPaymentMethodBySystemName(PayPalExpressProvider.SystemName, true);
 				var processor = provider != null ? provider.Value as PayPalExpressProvider : null;
 				if (processor == null)
-					throw new SmartException("PayPal Express Checkout module cannot be loaded");
+					throw new SmartException(T("Plugins.CannotLoadModule", T("Plugins.FriendlyName.Payments.PayPalExpress")));
 
 				var processPaymentRequest = new PayPalProcessPaymentRequest();
 
@@ -265,9 +265,9 @@ public ActionResult GetDetails(string token)
 			var provider = PaymentService.LoadPaymentMethodBySystemName("Payments.PayPalExpress", true);
 			var processor = provider != null ? provider.Value as PayPalExpressProvider : null;
 			if (processor == null)
-				throw new SmartException("PayPal Express module cannot be loaded");
+                throw new SmartException(T("Plugins.CannotLoadModule", T("Plugins.FriendlyName.Payments.PayPalExpress")));
 
-			var resp = processor.GetExpressCheckoutDetails(token);
+            var resp = processor.GetExpressCheckoutDetails(token);
 
 			if (resp.Ack == AckCodeType.Success)
 			{

From 70416279f4f9b3c6151e04012c51d15bac576749 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Mon, 24 Sep 2018 15:23:29 +0200
Subject: [PATCH 03/71] Forum: Further limited to store checks necessary

---
 .../Forums/ForumService.cs                    |  19 +-
 .../Controllers/BoardsController.cs           | 219 +++++++-----------
 2 files changed, 103 insertions(+), 135 deletions(-)

diff --git a/src/Libraries/SmartStore.Services/Forums/ForumService.cs b/src/Libraries/SmartStore.Services/Forums/ForumService.cs
index ae0c3c1172..43a68f4f98 100644
--- a/src/Libraries/SmartStore.Services/Forums/ForumService.cs
+++ b/src/Libraries/SmartStore.Services/Forums/ForumService.cs
@@ -204,7 +204,11 @@ public virtual Forum GetForumById(int forumId)
                 return null;
             }
 
-            return _forumRepository.GetById(forumId);
+            var entity = _forumRepository.Table
+                .Expand(x => x.ForumGroup)
+                .FirstOrDefault(x => x.Id == forumId);
+
+            return entity;
         }
 
         public virtual IList<Forum> GetAllForumsByGroupId(int forumGroupId)
@@ -275,7 +279,11 @@ public virtual ForumTopic GetTopicById(int forumTopicId)
                 return null;
             }
 
-            var entity = _forumTopicRepository.Table.FirstOrDefault(x => x.Id == forumTopicId);
+            var entity = _forumTopicRepository.Table
+                .Expand(x => x.Forum)
+                .Expand(x => x.Forum.ForumGroup)
+                .FirstOrDefault(x => x.Id == forumTopicId);
+
             return entity;
         }
 
@@ -459,7 +467,12 @@ public virtual ForumPost GetPostById(int forumPostId)
                 return null;
             }
 
-            var forumPost = _forumPostRepository.Table.FirstOrDefault(x => x.Id == forumPostId);
+            var forumPost = _forumPostRepository.Table
+                .Expand(x => x.ForumTopic)
+                .Expand(x => x.ForumTopic.Forum)
+                .Expand(x => x.ForumTopic.Forum.ForumGroup)
+                .FirstOrDefault(x => x.Id == forumPostId);
+
             return forumPost;
         }
 
diff --git a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
index bdd2715e83..6da936f0e9 100644
--- a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
+++ b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
@@ -21,6 +21,7 @@
 using SmartStore.Services.Search.Modelling;
 using SmartStore.Services.Search.Rendering;
 using SmartStore.Services.Seo;
+using SmartStore.Services.Stores;
 using SmartStore.Utilities;
 using SmartStore.Web.Framework;
 using SmartStore.Web.Framework.Controllers;
@@ -41,6 +42,7 @@ public partial class BoardsController : PublicControllerBase
         private readonly ICountryService _countryService;
         private readonly IForumSearchService _forumSearchService;
         private readonly IGenericAttributeService _genericAttributeService;
+        private readonly IStoreMappingService _storeMappingService;
         private readonly ForumSettings _forumSettings;
         private readonly ForumSearchSettings _searchSettings;
         private readonly CustomerSettings _customerSettings;
@@ -57,6 +59,7 @@ public BoardsController(
             ICountryService countryService,
             IForumSearchService forumSearchService,
             IGenericAttributeService genericAttributeService,
+            IStoreMappingService storeMappingService,
             ForumSettings forumSettings,
             ForumSearchSettings searchSettings,
             CustomerSettings customerSettings,
@@ -72,6 +75,7 @@ public BoardsController(
             _countryService = countryService;
             _forumSearchService = forumSearchService;
             _genericAttributeService = genericAttributeService;
+            _storeMappingService = storeMappingService;
             _forumSettings = forumSettings;
             _searchSettings = searchSettings;
             _customerSettings = customerSettings;
@@ -337,7 +341,7 @@ public ActionResult ForumGroup(int id)
             }
 
             var forumGroup = _forumService.GetForumGroupById(id);
-            if (forumGroup == null)
+            if (forumGroup == null || !_storeMappingService.Authorize(forumGroup))
             {
                 return HttpNotFound();
             }
@@ -361,7 +365,7 @@ public ActionResult Forum(int id, int page = 1)
 
             var customer = Services.WorkContext.CurrentCustomer;
             var forum = _forumService.GetForumById(id);
-            if (forum == null)
+            if (forum == null || !_storeMappingService.Authorize(forum.ForumGroup))
             {
                 return HttpNotFound();
             }
@@ -439,12 +443,12 @@ public ActionResult ForumRss(int id = 0)
             }
 
 			var forum = _forumService.GetForumById(id);
-            if (forum == null)
+            if (forum == null || !_storeMappingService.Authorize(forum.ForumGroup))
             {
                 return new RssActionResult { Feed = feed };
             }
 
-			feed.Title = new TextSyndicationContent("{0} - {1}".FormatInvariant(store.Name, forum.GetLocalized(x => x.Name, language)));
+            feed.Title = new TextSyndicationContent("{0} - {1}".FormatInvariant(store.Name, forum.GetLocalized(x => x.Name, language)));
 
 			var items = new List<SyndicationItem>();
 			var topics = _forumService.GetAllTopics(id, 0, _forumSettings.ForumFeedCount);
@@ -473,12 +477,7 @@ public ActionResult ForumWatch(int id)
             var customer = Services.WorkContext.CurrentCustomer;
             var forum = _forumService.GetForumById(id);
 
-            if (forum == null)
-            {
-                return Json(new { Subscribed = subscribed, Text = returnText, Error = true });
-            }
-
-            if (!_forumService.IsCustomerAllowedToSubscribe(customer))
+            if (forum == null || !_storeMappingService.Authorize(forum.ForumGroup) || !_forumService.IsCustomerAllowedToSubscribe(customer))
             {
                 return Json(new { Subscribed = subscribed, Text = returnText, Error = true });
             }
@@ -638,6 +637,11 @@ public ActionResult Topic(int id, int page = 1)
 
             if (forumTopic != null)
             {
+                if (!_storeMappingService.Authorize(forumTopic.Forum.ForumGroup))
+                {
+                    return HttpNotFound();
+                }
+
                 var posts = _forumService.GetAllPosts(forumTopic.Id, 0, true, page - 1, _forumSettings.PostsPageSize);
 
                 // If no posts area loaded, redirect to the first page.
@@ -750,7 +754,7 @@ public ActionResult TopicWatch(int id)
                 return Json(new { Subscribed = subscribed, Text = returnText, Error = true });
             }
 
-            if (!_forumService.IsCustomerAllowedToSubscribe(customer))
+            if (!_storeMappingService.Authorize(forumTopic.Forum.ForumGroup) && !_forumService.IsCustomerAllowedToSubscribe(customer))
             {
                 return Json(new { Subscribed = subscribed, Text = returnText, Error = true });
             }
@@ -788,8 +792,7 @@ public ActionResult TopicMove(int id)
             }
 
             var forumTopic = _forumService.GetTopicById(id);
-
-            if (forumTopic == null)
+            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup))
             {
 				return HttpNotFound();
             }
@@ -810,13 +813,13 @@ public ActionResult TopicMove(TopicMoveModel model)
         {
             if (!_forumSettings.ForumsEnabled)
             {
-                return RedirectToRoute("HomePage");
+                return HttpNotFound();
             }
 
             var forumTopic = _forumService.GetTopicById(model.Id);
-            if (forumTopic == null)
+            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup))
             {
-                return RedirectToRoute("Boards");
+                return HttpNotFound();
             }
 
             var newForumId = model.ForumSelected;
@@ -840,12 +843,12 @@ public ActionResult TopicCreate(int id)
 
             var customer = Services.WorkContext.CurrentCustomer;
             var forum = _forumService.GetForumById(id);
-            if (forum == null)
+            if (forum == null || !_storeMappingService.Authorize(forum.ForumGroup))
             {
 				return HttpNotFound();
             }
 
-            if (_forumService.IsCustomerAllowedToCreateTopic(customer, forum) == false)
+            if (!_forumService.IsCustomerAllowedToCreateTopic(customer, forum))
             {
                 return new HttpUnauthorizedResult();
             }
@@ -886,7 +889,7 @@ public ActionResult TopicCreate(EditForumTopicModel model, bool captchaValid)
 
             var customer = Services.WorkContext.CurrentCustomer;
             var forum = _forumService.GetForumById(model.ForumId);
-            if (forum == null)
+            if (forum == null || !_storeMappingService.Authorize(forum.ForumGroup))
             {
                 return HttpNotFound();
             }
@@ -997,9 +1000,9 @@ public ActionResult TopicEdit(int id)
 
             var customer = Services.WorkContext.CurrentCustomer;
             var forumTopic = _forumService.GetTopicById(id);
-            if (forumTopic == null)
+            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup))
             {
-                return RedirectToRoute("Boards");
+                return HttpNotFound();
             }
 
             if (!_forumService.IsCustomerAllowedToEditTopic(customer, forumTopic))
@@ -1007,25 +1010,19 @@ public ActionResult TopicEdit(int id)
                 return new HttpUnauthorizedResult();
             }
 
-            var forum = forumTopic.Forum;
-            if (forum == null)
-            {
-                return RedirectToRoute("Boards");
-            }
-
 			var firstPost = forumTopic.GetFirstPost(_forumService);
             var model = new EditForumTopicModel();
 
             model.IsEdit = true;
             model.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnForumPage;
             model.TopicPriorities = ForumTopicTypesList();
-            model.ForumName = forum.GetLocalized(x => x.Name);
-            model.ForumSeName = forum.GetSeName();
+            model.ForumName = forumTopic.Forum.GetLocalized(x => x.Name);
+            model.ForumSeName = forumTopic.Forum.GetSeName();
             model.Text = firstPost.Text;
             model.Subject = forumTopic.Subject;
             model.TopicTypeId = forumTopic.TopicTypeId;
             model.Id = forumTopic.Id;
-            model.ForumId = forum.Id;
+            model.ForumId = forumTopic.Forum.Id;
             model.ForumEditor = _forumSettings.ForumEditor;
 
             model.IsCustomerAllowedToSetTopicPriority = _forumService.IsCustomerAllowedToSetTopicPriority(customer);
@@ -1038,7 +1035,7 @@ public ActionResult TopicEdit(int id)
                 model.Subscribed = forumSubscription != null;
             }
 
-			CreateForumBreadcrumb(forum: forum, topic: forumTopic);
+			CreateForumBreadcrumb(forum: forumTopic.Forum, topic: forumTopic);
 
 			return View(model);
         }
@@ -1060,15 +1057,10 @@ public ActionResult TopicEdit(EditForumTopicModel model, bool captchaValid)
 
             var customer = Services.WorkContext.CurrentCustomer;
             var forumTopic = _forumService.GetTopicById(model.Id);
-            if (forumTopic == null)
+            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup))
             {
                 return HttpNotFound();
             }
-            var forum = forumTopic.Forum;
-            if (forum == null)
-            {
-                return RedirectToRoute("Boards");
-            }
 
             if (ModelState.IsValid)
             {
@@ -1168,9 +1160,9 @@ public ActionResult TopicEdit(EditForumTopicModel model, bool captchaValid)
             model.TopicPriorities = ForumTopicTypesList();
             model.IsEdit = true;
             model.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnForumPage;
-            model.ForumName = forum.GetLocalized(x => x.Name);
-            model.ForumSeName = forum.GetSeName();
-            model.ForumId = forum.Id;
+            model.ForumName = forumTopic.Forum.GetLocalized(x => x.Name);
+            model.ForumSeName = forumTopic.Forum.GetSeName();
+            model.ForumId = forumTopic.Forum.Id;
             model.ForumEditor = _forumSettings.ForumEditor;
 
             model.IsCustomerAllowedToSetTopicPriority = _forumService.IsCustomerAllowedToSetTopicPriority(customer);
@@ -1187,21 +1179,22 @@ public ActionResult TopicDelete(int id)
             }
 
             var forumTopic = _forumService.GetTopicById(id);
-            if (forumTopic != null)
+            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup))
             {
-                if (!_forumService.IsCustomerAllowedToDeleteTopic(Services.WorkContext.CurrentCustomer, forumTopic))
-                {
-                    return new HttpUnauthorizedResult();
-                }
+                return HttpNotFound();
+            }
 
-                var forum = _forumService.GetForumById(forumTopic.ForumId);
+            if (!_forumService.IsCustomerAllowedToDeleteTopic(Services.WorkContext.CurrentCustomer, forumTopic))
+            {
+                return new HttpUnauthorizedResult();
+            }
 
-                _forumService.DeleteTopic(forumTopic);
+            var forum = _forumService.GetForumById(forumTopic.ForumId);
+            _forumService.DeleteTopic(forumTopic);
 
-                if (forum != null)
-                {
-                    return RedirectToRoute("ForumSlug", new { id = forum.Id, slug = forum.GetSeName() });
-                }
+            if (forum != null)
+            {
+                return RedirectToRoute("ForumSlug", new { id = forum.Id, slug = forum.GetSeName() });
             }
 
             return RedirectToRoute("Boards");
@@ -1221,9 +1214,9 @@ public ActionResult PostCreate(int id, int? quote)
 
             var customer = Services.WorkContext.CurrentCustomer;
             var forumTopic = _forumService.GetTopicById(id);
-            if (forumTopic == null)
+            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup))
             {
-                return RedirectToRoute("Boards");
+                return HttpNotFound();
             }
 
             if (!_forumService.IsCustomerAllowedToCreatePost(customer, forumTopic))
@@ -1231,12 +1224,6 @@ public ActionResult PostCreate(int id, int? quote)
                 return new HttpUnauthorizedResult();
             }
 
-            var forum = forumTopic.Forum;
-            if (forum == null)
-            {
-                return RedirectToRoute("Boards");
-            }
-
             var model = new EditForumPostModel
             {
                 Id = 0,
@@ -1244,7 +1231,7 @@ public ActionResult PostCreate(int id, int? quote)
                 IsEdit = false,
                 DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnForumPage,
                 ForumEditor = _forumSettings.ForumEditor,
-                ForumName = forum.GetLocalized(x => x.Name),
+                ForumName = forumTopic.Forum.GetLocalized(x => x.Name),
                 ForumTopicSubject = forumTopic.Subject,
                 ForumTopicSeName = forumTopic.GetSeName(),
                 IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer),
@@ -1270,18 +1257,17 @@ public ActionResult PostCreate(int id, int? quote)
                     switch (_forumSettings.ForumEditor)
                     {
                         case EditorType.SimpleTextBox:
-                            text = String.Format("{0}:\n{1}\n", quotePost.Customer.FormatUserName(), quotePostText);
+                            text = string.Format("{0}:\n{1}\n", quotePost.Customer.FormatUserName(), quotePostText);
                             break;
                         case EditorType.BBCodeEditor:
-                            text = String.Format("[quote={0}]{1}[/quote]", quotePost.Customer.FormatUserName(), BBCodeHelper.RemoveQuotes(quotePostText));
+                            text = string.Format("[quote={0}]{1}[/quote]", quotePost.Customer.FormatUserName(), BBCodeHelper.RemoveQuotes(quotePostText));
                             break;
                     }
                     model.Text = text;
                 }
             }
 
-			CreateForumBreadcrumb(forum: forum, topic: forumTopic);
-
+			CreateForumBreadcrumb(forum: forumTopic.Forum, topic: forumTopic);
 			return View(model);
         }
 
@@ -1303,7 +1289,7 @@ public ActionResult PostCreate(EditForumPostModel model, bool captchaValid)
 
             var customer = Services.WorkContext.CurrentCustomer;
             var forumTopic = _forumService.GetTopicById(model.ForumTopicId);
-            if (forumTopic == null)
+            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup))
             {
                 return HttpNotFound();
             }
@@ -1387,19 +1373,13 @@ public ActionResult PostCreate(EditForumPostModel model, bool captchaValid)
             }
 
             // Redisplay form.
-            var forum = forumTopic.Forum;
-            if (forum == null)
-            {
-                return RedirectToRoute("Boards");
-            }
-
+            model.Id = 0;
             model.IsEdit = false;
             model.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnForumPage;
-            model.ForumName = forum.GetLocalized(x => x.Name);
+            model.ForumName = forumTopic.Forum.GetLocalized(x => x.Name);
             model.ForumTopicId = forumTopic.Id;
             model.ForumTopicSubject = forumTopic.Subject;
             model.ForumTopicSeName = forumTopic.GetSeName();
-            model.Id = 0;
             model.IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer);
             model.ForumEditor = _forumSettings.ForumEditor;
             
@@ -1416,37 +1396,25 @@ public ActionResult PostEdit(int id)
             var customer = Services.WorkContext.CurrentCustomer;
             var forumPost = _forumService.GetPostById(id);
 
-            if (forumPost == null)
+            if (forumPost == null || !_storeMappingService.Authorize(forumPost.ForumTopic.Forum.ForumGroup))
             {
-                return RedirectToRoute("Boards");
+                return HttpNotFound();
             }
             if (!_forumService.IsCustomerAllowedToEditPost(customer, forumPost))
             {
                 return new HttpUnauthorizedResult();
             }
 
-            var forumTopic = forumPost.ForumTopic;
-            if (forumTopic == null)
-            {
-                return RedirectToRoute("Boards");
-            }
-
-            var forum = forumTopic.Forum;
-            if (forum == null)
-            {
-                return RedirectToRoute("Boards");
-            }
-
             var model = new EditForumPostModel
             {
                 Id = forumPost.Id,
-                ForumTopicId = forumTopic.Id,
                 IsEdit = true,
+                ForumTopicId = forumPost.ForumTopic.Id,
                 DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnForumPage,
                 ForumEditor = _forumSettings.ForumEditor,
-                ForumName = forum.GetLocalized(x => x.Name),
-                ForumTopicSubject = forumTopic.Subject,
-                ForumTopicSeName = forumTopic.GetSeName(),
+                ForumName = forumPost.ForumTopic.Forum.GetLocalized(x => x.Name),
+                ForumTopicSubject = forumPost.ForumTopic.Subject,
+                ForumTopicSeName = forumPost.ForumTopic.GetSeName(),
                 IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer),
                 Subscribed = false,
                 Text = forumPost.Text,
@@ -1455,11 +1423,11 @@ public ActionResult PostEdit(int id)
             // Subscription.
             if (model.IsCustomerAllowedToSubscribe)
             {
-                var forumSubscription = _forumService.GetAllSubscriptions(customer.Id, 0, forumTopic.Id, 0, 1).FirstOrDefault();
+                var forumSubscription = _forumService.GetAllSubscriptions(customer.Id, 0, forumPost.ForumTopic.Id, 0, 1).FirstOrDefault();
                 model.Subscribed = forumSubscription != null;
             }
 
-			CreateForumBreadcrumb(forum: forum, topic: forumTopic);
+			CreateForumBreadcrumb(forum: forumPost.ForumTopic.Forum, topic: forumPost.ForumTopic);
 
 			return View(model);
         }
@@ -1481,7 +1449,7 @@ public ActionResult PostEdit(EditForumPostModel model, bool captchaValid)
 
             var customer = Services.WorkContext.CurrentCustomer;
             var forumPost = _forumService.GetPostById(model.Id);
-            if (forumPost == null)
+            if (forumPost == null || !_storeMappingService.Authorize(forumPost.ForumTopic.Forum.ForumGroup))
             {
                 return HttpNotFound();
             }
@@ -1491,18 +1459,6 @@ public ActionResult PostEdit(EditForumPostModel model, bool captchaValid)
                 return new HttpUnauthorizedResult();
             }
 
-            var forumTopic = forumPost.ForumTopic;
-            if (forumTopic == null)
-            {
-                return RedirectToRoute("Boards");
-            }
-
-            var forum = forumTopic.Forum;
-            if (forum == null)
-            {
-                return RedirectToRoute("Boards");
-            }
-
             if (ModelState.IsValid)
             {
                 try
@@ -1571,10 +1527,10 @@ public ActionResult PostEdit(EditForumPostModel model, bool captchaValid)
             // Redisplay form.
             model.IsEdit = true;
             model.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnForumPage;
-            model.ForumName = forum.GetLocalized(x => x.Name);
-            model.ForumTopicId = forumTopic.Id;
-            model.ForumTopicSubject = forumTopic.Subject;
-            model.ForumTopicSeName = forumTopic.GetSeName();
+            model.ForumName = forumPost.ForumTopic.Forum.GetLocalized(x => x.Name);
+            model.ForumTopicId = forumPost.ForumTopic.Id;
+            model.ForumTopicSubject = forumPost.ForumTopic.Subject;
+            model.ForumTopicSeName = forumPost.ForumTopic.GetSeName();
             model.Id = forumPost.Id;
             model.IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer);
             model.ForumEditor = _forumSettings.ForumEditor;
@@ -1590,33 +1546,32 @@ public ActionResult PostDelete(int id)
             }
 
             var forumPost = _forumService.GetPostById(id);
-            if (forumPost != null)
+            if (forumPost == null || !_storeMappingService.Authorize(forumPost.ForumTopic.Forum.ForumGroup))
             {
-                if (!_forumService.IsCustomerAllowedToDeletePost(Services.WorkContext.CurrentCustomer, forumPost))
-                {
-                    return new HttpUnauthorizedResult();
-                }
+                return HttpNotFound();
+            }
 
-                var forumTopic = forumPost.ForumTopic;
-                var forumId = forumTopic.Forum.Id;
-                var forumSlug = forumTopic.Forum.GetSeName();
-                var url = string.Empty;
+            if (!_forumService.IsCustomerAllowedToDeletePost(Services.WorkContext.CurrentCustomer, forumPost))
+            {
+                return new HttpUnauthorizedResult();
+            }
 
-                _forumService.DeletePost(forumPost);
+            var forumTopic = forumPost.ForumTopic;
+            var forumId = forumTopic.Forum.Id;
+            var forumSlug = forumTopic.Forum.GetSeName();
 
-                // Get topic one more time because it can be deleted (first or only post deleted).
-                forumTopic = _forumService.GetTopicById(forumPost.TopicId);
-                if (forumTopic == null)
-                {
-                    return RedirectToRoute("ForumSlug", new { id = forumId, slug = forumSlug });
-                }
-                else
-                {
-                    return RedirectToRoute("TopicSlug", new { id = forumTopic.Id, slug = forumTopic.GetSeName() });
-                }
-            }
+            _forumService.DeletePost(forumPost);
 
-            return RedirectToRoute("Boards");
+            // Get topic one more time because it can be deleted (first or only post deleted).
+            forumTopic = _forumService.GetTopicById(forumPost.TopicId);
+            if (forumTopic == null)
+            {
+                return RedirectToRoute("ForumSlug", new { id = forumId, slug = forumSlug });
+            }
+            else
+            {
+                return RedirectToRoute("TopicSlug", new { id = forumTopic.Id, slug = forumTopic.GetSeName() });
+            }
         }
 
         #endregion

From a2d09752c0b75f45ae9e15cc457e4343dd0d44bd Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Mon, 24 Sep 2018 21:30:54 +0200
Subject: [PATCH 04/71] Admin theme: css grid layout & colors

---
 .../Administration/Content/_admin.scss        | 86 ++++++++-----------
 .../Administration/Content/_variables.scss    |  8 +-
 .../Scripts/admin.globalinit.js               | 40 +--------
 .../Views/Shared/Layouts/_AdminLayout.cshtml  | 69 ++++++++-------
 .../SmartStore.Web/Content/shared/_modal.scss |  9 +-
 5 files changed, 87 insertions(+), 125 deletions(-)

diff --git a/src/Presentation/SmartStore.Web/Administration/Content/_admin.scss b/src/Presentation/SmartStore.Web/Administration/Content/_admin.scss
index 8374987c71..a3fae78f39 100644
--- a/src/Presentation/SmartStore.Web/Administration/Content/_admin.scss
+++ b/src/Presentation/SmartStore.Web/Administration/Content/_admin.scss
@@ -103,44 +103,52 @@ body {
 	padding: 0;
 }
 
-header {
+.page-main {
+    display: grid;
+    grid-template-columns: 100%;
+    grid-template-rows: 72px 72px minmax(calc(100vh - 122px), auto);
+}
+
+#header {
 	@include gradient-bg($indigo);
-	padding-bottom: 50px;
+    grid-column: 1 / -1;
+    grid-row: 1 / span 2;
 
 	.popup & {
 		display: none;
 	}
 }
 
-.cph {
-   padding-top: 55px;
-}
-
 #content {
 	position: relative;
-	height: auto;
-	margin: 0 15px;
-	margin-top: -50px;
-	background-color: #fff;
+	margin: 0 ($content-padding-x / 2);
 	padding: $content-padding-y ($content-padding-x / 2);
 	padding-bottom: $content-padding-x * 2;
-	box-shadow: 0 0 6px rgba(0,0,0, 0.2);
-	border-top-left-radius: $border-radius;
-	border-top-right-radius: $border-radius;
+    box-shadow: 0 8px 16px rgba(#32325d, .1), 0 -2px 8px rgba(#000, .09);
+	border-radius: $border-radius-lg $border-radius-lg 0 0;
+    background-color: #fff;
+    grid-column: 1 / -1;
+    grid-row: 2 / -1;
 
 	@include media-breakpoint-up(lg) {
-		margin-left: 30px;
-		margin-right: 30px;
+		margin-left: $content-padding-x;
+		margin-right: $content-padding-x;
 		padding-left: $content-padding-x;
 		padding-right: $content-padding-x;
 	}
+
+    .popup & {
+	    margin: 0;
+	    border: 0;
+	    box-shadow: none;
+	    border-radius: 0;
+        grid-row: 1 / -1;
+    }
 }
 
-.popup #content {
-	margin: 0;
-	border: 0;
-	box-shadow: none;
-	border-radius: 0;
+.cph {
+    display: flex;
+    flex-flow: column;
 }
 
 .popup.bare {
@@ -155,28 +163,9 @@ header {
 	}
 }
 
-.section-title {
-	border-bottom: solid 3px $gray-300;
-	padding-bottom: 1px;
-	margin-bottom: 10px;
-	color: #009FFF;
-	font-size: 14px;
-	font-weight: 700;
-	vertical-align: bottom;
-}
-
-.section-title img {
-	vertical-align: middle;
-	padding-bottom: 2px;
-}
-
 .section-header {
-	position: absolute;
-	left: 0;
-	top: 0;
-	right: 0;
-	padding: 0.75rem ($content-padding-x / 2);
-	transition: background-color 0.1s ease-in-out, padding 0.1s ease-in-out;
+    padding-bottom: 0.75rem;
+	transition: background-color 0.1s ease-in-out;
 
 	@include make-row();
 	flex-wrap: nowrap;
@@ -255,6 +244,10 @@ header {
 		z-index: 600;
 		left: $content-padding-x / 2;
 		right: $content-padding-x / 2;
+        top: 0;
+		padding-left: $content-padding-x / 2;
+		padding-right: $content-padding-x / 2;
+        padding-top: $content-padding-y;
 		margin-left: 0 !important;
 		margin-right: 0 !important;
 		background: $gray-100;
@@ -265,16 +258,13 @@ header {
 			// add the killed scrollbar width
 			margin-right: 17px !important;
 		}
-	}
-
-	@include media-breakpoint-up(lg) {
-		padding-left: $content-padding-x;
-		padding-right: $content-padding-x;
 
-		&.sticky {
+	    @include media-breakpoint-up(lg) {
 			left: $content-padding-x;
 			right: $content-padding-x;
-		}
+            padding-left: $content-padding-x;
+		    padding-right: $content-padding-x;
+	    }
 	}
 }
 
diff --git a/src/Presentation/SmartStore.Web/Administration/Content/_variables.scss b/src/Presentation/SmartStore.Web/Administration/Content/_variables.scss
index 30b574cca2..cd940a8f7d 100644
--- a/src/Presentation/SmartStore.Web/Administration/Content/_variables.scss
+++ b/src/Presentation/SmartStore.Web/Administration/Content/_variables.scss
@@ -4,14 +4,14 @@
 // SmartStore CI colors
 // --------------------------------------------------
 
-$sm-orange1:	#ee9B00;
+$sm-orange1:	#f7a833;
 $sm-orange2:	#e77c00;
-$sm-green1:		#44b284;
+$sm-green1:		#009e74;
 $sm-bluegreen:	#2c8d8a;
 $sm-red1:		#ee1111;
 $sm-red2:		#dc3000;
 $sm-red3:		#db004f;
-$sm-blue:		#37a0e6;
+$sm-blue:		#307abe;
 $sm-blue2:		#18509f;
 $sm-violet:		#55237d;
 $sm-gray1:		#dadada;
@@ -92,7 +92,7 @@ $link-color:	desaturate(darken($primary, 12%), 0%); //#0277bb;
 $theme-color-interval:		8%;
 
 // The yiq lightness value that determines when the lightness of color changes from "dark" to "light". Acceptable values are between 0 and 255.
-$yiq-contrasted-threshold:	164;
+$yiq-contrasted-threshold:	179;
 
 // Customize the light and dark text colors for use in our YIQ color contrast function.
 $yiq-text-dark:				$gray-800;
diff --git a/src/Presentation/SmartStore.Web/Administration/Scripts/admin.globalinit.js b/src/Presentation/SmartStore.Web/Administration/Scripts/admin.globalinit.js
index 95770cb6f9..8707ff513b 100644
--- a/src/Presentation/SmartStore.Web/Administration/Scripts/admin.globalinit.js
+++ b/src/Presentation/SmartStore.Web/Administration/Scripts/admin.globalinit.js
@@ -123,7 +123,7 @@
 
         // sticky section-header
         var navbar = $("#navbar");
-        var navbarHeight = navbar.height() || 1;
+        var navbarHeight = navbar.height() || 0;
         var sectionHeader = $('.section-header');
         var sectionHeaderHasButtons = undefined;
 
@@ -132,50 +132,14 @@
                 sectionHeaderHasButtons = sectionHeader.find(".options").children().length > 0;
             }
             if (sectionHeaderHasButtons === true) {
-            	var y = $(this).scrollTop();
+                var y = $(this).scrollTop();
                 sectionHeader.toggleClass("sticky", y >= navbarHeight);
             }
         }).trigger('resize');
 
         $(window).on('load', function () {
-
         	// swap classes onload and domready
         	html.removeClass("loading").addClass("loaded");
-
-        	// make #content fit into viewspace
-        	var fitContentToWindow = function (initial) {
-        		var content = $('#content');
-
-        		if (!content.length)
-        			return;
-
-				var height = initialHeight = content.outerHeight(false),
-                             outerHeight,
-                             winHeight = $(window).height(),
-                             top,
-                             offset = 0;
-
-        		if (initial === true) {
-        			top = content.offset().top;
-					content
-						.data("initial-height", initialHeight)
-						.data("initial-offset", offset)
-						.data("initial-top", top);
-        		}
-        		else {
-        			top = content.data("initial-top");
-        			offset = content.data("initial-offset");
-        			initialHeight = content.data("initial-height");
-        		}
-
-				content.css("min-height", Math.max(initialHeight, winHeight - offset - top) + "px");
-			};
-
-			if (!$('body').is('.popup.bare')) {
-				fitContentToWindow(true);
-				$(window).on("resize", fitContentToWindow);
-			}
-
         });
 
     });
diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Shared/Layouts/_AdminLayout.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Shared/Layouts/_AdminLayout.cshtml
index f1cdda6cfa..02d4189516 100644
--- a/src/Presentation/SmartStore.Web/Administration/Views/Shared/Layouts/_AdminLayout.cshtml
+++ b/src/Presentation/SmartStore.Web/Administration/Views/Shared/Layouts/_AdminLayout.cshtml
@@ -33,42 +33,45 @@
 		</div>
     }
 	
-	@if (IsSectionDefined("header"))
-    {
-		@RenderSection("header")
-    }
-    else
-    {
-		<header>
-			@if (IsSectionDefined("navbar"))
-            {
-				@RenderSection("navbar")
-            }
-            else
-            {
-                Html.RenderWidget("admin_navbar_before");
-                Html.RenderAction("Navbar", "Common", new { area = "Admin" });
-                Html.RenderWidget("admin_navbar_after");
-            }
+	<div class="page-main">
+		@if (IsSectionDefined("header"))
+		{
+			@RenderSection("header")
+		}
+		else
+		{
+			<header id="header">
+				@if (IsSectionDefined("navbar"))
+				{
+					@RenderSection("navbar")
+				}
+				else
+				{
+					Html.RenderWidget("admin_navbar_before");
+					Html.RenderAction("Navbar", "Common", new { area = "Admin" });
+					Html.RenderWidget("admin_navbar_after");
+				}
 
-			<div id="breadcrumb">
-				<!-- SiteMapPath here-->
-				@{ Html.RenderWidget("admin_breadcrumb"); }
-			</div>
-		</header>		
-    }
+				<div id="breadcrumb">
+					<!-- SiteMapPath here-->
+					@{ Html.RenderWidget("admin_breadcrumb"); }
+				</div>
+			</header>		
+		}
 
-    @{ Html.RenderWidget("admin_content_before"); }
-    <div id="content">
-        <div class="cph">
-            @RenderBody()
-        </div>
-		<div id="ajax-busy">
-			<div class="bar"></div>
-			<div class="bar"></div>
-			<div class="bar"></div>
+		<div id="content">
+			<div class="cph">
+				@{ Html.RenderWidget("admin_content_before"); }
+				@RenderBody()
+			</div>
+			<div id="ajax-busy">
+				<div class="bar"></div>
+				<div class="bar"></div>
+				<div class="bar"></div>
+			</div>
 		</div>
-    </div>
+	</div>
+
 	@{ Html.RenderPartial("_Notifications"); }
     @{ Html.RenderWidget("admin_content_after"); }
 </div>
diff --git a/src/Presentation/SmartStore.Web/Content/shared/_modal.scss b/src/Presentation/SmartStore.Web/Content/shared/_modal.scss
index 3967dda953..76f57c64e1 100644
--- a/src/Presentation/SmartStore.Web/Content/shared/_modal.scss
+++ b/src/Presentation/SmartStore.Web/Content/shared/_modal.scss
@@ -33,8 +33,13 @@
 	min-height: 300px;
 }
 
-.modal-dialog-app > .modal-content > .modal-body {
-    padding: $border-radius 0;
+.modal-dialog-app > .modal-content {
+    border-radius: 0;
+
+    > .modal-body {
+        //padding: $border-radius 0;
+        padding: 0;
+    }
 }
 
 .modal-closer {

From 8039e3f02046e8172ed609194e96df9e8b851368 Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Tue, 25 Sep 2018 03:26:35 +0200
Subject: [PATCH 05/71] Theming: various css enhancements

---
 .../Extensions/HttpExtensions.cs              | 27 ++++++------
 .../Administration/Content/_admin.scss        |  7 ++-
 .../Scripts/admin.globalinit.js               |  2 +-
 .../Views/Shared/Layouts/_AdminLayout.cshtml  |  4 ++
 .../SmartStore.Web/Content/shared/_nav.scss   | 36 ++++++++++------
 .../Content/shared/_switch.scss               |  5 +++
 .../Shared/EditorTemplates/DateTime.cshtml    | 43 +++++++++++++------
 7 files changed, 78 insertions(+), 46 deletions(-)

diff --git a/src/Presentation/SmartStore.Web.Framework/Extensions/HttpExtensions.cs b/src/Presentation/SmartStore.Web.Framework/Extensions/HttpExtensions.cs
index 65b716686a..f3bdab1bfd 100644
--- a/src/Presentation/SmartStore.Web.Framework/Extensions/HttpExtensions.cs
+++ b/src/Presentation/SmartStore.Web.Framework/Extensions/HttpExtensions.cs
@@ -25,16 +25,17 @@ public static bool IsAdminArea(this HttpRequestBase request)
 		{
 			try
 			{
-				if (request != null)
+				// TODO: not really reliable. Change this.
+				var area = request?.RequestContext?.RouteData?.GetAreaName();
+				if (area != null)
 				{
-					var area = request.RequestContext.RouteData.GetAreaName();
-					if (area != null)
-					{
-						return area.IsCaseInsensitiveEqual("admin");
-					}
+					return area.IsCaseInsensitiveEqual("admin");
+				}
+				else
+				{
+					var paths = new[] { "~/administration/", "~/admin/" };
+					return paths.Any(x => request?.AppRelativeCurrentExecutionFilePath?.StartsWith(x, StringComparison.OrdinalIgnoreCase) == true);
 				}
-
-				return false;
 			}
 			catch
 			{
@@ -56,13 +57,9 @@ public static bool IsPublicArea(this HttpRequestBase request)
 		{
 			try
 			{
-				if (request != null)
-				{
-					var area = request.RequestContext.RouteData.GetAreaName();
-					return area.IsEmpty();
-				}
-
-				return false;
+				// TODO: not really reliable. Change this.
+				var area = request?.RequestContext?.RouteData?.GetAreaName();
+				return area.IsEmpty();
 			}
 			catch
 			{
diff --git a/src/Presentation/SmartStore.Web/Administration/Content/_admin.scss b/src/Presentation/SmartStore.Web/Administration/Content/_admin.scss
index a3fae78f39..6c00126382 100644
--- a/src/Presentation/SmartStore.Web/Administration/Content/_admin.scss
+++ b/src/Presentation/SmartStore.Web/Administration/Content/_admin.scss
@@ -104,6 +104,7 @@ body {
 }
 
 .page-main {
+    position: relative;
     display: grid;
     grid-template-columns: 100%;
     grid-template-rows: 72px 72px minmax(calc(100vh - 122px), auto);
@@ -129,6 +130,7 @@ body {
     background-color: #fff;
     grid-column: 1 / -1;
     grid-row: 2 / -1;
+    z-index: 9;
 
 	@include media-breakpoint-up(lg) {
 		margin-left: $content-padding-x;
@@ -147,6 +149,7 @@ body {
 }
 
 .cph {
+    position: relative;
     display: flex;
     flex-flow: column;
 }
@@ -268,7 +271,7 @@ body {
 	}
 }
 
-.popup .section-header.sticky {
+.popup .section-header.sticky { 
 	left: 0;
 	right: 0;
 	top: 0;
@@ -883,7 +886,7 @@ textarea:not([class*="form-control"]) {
 		font-family: $headings-font-family;
 		font-weight: $headings-font-weight;
 		color: inherit; 
-		border-bottom: 1px solid $gray-300;
+        border-bottom: 1px solid rgba(#000, 0.11);
 	}
 	.sub-title {
 		font-family: $font-family-base;
diff --git a/src/Presentation/SmartStore.Web/Administration/Scripts/admin.globalinit.js b/src/Presentation/SmartStore.Web/Administration/Scripts/admin.globalinit.js
index 8707ff513b..f5197676da 100644
--- a/src/Presentation/SmartStore.Web/Administration/Scripts/admin.globalinit.js
+++ b/src/Presentation/SmartStore.Web/Administration/Scripts/admin.globalinit.js
@@ -24,7 +24,7 @@
 		},
 		// switch
 		function (ctx) {
-			ctx.find(".adminData > input[type=checkbox], .multi-store-setting-control > input[type=checkbox]").each(function (i, el) {
+            ctx.find(".adminData > input[type=checkbox], .multi-store-setting-control > input[type=checkbox], .switcher > input[type=checkbox]").each(function (i, el) {
 				var wrap = $(el)
 					.wrap('<label class="switch"></label>')
 					.after('<span class="switch-toggle" data-on="' + window.Res['Common.On'] + '" data-off="' + window.Res['Common.Off'] + '"></span>');
diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Shared/Layouts/_AdminLayout.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Shared/Layouts/_AdminLayout.cshtml
index 02d4189516..bc76804f20 100644
--- a/src/Presentation/SmartStore.Web/Administration/Views/Shared/Layouts/_AdminLayout.cshtml
+++ b/src/Presentation/SmartStore.Web/Administration/Views/Shared/Layouts/_AdminLayout.cshtml
@@ -59,6 +59,8 @@
 			</header>		
 		}
 
+		@{ Html.RenderZone("beforemaincontent"); }
+
 		<div id="content">
 			<div class="cph">
 				@{ Html.RenderWidget("admin_content_before"); }
@@ -70,6 +72,8 @@
 				<div class="bar"></div>
 			</div>
 		</div>
+
+		@{ Html.RenderZone("aftermaincontent"); }
 	</div>
 
 	@{ Html.RenderPartial("_Notifications"); }
diff --git a/src/Presentation/SmartStore.Web/Content/shared/_nav.scss b/src/Presentation/SmartStore.Web/Content/shared/_nav.scss
index 8a0ee8756d..722feee46c 100644
--- a/src/Presentation/SmartStore.Web/Content/shared/_nav.scss
+++ b/src/Presentation/SmartStore.Web/Content/shared/_nav.scss
@@ -72,6 +72,28 @@
 		}
 	}
 
+    &.nav-inverse .nav-link {
+        color: rgba($yiq-text-light, 0.4);
+
+		&:hover {
+			color: rgba($yiq-text-light, 0.75);
+		}
+
+		&:hover:not(.active) {
+			background-color: rgba(#fff, 0.08);
+		}
+
+		&:active:not(.active) {
+            color: $yiq-text-light;
+			background-color: rgba(#fff, 0.16);
+		}
+
+		&.active {
+            background-color: transparent;
+			color: $yiq-text-light;
+		}
+    }
+
 	.nav-link:not(.disabled):before {
 		position: absolute;
 		content: '';
@@ -152,20 +174,6 @@
 	}
 }
 
-@include media-breakpoint-up(lg) {
-	/*.nav-aside {
-		flex: 0 0 auto;
-		width: auto;
-		max-width: none;
-	}
-
-	.nav-content {
-		flex-basis: 0;
-		flex-grow: 1;
-		max-width: 100%;
-	}*/
-}
-
 
 // Responsive Tabs
 // ==============================================================
diff --git a/src/Presentation/SmartStore.Web/Content/shared/_switch.scss b/src/Presentation/SmartStore.Web/Content/shared/_switch.scss
index 76464ea941..eb8733c11d 100644
--- a/src/Presentation/SmartStore.Web/Content/shared/_switch.scss
+++ b/src/Presentation/SmartStore.Web/Content/shared/_switch.scss
@@ -7,6 +7,7 @@
 
 .switch {
 	$h: $font-size-base * $line-height-base;
+    $h-sm: $font-size-sm * $line-height-sm;
 	position: relative;
 	display: inline-block;
 	vertical-align: bottom;
@@ -16,6 +17,10 @@
 	box-sizing: content-box;
 	height: $h;
 
+    .switcher-sm > & {
+        height: $h-sm;
+    }
+
 	> .switch-toggle {
 		position: relative;
 		display: inline-block;
diff --git a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/DateTime.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/DateTime.cshtml
index 32a351d72d..61a236c6db 100644
--- a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/DateTime.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/DateTime.cshtml
@@ -1,17 +1,17 @@
 @functions{   
-    private DateTime? Value
-    {
-        get
-        {
-            DateTime? value = null;
-            if (ViewData.Model != null)
-            {
-                value = Convert.ToDateTime(ViewData.Model, System.Globalization.CultureInfo.CurrentCulture);
-            }
-            return value;
-        }
-    }
-	
+	private DateTime? Value
+	{
+		get
+		{
+			DateTime? value = null;
+			if (ViewData.Model != null)
+			{
+				value = Convert.ToDateTime(ViewData.Model, System.Globalization.CultureInfo.CurrentCulture);
+			}
+			return value;
+		}
+	}
+
 	private bool PickTime
 	{
 		get
@@ -29,6 +29,21 @@
 			return false;
 		}
 	}
+
+	private string CssClass
+	{
+		get
+		{
+			var cls = "input-group date datetimepicker-group";
+
+			if (ViewData.ContainsKey("size"))
+			{
+				cls += " input-group input-group-" + ViewData["size"].Convert<string>();
+			}
+
+			return cls;
+		}
+	}
 }
 
 @{
@@ -41,7 +56,7 @@
     }
 }
 
-<div class="input-group date datetimepicker-group" id="@id-parent" data-date="@value" data-target-input="nearest">
+<div class="@CssClass" id="@id-parent" data-date="@value" data-target-input="nearest">
     @Html.TextBox("", value, new { @class = "form-control datetimepicker-input", data_target = "#" + id + "-parent", data_format = format })
 	<div class="input-group-append input-group-addon" data-target="#@(id)-parent" data-toggle="datetimepicker">
 		<span class="input-group-text"><i class="fa fa-calendar"></i></span>

From 522ec887ca25d374b81774f42d34e95a4841f39c Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Tue, 25 Sep 2018 11:05:09 +0200
Subject: [PATCH 06/71] Resolves #417 Restrict forum groups to specific
 customer roles

---
 changelog.md                                  |   4 +-
 .../Domain/Forums/ForumGroup.cs               |   8 +-
 .../201809241947314_ForumGroupAcl.Designer.cs |  29 ++++
 .../201809241947314_ForumGroupAcl.cs          |  18 +++
 .../201809241947314_ForumGroupAcl.resx        | 126 ++++++++++++++++++
 .../SmartStore.Data/SmartStore.Data.csproj    |   7 +
 .../Forums/ForumService.cs                    |  62 +++++++--
 .../Forums/IForumService.cs                   |   6 +-
 .../Controllers/ForumController.cs            |  59 +++++---
 .../Models/Forums/ForumGroupModel.cs          |   7 +-
 .../Forum/_CreateOrUpdateForumGroup.cshtml    |  12 +-
 .../Controllers/BoardsController.cs           | 116 ++++++++--------
 12 files changed, 362 insertions(+), 92 deletions(-)
 create mode 100644 src/Libraries/SmartStore.Data/Migrations/201809241947314_ForumGroupAcl.Designer.cs
 create mode 100644 src/Libraries/SmartStore.Data/Migrations/201809241947314_ForumGroupAcl.cs
 create mode 100644 src/Libraries/SmartStore.Data/Migrations/201809241947314_ForumGroupAcl.resx

diff --git a/changelog.md b/changelog.md
index 6de6f5b983..7da2864c7c 100644
--- a/changelog.md
+++ b/changelog.md
@@ -15,7 +15,9 @@
 * Added option to display preview pictures in product lists
 * Added option to add multiple file versions to product download section
 * Added options for alternating price display (in badges)
-* Added option to display a captcha on forum pages when creating or replying to a topic.
+* **Forum**:
+	* Added option to display a captcha on forum pages when creating or replying to a topic.
+	* #417 Restrict forum groups to specific customer roles.
 * **MegaSearch**:
 	* Supports searching for forum posts.
 	* #1172 Option to display related search terms on search page.
diff --git a/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs b/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs
index d68dceb19c..7974973f45 100644
--- a/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs
+++ b/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs
@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using SmartStore.Core.Domain.Localization;
+using SmartStore.Core.Domain.Security;
 using SmartStore.Core.Domain.Seo;
 using SmartStore.Core.Domain.Stores;
 
@@ -9,7 +10,7 @@ namespace SmartStore.Core.Domain.Forums
     /// <summary>
     /// Represents a forum group
     /// </summary>
-	public partial class ForumGroup : BaseEntity, IAuditable, IStoreMappingSupported, ILocalizedEntity, ISlugSupported
+	public partial class ForumGroup : BaseEntity, IAuditable, IStoreMappingSupported, IAclSupported, ILocalizedEntity, ISlugSupported
     {
         private ICollection<Forum> _forums;
 
@@ -43,6 +44,11 @@ public partial class ForumGroup : BaseEntity, IAuditable, IStoreMappingSupported
 		/// </summary>
 		public bool LimitedToStores { get; set; }
 
+        /// <summary>
+        /// Gets or sets a value indicating whether the entity is subject to ACL
+        /// </summary>
+        public bool SubjectToAcl { get; set; }
+
         /// <summary>
         /// Gets or sets the collection of Forums
         /// </summary>
diff --git a/src/Libraries/SmartStore.Data/Migrations/201809241947314_ForumGroupAcl.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201809241947314_ForumGroupAcl.Designer.cs
new file mode 100644
index 0000000000..5d82777a3a
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201809241947314_ForumGroupAcl.Designer.cs
@@ -0,0 +1,29 @@
+// <auto-generated />
+namespace SmartStore.Data.Migrations
+{
+    using System.CodeDom.Compiler;
+    using System.Data.Entity.Migrations;
+    using System.Data.Entity.Migrations.Infrastructure;
+    using System.Resources;
+    
+    [GeneratedCode("EntityFramework.Migrations", "6.2.0-61023")]
+    public sealed partial class ForumGroupAcl : IMigrationMetadata
+    {
+        private readonly ResourceManager Resources = new ResourceManager(typeof(ForumGroupAcl));
+        
+        string IMigrationMetadata.Id
+        {
+            get { return "201809241947314_ForumGroupAcl"; }
+        }
+        
+        string IMigrationMetadata.Source
+        {
+            get { return null; }
+        }
+        
+        string IMigrationMetadata.Target
+        {
+            get { return Resources.GetString("Target"); }
+        }
+    }
+}
diff --git a/src/Libraries/SmartStore.Data/Migrations/201809241947314_ForumGroupAcl.cs b/src/Libraries/SmartStore.Data/Migrations/201809241947314_ForumGroupAcl.cs
new file mode 100644
index 0000000000..25876305cd
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201809241947314_ForumGroupAcl.cs
@@ -0,0 +1,18 @@
+namespace SmartStore.Data.Migrations
+{
+    using System;
+    using System.Data.Entity.Migrations;
+    
+    public partial class ForumGroupAcl : DbMigration
+    {
+        public override void Up()
+        {
+            AddColumn("dbo.Forums_Group", "SubjectToAcl", c => c.Boolean(nullable: false));
+        }
+        
+        public override void Down()
+        {
+            DropColumn("dbo.Forums_Group", "SubjectToAcl");
+        }
+    }
+}
diff --git a/src/Libraries/SmartStore.Data/Migrations/201809241947314_ForumGroupAcl.resx b/src/Libraries/SmartStore.Data/Migrations/201809241947314_ForumGroupAcl.resx
new file mode 100644
index 0000000000..43f5701c1e
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201809241947314_ForumGroupAcl.resx
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="Target" xml:space="preserve">
+    <value>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</value>
+  </data>
+  <data name="DefaultSchema" xml:space="preserve">
+    <value>dbo</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj
index 5f527da1fb..364baeac00 100644
--- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj
+++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj
@@ -623,6 +623,10 @@
     <Compile Include="Migrations\201809171309522_NewsletterSubscriptionLanguage.Designer.cs">
       <DependentUpon>201809171309522_NewsletterSubscriptionLanguage.cs</DependentUpon>
     </Compile>
+    <Compile Include="Migrations\201809241947314_ForumGroupAcl.cs" />
+    <Compile Include="Migrations\201809241947314_ForumGroupAcl.Designer.cs">
+      <DependentUpon>201809241947314_ForumGroupAcl.cs</DependentUpon>
+    </Compile>
     <Compile Include="ObjectContextBase.SaveChanges.cs" />
     <Compile Include="Setup\Builder\ActivityLogTypeMigrator.cs" />
     <Compile Include="Setup\Builder\PermissionMigrator.cs" />
@@ -1120,6 +1124,9 @@
     <EmbeddedResource Include="Migrations\201809171309522_NewsletterSubscriptionLanguage.resx">
       <DependentUpon>201809171309522_NewsletterSubscriptionLanguage.cs</DependentUpon>
     </EmbeddedResource>
+    <EmbeddedResource Include="Migrations\201809241947314_ForumGroupAcl.resx">
+      <DependentUpon>201809241947314_ForumGroupAcl.cs</DependentUpon>
+    </EmbeddedResource>
     <EmbeddedResource Include="Sql\Indexes.sql" />
     <EmbeddedResource Include="Sql\StoredProcedures.sql" />
   </ItemGroup>
diff --git a/src/Libraries/SmartStore.Services/Forums/ForumService.cs b/src/Libraries/SmartStore.Services/Forums/ForumService.cs
index 43a68f4f98..0ae5e99e30 100644
--- a/src/Libraries/SmartStore.Services/Forums/ForumService.cs
+++ b/src/Libraries/SmartStore.Services/Forums/ForumService.cs
@@ -4,6 +4,7 @@
 using SmartStore.Core.Data;
 using SmartStore.Core.Domain.Customers;
 using SmartStore.Core.Domain.Forums;
+using SmartStore.Core.Domain.Security;
 using SmartStore.Core.Domain.Stores;
 using SmartStore.Data.Caching;
 using SmartStore.Services.Common;
@@ -19,6 +20,7 @@ public partial class ForumService : IForumService
         private readonly IRepository<ForumPost> _forumPostRepository;
         private readonly IRepository<PrivateMessage> _forumPrivateMessageRepository;
         private readonly IRepository<ForumSubscription> _forumSubscriptionRepository;
+        private readonly IRepository<AclRecord> _aclRepository;
         private readonly ForumSettings _forumSettings;
         private readonly IRepository<Customer> _customerRepository;
         private readonly IGenericAttributeService _genericAttributeService;
@@ -33,6 +35,7 @@ public ForumService(
             IRepository<ForumPost> forumPostRepository,
             IRepository<PrivateMessage> forumPrivateMessageRepository,
             IRepository<ForumSubscription> forumSubscriptionRepository,
+            IRepository<AclRecord> aclRepository,
             ForumSettings forumSettings,
             IRepository<Customer> customerRepository,
             IGenericAttributeService genericAttributeService,
@@ -46,6 +49,7 @@ public ForumService(
             _forumPostRepository = forumPostRepository;
             _forumPrivateMessageRepository = forumPrivateMessageRepository;
             _forumSubscriptionRepository = forumSubscriptionRepository;
+            _aclRepository = aclRepository;
             _forumSettings = forumSettings;
             _customerRepository = customerRepository;
             _genericAttributeService = genericAttributeService;
@@ -146,8 +150,9 @@ public virtual ForumGroup GetForumGroupById(int forumGroupId)
             return _forumGroupRepository.GetById(forumGroupId);
         }
 
-        public virtual IList<ForumGroup> GetAllForumGroups(int storeId = 0)
+        public virtual IList<ForumGroup> GetAllForumGroups(int storeId = 0, bool showHidden = false)
         {
+            var joinApplied = false;
             var query = _forumGroupRepository.Table.Expand(x => x.Forums);
 
             if (!QuerySettings.IgnoreMultiStore && storeId > 0)
@@ -159,6 +164,25 @@ from sm in fg_sm.DefaultIfEmpty()
                     where !fg.LimitedToStores || storeId == sm.StoreId
                     select fg;
 
+                joinApplied = true;
+            }
+
+            if (!showHidden && !QuerySettings.IgnoreAcl)
+            {
+                var allowedCustomerRolesIds = _services.WorkContext.CurrentCustomer.CustomerRoles.Where(x => x.Active).Select(x => x.Id).ToList();
+
+                query = 
+                    from fg in query
+                    join a in _aclRepository.Table on new { a1 = fg.Id, a2 = "ForumGroup" } equals new { a1 = a.EntityId, a2 = a.EntityName } into fg_acl
+                    from a in fg_acl.DefaultIfEmpty()
+                    where !fg.SubjectToAcl || allowedCustomerRolesIds.Contains(a.CustomerRoleId)
+                    select fg;
+
+                joinApplied = true;
+            }
+
+            if (joinApplied)
+            {
                 query =
                     from fg in query
                     group fg by fg.Id into fgGroup
@@ -317,8 +341,9 @@ public virtual IPagedList<ForumTopic> GetAllTopics(int forumId, int pageIndex, i
             return topics;
         }
 
-        public virtual IList<ForumTopic> GetActiveTopics(int forumId, int count)
+        public virtual IList<ForumTopic> GetActiveTopics(int forumId, int count, bool showHidden = false)
         {
+            var joinApplied = false;
             var query =
 				from ft in _forumTopicRepository.Table
 				where (forumId == 0 || ft.ForumId == forumId) && (ft.LastPostTime.HasValue)
@@ -337,14 +362,35 @@ from sm in fg_sm.DefaultIfEmpty()
 					where !fg.LimitedToStores || currentStoreId == sm.StoreId
 					select ft;
 
-				query =
-					from ft in query
-					group ft by ft.Id into ftGroup
-					orderby ftGroup.Key
-					select ftGroup.FirstOrDefault();
+                joinApplied = true;
 			}
 
-			query = query.OrderByDescending(x => x.LastPostTime);
+            if (!showHidden && !QuerySettings.IgnoreAcl)
+            {
+                var allowedCustomerRolesIds = _services.WorkContext.CurrentCustomer.CustomerRoles.Where(x => x.Active).Select(x => x.Id).ToList();
+
+                query =
+                    from ft in query
+                    join ff in _forumRepository.Table on ft.ForumId equals ff.Id
+                    join fg in _forumGroupRepository.Table on ff.ForumGroupId equals fg.Id
+                    join a in _aclRepository.Table on new { a1 = fg.Id, a2 = "ForumGroup" } equals new { a1 = a.EntityId, a2 = a.EntityName } into fg_acl
+                    from a in fg_acl.DefaultIfEmpty()
+                    where !fg.SubjectToAcl || allowedCustomerRolesIds.Contains(a.CustomerRoleId)
+                    select ft;
+
+                joinApplied = true;
+            }
+
+            if (joinApplied)
+            {
+                query =
+                    from ft in query
+                    group ft by ft.Id into ftGroup
+                    orderby ftGroup.Key
+                    select ftGroup.FirstOrDefault();
+            }
+
+            query = query.OrderByDescending(x => x.LastPostTime);
 
             var forumTopics = query.Take(count).ToList();
             return forumTopics;
diff --git a/src/Libraries/SmartStore.Services/Forums/IForumService.cs b/src/Libraries/SmartStore.Services/Forums/IForumService.cs
index cf743e3411..ed991c0c8d 100644
--- a/src/Libraries/SmartStore.Services/Forums/IForumService.cs
+++ b/src/Libraries/SmartStore.Services/Forums/IForumService.cs
@@ -23,8 +23,9 @@ public partial interface IForumService
         /// Gets all forum groups
         /// </summary>
         /// <param name="storeId">Store identifier</param>
+        /// <param name="showHidden">Whether to load hidden records</param>
         /// <returns>Forum groups</returns>
-		IList<ForumGroup> GetAllForumGroups(int storeId = 0);
+		IList<ForumGroup> GetAllForumGroups(int storeId = 0, bool showHidden = false);
 
         /// <summary>
         /// Deletes a forum group
@@ -112,8 +113,9 @@ public partial interface IForumService
         /// </summary>
         /// <param name="forumId">The forum identifier</param>
         /// <param name="topicCount">Count of forum topics to return</param>
+        /// <param name="showHidden">Whether to load hidden records</param>
         /// <returns>Forum Topics</returns>
-        IList<ForumTopic> GetActiveTopics(int forumId, int topicCount);
+        IList<ForumTopic> GetActiveTopics(int forumId, int topicCount, bool showHidden = false);
 
         /// <summary>
         /// Deletes a forum topic
diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs
index d418935457..67e19c99db 100644
--- a/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs
+++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ForumController.cs
@@ -4,16 +4,17 @@
 using SmartStore.Admin.Models.Forums;
 using SmartStore.Core.Domain.Forums;
 using SmartStore.Services;
+using SmartStore.Services.Customers;
 using SmartStore.Services.Forums;
 using SmartStore.Services.Helpers;
 using SmartStore.Services.Localization;
 using SmartStore.Services.Security;
 using SmartStore.Services.Seo;
 using SmartStore.Services.Stores;
+using SmartStore.Web.Framework;
 using SmartStore.Web.Framework.Controllers;
 using SmartStore.Web.Framework.Filters;
 using SmartStore.Web.Framework.Security;
-using SmartStore.Web.Framework;
 
 namespace SmartStore.Admin.Controllers
 {
@@ -22,27 +23,34 @@ public class ForumController : AdminControllerBase
     {
         private readonly IForumService _forumService;
 		private readonly ICommonServices _services;
-        private readonly IDateTimeHelper _dateTimeHelper;
 		private readonly IStoreMappingService _storeMappingService;
-		private readonly ILanguageService _languageService;
+        private readonly IAclService _aclService;
+        private readonly ICustomerService _customerService;
+        private readonly ILanguageService _languageService;
 		private readonly ILocalizedEntityService _localizedEntityService;
 		private readonly IUrlRecordService _urlRecordService;
+        private readonly IDateTimeHelper _dateTimeHelper;
 
-        public ForumController(IForumService forumService,
+        public ForumController(
+            IForumService forumService,
 			ICommonServices services,
-            IDateTimeHelper dateTimeHelper,
-			IStoreMappingService storeMappingService,
+            IStoreMappingService storeMappingService,
+            IAclService aclService,
+            ICustomerService customerService,
 			ILanguageService languageService,
 			ILocalizedEntityService localizedEntityService,
-			IUrlRecordService urlRecordService)
+			IUrlRecordService urlRecordService,
+            IDateTimeHelper dateTimeHelper)
         {
             _forumService = forumService;
 			_services = services;
-            _dateTimeHelper = dateTimeHelper;
 			_storeMappingService = storeMappingService;
+            _aclService = aclService;
+            _customerService = customerService;
 			_languageService = languageService;
 			_localizedEntityService = localizedEntityService;
 			_urlRecordService = urlRecordService;
+            _dateTimeHelper = dateTimeHelper;
         }
 
 		#region Utilities
@@ -62,10 +70,13 @@ private void PrepareForumGroupModel(ForumGroupModel model, ForumGroup forumGroup
 			if (!excludeProperties)
 			{
 				model.SelectedStoreIds = _storeMappingService.GetStoresIdsWithAccess(forumGroup);
-			}
+                model.SelectedCustomerRoleIds = _aclService.GetCustomerRoleIdsWithAccess(forumGroup);
+            }
 
 			model.AvailableStores = allStores.ToSelectListItems(model.SelectedStoreIds);
-			ViewBag.StoreCount = allStores.Count;
+            model.AvailableCustomerRoles = _customerService.GetAllCustomerRoles(true).ToSelectListItems(model.SelectedCustomerRoleIds);
+
+            ViewBag.StoreCount = allStores.Count;
 		}
 
 		[NonAction]
@@ -108,7 +119,7 @@ public ActionResult List()
             if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageForums))
                 return AccessDeniedView();
 
-            var forumGroupsModel = _forumService.GetAllForumGroups(0)
+            var forumGroupsModel = _forumService.GetAllForumGroups(0, true)
                 .Select(fg =>
                 {
                     var forumGroupModel = fg.ToModel();
@@ -151,7 +162,9 @@ public ActionResult CreateForumGroup()
         public ActionResult CreateForumGroup(ForumGroupModel model, bool continueEditing)
         {
             if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageForums))
+            {
                 return AccessDeniedView();
+            }
 
             if (ModelState.IsValid)
             {
@@ -165,14 +178,14 @@ public ActionResult CreateForumGroup(ForumGroupModel model, bool continueEditing
 				UpdateLocales(model, forumGroup);
 
 				SaveStoreMappings(forumGroup, model);
+                SaveAclMappings(forumGroup, model);
 
-                NotifySuccess(_services.Localization.GetResource("Admin.ContentManagement.Forums.ForumGroup.Added"));
+                NotifySuccess(T("Admin.ContentManagement.Forums.ForumGroup.Added"));
 
                 return continueEditing ? RedirectToAction("EditForumGroup", new { forumGroup.Id }) : RedirectToAction("List");
             }
 
-            //If we got this far, something failed, redisplay form
-
+            // If we got this far, something failed, redisplay form.
 			PrepareForumGroupModel(model, null, true);
 
             return View(model);
@@ -187,7 +200,7 @@ public ActionResult CreateForum()
 
 			AddLocales(_languageService, model.Locales);
 
-            foreach (var forumGroup in _forumService.GetAllForumGroups())
+            foreach (var forumGroup in _forumService.GetAllForumGroups(0, true))
             {
                 var forumGroupModel = forumGroup.ToModel();
                 model.ForumGroups.Add(forumGroupModel);
@@ -218,7 +231,7 @@ public ActionResult CreateForum(ForumModel model, bool continueEditing)
             }
 
             //If we got this far, something failed, redisplay form
-            foreach (var forumGroup in _forumService.GetAllForumGroups())
+            foreach (var forumGroup in _forumService.GetAllForumGroups(0, true))
             {
                 var forumGroupModel = forumGroup.ToModel();
                 model.ForumGroups.Add(forumGroupModel);
@@ -257,11 +270,15 @@ public ActionResult EditForumGroup(int id)
         public ActionResult EditForumGroup(ForumGroupModel model, bool continueEditing)
         {
             if (!_services.Permissions.Authorize(StandardPermissionProvider.ManageForums))
+            {
                 return AccessDeniedView();
+            }
 
             var forumGroup = _forumService.GetForumGroupById(model.Id);
             if (forumGroup == null)
+            {
                 return RedirectToAction("List");
+            }
 
             if (ModelState.IsValid)
             {
@@ -275,14 +292,14 @@ public ActionResult EditForumGroup(ForumGroupModel model, bool continueEditing)
 				UpdateLocales(model, forumGroup);
 
 				SaveStoreMappings(forumGroup, model);
+                SaveAclMappings(forumGroup, model);
 
-                NotifySuccess(_services.Localization.GetResource("Admin.ContentManagement.Forums.ForumGroup.Updated"));
+                NotifySuccess(T("Admin.ContentManagement.Forums.ForumGroup.Updated"));
 
                 return continueEditing ? RedirectToAction("EditForumGroup", forumGroup.Id) : RedirectToAction("List");
             }
 
-            //If we got this far, something failed, redisplay form
-
+            // If we got this far, something failed, redisplay form.
 			PrepareForumGroupModel(model, forumGroup, true);
 
             return View(model);
@@ -306,7 +323,7 @@ public ActionResult EditForum(int id)
 				locale.SeName = forum.GetSeName(languageId, false, false);
 			});
 
-            foreach (var forumGroup in _forumService.GetAllForumGroups(0))
+            foreach (var forumGroup in _forumService.GetAllForumGroups(0, true))
             {
                 var forumGroupModel = forumGroup.ToModel();
                 model.ForumGroups.Add(forumGroupModel);
@@ -341,7 +358,7 @@ public ActionResult EditForum(ForumModel model, bool continueEditing)
             }
 
             //If we got this far, something failed, redisplay form
-            foreach (var forumGroup in _forumService.GetAllForumGroups())
+            foreach (var forumGroup in _forumService.GetAllForumGroups(0, true))
             {
                 var forumGroupModel = forumGroup.ToModel();
                 model.ForumGroups.Add(forumGroupModel);
diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumGroupModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumGroupModel.cs
index 44d1646cd5..361c0d951a 100644
--- a/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumGroupModel.cs
+++ b/src/Presentation/SmartStore.Web/Administration/Models/Forums/ForumGroupModel.cs
@@ -10,7 +10,7 @@
 namespace SmartStore.Admin.Models.Forums
 {
     [Validator(typeof(ForumGroupValidator))]
-	public class ForumGroupModel : EntityModelBase, ILocalizedModel<ForumGroupLocalizedModel>, IStoreSelector
+	public class ForumGroupModel : EntityModelBase, ILocalizedModel<ForumGroupLocalizedModel>, IStoreSelector, IAclSelector
     {
         public ForumGroupModel()
         {
@@ -41,8 +41,11 @@ public ForumGroupModel()
 		public IEnumerable<SelectListItem> AvailableStores { get; set; }
 		public int[] SelectedStoreIds { get; set; }
 
-		public IList<ForumModel> ForumModels { get; set; }
+        public bool SubjectToAcl { get; set; }
+        public IEnumerable<SelectListItem> AvailableCustomerRoles { get; set; }
+        public int[] SelectedCustomerRoleIds { get; set; }
 
+        public IList<ForumModel> ForumModels { get; set; }
 		public IList<ForumGroupLocalizedModel> Locales { get; set; }
     }
 
diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForumGroup.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForumGroup.cshtml
index b8776317ee..2c248f2077 100644
--- a/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForumGroup.cshtml
+++ b/src/Presentation/SmartStore.Web/Administration/Views/Forum/_CreateOrUpdateForumGroup.cshtml
@@ -1,6 +1,5 @@
-@model ForumGroupModel
-
-@using Telerik.Web.Mvc.UI;
+@using Telerik.Web.Mvc.UI;
+@model ForumGroupModel
 
 @Html.ValidationSummary(true)
 @Html.HiddenFor(model => model.Id)
@@ -8,9 +7,9 @@
 @Html.SmartStore().TabStrip().Name("forumgroup-edit").Style(TabsStyle.Material).Items(x =>
 {
 	x.Add().Text(T("Admin.Common.General").Text).Content(TabInfo()).Selected(true);
+    x.Add().Text(T("Admin.Catalog.Categories.Acl").Text).Content(TabAcl());
 	x.Add().Text(T("Admin.Common.Stores").Text).Content(TabStores());
 
-	//generate an event
 	EngineContext.Current.Resolve<IEventPublisher>().Publish(new TabStripCreated(x, "forumgroup-edit", this.Html, this.Model));
 })
 
@@ -98,6 +97,11 @@
 	</table>
 }
 
+@helper TabAcl()
+{
+	@Html.Partial("AclSelector", Model)
+}
+
 @helper TabStores()
 {
 	@Html.Partial("StoreSelector", Model)
diff --git a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
index 6da936f0e9..a6310b4388 100644
--- a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
+++ b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
@@ -20,6 +20,7 @@
 using SmartStore.Services.Search;
 using SmartStore.Services.Search.Modelling;
 using SmartStore.Services.Search.Rendering;
+using SmartStore.Services.Security;
 using SmartStore.Services.Seo;
 using SmartStore.Services.Stores;
 using SmartStore.Utilities;
@@ -43,6 +44,7 @@ public partial class BoardsController : PublicControllerBase
         private readonly IForumSearchService _forumSearchService;
         private readonly IGenericAttributeService _genericAttributeService;
         private readonly IStoreMappingService _storeMappingService;
+        private readonly IAclService _aclService;
         private readonly ForumSettings _forumSettings;
         private readonly ForumSearchSettings _searchSettings;
         private readonly CustomerSettings _customerSettings;
@@ -60,6 +62,7 @@ public BoardsController(
             IForumSearchService forumSearchService,
             IGenericAttributeService genericAttributeService,
             IStoreMappingService storeMappingService,
+            IAclService aclService,
             ForumSettings forumSettings,
             ForumSearchSettings searchSettings,
             CustomerSettings customerSettings,
@@ -76,6 +79,7 @@ public BoardsController(
             _forumSearchService = forumSearchService;
             _genericAttributeService = genericAttributeService;
             _storeMappingService = storeMappingService;
+            _aclService = aclService;
             _forumSettings = forumSettings;
             _searchSettings = searchSettings;
             _customerSettings = customerSettings;
@@ -341,7 +345,7 @@ public ActionResult ForumGroup(int id)
             }
 
             var forumGroup = _forumService.GetForumGroupById(id);
-            if (forumGroup == null || !_storeMappingService.Authorize(forumGroup))
+            if (forumGroup == null || !_storeMappingService.Authorize(forumGroup) || !_aclService.Authorize(forumGroup))
             {
                 return HttpNotFound();
             }
@@ -365,7 +369,7 @@ public ActionResult Forum(int id, int page = 1)
 
             var customer = Services.WorkContext.CurrentCustomer;
             var forum = _forumService.GetForumById(id);
-            if (forum == null || !_storeMappingService.Authorize(forum.ForumGroup))
+            if (forum == null || !_storeMappingService.Authorize(forum.ForumGroup) || !_aclService.Authorize(forum.ForumGroup))
             {
                 return HttpNotFound();
             }
@@ -443,7 +447,7 @@ public ActionResult ForumRss(int id = 0)
             }
 
 			var forum = _forumService.GetForumById(id);
-            if (forum == null || !_storeMappingService.Authorize(forum.ForumGroup))
+            if (forum == null || !_storeMappingService.Authorize(forum.ForumGroup) || !_aclService.Authorize(forum.ForumGroup))
             {
                 return new RssActionResult { Feed = feed };
             }
@@ -477,7 +481,10 @@ public ActionResult ForumWatch(int id)
             var customer = Services.WorkContext.CurrentCustomer;
             var forum = _forumService.GetForumById(id);
 
-            if (forum == null || !_storeMappingService.Authorize(forum.ForumGroup) || !_forumService.IsCustomerAllowedToSubscribe(customer))
+            if (forum == null || 
+                !_storeMappingService.Authorize(forum.ForumGroup) ||
+                !_aclService.Authorize(forum.ForumGroup) ||
+                !_forumService.IsCustomerAllowedToSubscribe(customer))
             {
                 return Json(new { Subscribed = subscribed, Text = returnText, Error = true });
             }
@@ -637,7 +644,7 @@ public ActionResult Topic(int id, int page = 1)
 
             if (forumTopic != null)
             {
-                if (!_storeMappingService.Authorize(forumTopic.Forum.ForumGroup))
+                if (!_storeMappingService.Authorize(forumTopic.Forum.ForumGroup) || !_aclService.Authorize(forumTopic.Forum.ForumGroup))
                 {
                     return HttpNotFound();
                 }
@@ -754,7 +761,9 @@ public ActionResult TopicWatch(int id)
                 return Json(new { Subscribed = subscribed, Text = returnText, Error = true });
             }
 
-            if (!_storeMappingService.Authorize(forumTopic.Forum.ForumGroup) && !_forumService.IsCustomerAllowedToSubscribe(customer))
+            if (!_storeMappingService.Authorize(forumTopic.Forum.ForumGroup) ||
+                !_aclService.Authorize(forumTopic.Forum.ForumGroup) ||
+                !_forumService.IsCustomerAllowedToSubscribe(customer))
             {
                 return Json(new { Subscribed = subscribed, Text = returnText, Error = true });
             }
@@ -792,7 +801,7 @@ public ActionResult TopicMove(int id)
             }
 
             var forumTopic = _forumService.GetTopicById(id);
-            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup))
+            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup) || !_aclService.Authorize(forumTopic.Forum.ForumGroup))
             {
 				return HttpNotFound();
             }
@@ -817,7 +826,7 @@ public ActionResult TopicMove(TopicMoveModel model)
             }
 
             var forumTopic = _forumService.GetTopicById(model.Id);
-            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup))
+            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup) || !_aclService.Authorize(forumTopic.Forum.ForumGroup))
             {
                 return HttpNotFound();
             }
@@ -843,7 +852,7 @@ public ActionResult TopicCreate(int id)
 
             var customer = Services.WorkContext.CurrentCustomer;
             var forum = _forumService.GetForumById(id);
-            if (forum == null || !_storeMappingService.Authorize(forum.ForumGroup))
+            if (forum == null || !_storeMappingService.Authorize(forum.ForumGroup) || !_aclService.Authorize(forum.ForumGroup))
             {
 				return HttpNotFound();
             }
@@ -882,27 +891,27 @@ public ActionResult TopicCreate(EditForumTopicModel model, bool captchaValid)
 				return HttpNotFound();
             }
 
-            if (_captchaSettings.Enabled && _captchaSettings.ShowOnForumPage && !captchaValid)
-            {
-                ModelState.AddModelError("", T("Common.WrongCaptcha"));
-            }
-
             var customer = Services.WorkContext.CurrentCustomer;
             var forum = _forumService.GetForumById(model.ForumId);
-            if (forum == null || !_storeMappingService.Authorize(forum.ForumGroup))
+            if (forum == null || !_storeMappingService.Authorize(forum.ForumGroup) || !_aclService.Authorize(forum.ForumGroup))
             {
                 return HttpNotFound();
             }
 
+            if (!_forumService.IsCustomerAllowedToCreateTopic(customer, forum))
+            {
+                return new HttpUnauthorizedResult();
+            }
+
+            if (_captchaSettings.Enabled && _captchaSettings.ShowOnForumPage && !captchaValid)
+            {
+                ModelState.AddModelError("", T("Common.WrongCaptcha"));
+            }
+
             if (ModelState.IsValid)
             {
                 try
                 {
-                    if (!_forumService.IsCustomerAllowedToCreateTopic(customer, forum))
-                    {
-                        return new HttpUnauthorizedResult();
-                    }
-
                     var subject = model.Subject;
                     var maxSubjectLength = _forumSettings.TopicSubjectMaxLength;
                     if (maxSubjectLength > 0 && subject.Length > maxSubjectLength)
@@ -1000,7 +1009,7 @@ public ActionResult TopicEdit(int id)
 
             var customer = Services.WorkContext.CurrentCustomer;
             var forumTopic = _forumService.GetTopicById(id);
-            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup))
+            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup) || !_aclService.Authorize(forumTopic.Forum.ForumGroup))
             {
                 return HttpNotFound();
             }
@@ -1050,27 +1059,27 @@ public ActionResult TopicEdit(EditForumTopicModel model, bool captchaValid)
 				return HttpNotFound();
             }
 
-            if (_captchaSettings.Enabled && _captchaSettings.ShowOnForumPage && !captchaValid)
-            {
-                ModelState.AddModelError("", T("Common.WrongCaptcha"));
-            }
-
             var customer = Services.WorkContext.CurrentCustomer;
             var forumTopic = _forumService.GetTopicById(model.Id);
-            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup))
+            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup) || !_aclService.Authorize(forumTopic.Forum.ForumGroup))
             {
                 return HttpNotFound();
             }
 
+            if (!_forumService.IsCustomerAllowedToEditTopic(customer, forumTopic))
+            {
+                return new HttpUnauthorizedResult();
+            }
+
+            if (_captchaSettings.Enabled && _captchaSettings.ShowOnForumPage && !captchaValid)
+            {
+                ModelState.AddModelError("", T("Common.WrongCaptcha"));
+            }
+
             if (ModelState.IsValid)
             {
                 try
                 {
-                    if (!_forumService.IsCustomerAllowedToEditTopic(customer, forumTopic))
-                    {
-                        return new HttpUnauthorizedResult();
-                    }
-
                     var subject = model.Subject;
                     var maxSubjectLength = _forumSettings.TopicSubjectMaxLength;
                     if (maxSubjectLength > 0 && subject.Length > maxSubjectLength)
@@ -1179,7 +1188,7 @@ public ActionResult TopicDelete(int id)
             }
 
             var forumTopic = _forumService.GetTopicById(id);
-            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup))
+            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup) || !_aclService.Authorize(forumTopic.Forum.ForumGroup))
             {
                 return HttpNotFound();
             }
@@ -1214,7 +1223,7 @@ public ActionResult PostCreate(int id, int? quote)
 
             var customer = Services.WorkContext.CurrentCustomer;
             var forumTopic = _forumService.GetTopicById(id);
-            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup))
+            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup) || !_aclService.Authorize(forumTopic.Forum.ForumGroup))
             {
                 return HttpNotFound();
             }
@@ -1282,27 +1291,27 @@ public ActionResult PostCreate(EditForumPostModel model, bool captchaValid)
 				return HttpNotFound();
             }
 
-            if (_captchaSettings.Enabled && _captchaSettings.ShowOnForumPage && !captchaValid)
-            {
-                ModelState.AddModelError("", T("Common.WrongCaptcha"));
-            }
-
             var customer = Services.WorkContext.CurrentCustomer;
             var forumTopic = _forumService.GetTopicById(model.ForumTopicId);
-            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup))
+            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup) || !_aclService.Authorize(forumTopic.Forum.ForumGroup))
             {
                 return HttpNotFound();
             }
 
+            if (!_forumService.IsCustomerAllowedToCreatePost(customer, forumTopic))
+            {
+                return new HttpUnauthorizedResult();
+            }
+
+            if (_captchaSettings.Enabled && _captchaSettings.ShowOnForumPage && !captchaValid)
+            {
+                ModelState.AddModelError("", T("Common.WrongCaptcha"));
+            }
+
             if (ModelState.IsValid)
             {
                 try
                 {
-                    if (!_forumService.IsCustomerAllowedToCreatePost(customer, forumTopic))
-                    {
-                        return new HttpUnauthorizedResult();
-                    }
-
                     var text = model.Text;
                     var maxPostLength = _forumSettings.PostMaxLength;
                     if (maxPostLength > 0 && text.Length > maxPostLength)
@@ -1396,10 +1405,11 @@ public ActionResult PostEdit(int id)
             var customer = Services.WorkContext.CurrentCustomer;
             var forumPost = _forumService.GetPostById(id);
 
-            if (forumPost == null || !_storeMappingService.Authorize(forumPost.ForumTopic.Forum.ForumGroup))
+            if (forumPost == null || !_storeMappingService.Authorize(forumPost.ForumTopic.Forum.ForumGroup) || !_aclService.Authorize(forumPost.ForumTopic.Forum.ForumGroup))
             {
                 return HttpNotFound();
             }
+
             if (!_forumService.IsCustomerAllowedToEditPost(customer, forumPost))
             {
                 return new HttpUnauthorizedResult();
@@ -1442,14 +1452,9 @@ public ActionResult PostEdit(EditForumPostModel model, bool captchaValid)
 				return HttpNotFound();
             }
 
-            if (_captchaSettings.Enabled && _captchaSettings.ShowOnForumPage && !captchaValid)
-            {
-                ModelState.AddModelError("", T("Common.WrongCaptcha"));
-            }
-
             var customer = Services.WorkContext.CurrentCustomer;
             var forumPost = _forumService.GetPostById(model.Id);
-            if (forumPost == null || !_storeMappingService.Authorize(forumPost.ForumTopic.Forum.ForumGroup))
+            if (forumPost == null || !_storeMappingService.Authorize(forumPost.ForumTopic.Forum.ForumGroup) || !_aclService.Authorize(forumPost.ForumTopic.Forum.ForumGroup))
             {
                 return HttpNotFound();
             }
@@ -1459,6 +1464,11 @@ public ActionResult PostEdit(EditForumPostModel model, bool captchaValid)
                 return new HttpUnauthorizedResult();
             }
 
+            if (_captchaSettings.Enabled && _captchaSettings.ShowOnForumPage && !captchaValid)
+            {
+                ModelState.AddModelError("", T("Common.WrongCaptcha"));
+            }
+
             if (ModelState.IsValid)
             {
                 try
@@ -1546,7 +1556,7 @@ public ActionResult PostDelete(int id)
             }
 
             var forumPost = _forumService.GetPostById(id);
-            if (forumPost == null || !_storeMappingService.Authorize(forumPost.ForumTopic.Forum.ForumGroup))
+            if (forumPost == null || !_storeMappingService.Authorize(forumPost.ForumTopic.Forum.ForumGroup) || !_aclService.Authorize(forumPost.ForumTopic.Forum.ForumGroup))
             {
                 return HttpNotFound();
             }

From db1dfb8fec47acb79ee6be55f753130647678e12 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Tue, 25 Sep 2018 13:03:51 +0200
Subject: [PATCH 07/71] Integrate ACL of forum groups in forum search

---
 .../Forums/ForumService.cs                    |  6 ++--
 .../Search/Forum/ForumSearchQuery.cs          | 28 +++++++++++++++++
 .../Search/Forum/LinqForumSearchService.cs    | 30 +++++++++++++++++++
 .../Modelling/ForumSearchQueryFactory.cs      |  3 ++
 4 files changed, 64 insertions(+), 3 deletions(-)

diff --git a/src/Libraries/SmartStore.Services/Forums/ForumService.cs b/src/Libraries/SmartStore.Services/Forums/ForumService.cs
index 0ae5e99e30..80f0dea995 100644
--- a/src/Libraries/SmartStore.Services/Forums/ForumService.cs
+++ b/src/Libraries/SmartStore.Services/Forums/ForumService.cs
@@ -20,12 +20,12 @@ public partial class ForumService : IForumService
         private readonly IRepository<ForumPost> _forumPostRepository;
         private readonly IRepository<PrivateMessage> _forumPrivateMessageRepository;
         private readonly IRepository<ForumSubscription> _forumSubscriptionRepository;
+        private readonly IRepository<StoreMapping> _storeMappingRepository;
         private readonly IRepository<AclRecord> _aclRepository;
         private readonly ForumSettings _forumSettings;
         private readonly IRepository<Customer> _customerRepository;
         private readonly IGenericAttributeService _genericAttributeService;
         private readonly ICustomerService _customerService;
-		private readonly IRepository<StoreMapping> _storeMappingRepository;
 		private readonly ICommonServices _services;
 
         public ForumService(
@@ -35,12 +35,12 @@ public ForumService(
             IRepository<ForumPost> forumPostRepository,
             IRepository<PrivateMessage> forumPrivateMessageRepository,
             IRepository<ForumSubscription> forumSubscriptionRepository,
+            IRepository<StoreMapping> storeMappingRepository,
             IRepository<AclRecord> aclRepository,
             ForumSettings forumSettings,
             IRepository<Customer> customerRepository,
             IGenericAttributeService genericAttributeService,
             ICustomerService customerService,
-			IRepository<StoreMapping> storeMappingRepository,
 			ICommonServices services)
         {
             _forumGroupRepository = forumGroupRepository;
@@ -49,12 +49,12 @@ public ForumService(
             _forumPostRepository = forumPostRepository;
             _forumPrivateMessageRepository = forumPrivateMessageRepository;
             _forumSubscriptionRepository = forumSubscriptionRepository;
+            _storeMappingRepository = storeMappingRepository;
             _aclRepository = aclRepository;
             _forumSettings = forumSettings;
             _customerRepository = customerRepository;
             _genericAttributeService = genericAttributeService;
             _customerService = customerService;
-			_storeMappingRepository = storeMappingRepository;
 			_services = services;
         }
 
diff --git a/src/Libraries/SmartStore.Services/Search/Forum/ForumSearchQuery.cs b/src/Libraries/SmartStore.Services/Search/Forum/ForumSearchQuery.cs
index a6b761cec1..1e964bad84 100644
--- a/src/Libraries/SmartStore.Services/Search/Forum/ForumSearchQuery.cs
+++ b/src/Libraries/SmartStore.Services/Search/Forum/ForumSearchQuery.cs
@@ -1,5 +1,6 @@
 using System;
 using System.Linq;
+using SmartStore.Core.Domain.Customers;
 using SmartStore.Core.Domain.Forums;
 using SmartStore.Core.Search;
 
@@ -65,6 +66,33 @@ public ForumSearchQuery SortBy(ForumTopicSorting sort)
             }
         }
 
+        public ForumSearchQuery VisibleOnly(Customer customer)
+        {
+            if (customer != null)
+            {
+                var allowedCustomerRoleIds = customer.CustomerRoles.Where(x => x.Active).Select(x => x.Id).ToArray();
+
+                return VisibleOnly(allowedCustomerRoleIds);
+            }
+
+            return VisibleOnly(new int[0]);
+        }
+
+        public ForumSearchQuery VisibleOnly(params int[] allowedCustomerRoleIds)
+        {
+            if (allowedCustomerRoleIds != null && allowedCustomerRoleIds.Length > 0)
+            {
+                var roleIds = allowedCustomerRoleIds.Where(x => x != 0).Distinct().ToList();
+                if (roleIds.Any())
+                {
+                    roleIds.Insert(0, 0);
+                    WithFilter(SearchFilter.Combined(roleIds.Select(x => SearchFilter.ByField("roleid", x).ExactMatch().NotAnalyzed()).ToArray()));
+                }
+            }
+
+            return this;
+        }
+
         public override ForumSearchQuery HasStoreId(int id)
         {
             base.HasStoreId(id);
diff --git a/src/Libraries/SmartStore.Services/Search/Forum/LinqForumSearchService.cs b/src/Libraries/SmartStore.Services/Search/Forum/LinqForumSearchService.cs
index 970a5566f8..917221d3b5 100644
--- a/src/Libraries/SmartStore.Services/Search/Forum/LinqForumSearchService.cs
+++ b/src/Libraries/SmartStore.Services/Search/Forum/LinqForumSearchService.cs
@@ -4,6 +4,7 @@
 using SmartStore.Core.Data;
 using SmartStore.Core.Domain.Customers;
 using SmartStore.Core.Domain.Forums;
+using SmartStore.Core.Domain.Security;
 using SmartStore.Core.Domain.Stores;
 using SmartStore.Core.Localization;
 using SmartStore.Core.Search;
@@ -18,20 +19,32 @@ namespace SmartStore.Services.Search
     public partial class LinqForumSearchService : SearchServiceBase, IForumSearchService
     {
         private readonly IRepository<ForumPost> _forumPostRepository;
+        private readonly IRepository<ForumTopic> _forumTopicRepository;
+        private readonly IRepository<Forum> _forumRepository;
+        private readonly IRepository<ForumGroup> _forumGroupRepository;
         private readonly IRepository<StoreMapping> _storeMappingRepository;
+        private readonly IRepository<AclRecord> _aclRepository;
         private readonly IForumService _forumService;
         private readonly ICommonServices _services;
         private readonly CustomerSettings _customerSettings;
 
         public LinqForumSearchService(
             IRepository<ForumPost> forumPostRepository,
+            IRepository<ForumTopic> forumTopicRepository,
+            IRepository<Forum> forumRepository,
+            IRepository<ForumGroup> forumGroupRepository,
             IRepository<StoreMapping> storeMappingRepository,
+            IRepository<AclRecord> aclRepository,
             IForumService forumService,
             ICommonServices services,
             CustomerSettings customerSettings)
 		{
             _forumPostRepository = forumPostRepository;
+            _forumTopicRepository = forumTopicRepository;
+            _forumRepository = forumRepository;
+            _forumGroupRepository = forumGroupRepository;
             _storeMappingRepository = storeMappingRepository;
+            _aclRepository = aclRepository;
             _forumService = forumService;
 			_services = services;
             _customerSettings = customerSettings;
@@ -85,6 +98,23 @@ protected virtual IQueryable<ForumPost> GetPostQuery(ForumSearchQuery searchQuer
             // Filters.
             FlattenFilters(searchQuery.Filters, filters);
 
+            if (!QuerySettings.IgnoreAcl)
+            {
+                var roleIds = GetIdList(filters, "roleid");
+                if (roleIds.Any())
+                {
+                    query =
+                        from fp in query
+                        join ft in _forumTopicRepository.TableUntracked on fp.TopicId equals ft.Id
+                        join ff in _forumRepository.Table on ft.ForumId equals ff.Id
+                        join fg in _forumGroupRepository.Table on ff.ForumGroupId equals fg.Id
+                        join a in _aclRepository.Table on new { a1 = fg.Id, a2 = "ForumGroup" } equals new { a1 = a.EntityId, a2 = a.EntityName } into fg_acl
+                        from a in fg_acl.DefaultIfEmpty()
+                        where !fg.SubjectToAcl || roleIds.Contains(a.CustomerRoleId)
+                        select fp;
+                }
+            }
+
             foreach (IAttributeSearchFilter filter in filters)
             {
                 var rangeFilter = filter as IRangeSearchFilter;
diff --git a/src/Libraries/SmartStore.Services/Search/Forum/Modelling/ForumSearchQueryFactory.cs b/src/Libraries/SmartStore.Services/Search/Forum/Modelling/ForumSearchQueryFactory.cs
index 50918174c6..f5b2d7960a 100644
--- a/src/Libraries/SmartStore.Services/Search/Forum/Modelling/ForumSearchQueryFactory.cs
+++ b/src/Libraries/SmartStore.Services/Search/Forum/Modelling/ForumSearchQueryFactory.cs
@@ -83,6 +83,9 @@ public ForumSearchQuery CreateFromQuery()
                 .WithCurrency(_services.WorkContext.WorkingCurrency)
                 .BuildFacetMap(!isInstantSearch);
 
+            // Visibility.
+            query.VisibleOnly(!QuerySettings.IgnoreAcl ? _services.WorkContext.CurrentCustomer : null);
+
             // Store.
             if (!QuerySettings.IgnoreMultiStore)
             {

From d3f80fe68cfa33018a590826ba326bb8246890f2 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Tue, 25 Sep 2018 15:06:06 +0200
Subject: [PATCH 08/71] Please execute "update-database -TargetMigration
 NewsletterSubscriptionLanguage"

---
 .../Domain/Forums/ForumPost.cs                |   5 +
 .../Domain/Forums/ForumTopic.cs               |   5 +
 .../201809241947314_ForumGroupAcl.resx        | 126 ------------------
 ...201809251233170_ForumGroupAcl.Designer.cs} |   2 +-
 ...cl.cs => 201809251233170_ForumGroupAcl.cs} |   4 +
 .../201809251233170_ForumGroupAcl.resx        | 126 ++++++++++++++++++
 .../SmartStore.Data/SmartStore.Data.csproj    |  10 +-
 .../Controllers/BoardsController.cs           |   8 +-
 .../Forums/ForumPostPersistenceTests.cs       |   2 +
 .../ForumSubscriptionPersistenceTests.cs      |   2 +
 .../Forums/ForumTopicPersistenceTests.cs      |   1 +
 11 files changed, 157 insertions(+), 134 deletions(-)
 delete mode 100644 src/Libraries/SmartStore.Data/Migrations/201809241947314_ForumGroupAcl.resx
 rename src/Libraries/SmartStore.Data/Migrations/{201809241947314_ForumGroupAcl.Designer.cs => 201809251233170_ForumGroupAcl.Designer.cs} (92%)
 rename src/Libraries/SmartStore.Data/Migrations/{201809241947314_ForumGroupAcl.cs => 201809251233170_ForumGroupAcl.cs} (57%)
 create mode 100644 src/Libraries/SmartStore.Data/Migrations/201809251233170_ForumGroupAcl.resx

diff --git a/src/Libraries/SmartStore.Core/Domain/Forums/ForumPost.cs b/src/Libraries/SmartStore.Core/Domain/Forums/ForumPost.cs
index 087c6205a2..2cfecbfe97 100644
--- a/src/Libraries/SmartStore.Core/Domain/Forums/ForumPost.cs
+++ b/src/Libraries/SmartStore.Core/Domain/Forums/ForumPost.cs
@@ -38,6 +38,11 @@ public partial class ForumPost : BaseEntity, IAuditable
         /// </summary>
         public DateTime UpdatedOnUtc { get; set; }
 
+        /// <summary>
+        /// Gets or sets a value indicating whether the entity is published
+        /// </summary>
+        public bool Published { get; set; }
+
         /// <summary>
         /// Gets the topic
         /// </summary>
diff --git a/src/Libraries/SmartStore.Core/Domain/Forums/ForumTopic.cs b/src/Libraries/SmartStore.Core/Domain/Forums/ForumTopic.cs
index 4b30ac9b02..b77c216592 100644
--- a/src/Libraries/SmartStore.Core/Domain/Forums/ForumTopic.cs
+++ b/src/Libraries/SmartStore.Core/Domain/Forums/ForumTopic.cs
@@ -69,6 +69,11 @@ public partial class ForumTopic : BaseEntity, IAuditable
         /// </summary>
         public DateTime UpdatedOnUtc { get; set; }
 
+        /// <summary>
+        /// Gets or sets a value indicating whether the entity is published
+        /// </summary>
+        public bool Published { get; set; }
+
         /// <summary>
         /// Gets or sets the forum topic type
         /// </summary>
diff --git a/src/Libraries/SmartStore.Data/Migrations/201809241947314_ForumGroupAcl.resx b/src/Libraries/SmartStore.Data/Migrations/201809241947314_ForumGroupAcl.resx
deleted file mode 100644
index 43f5701c1e..0000000000
--- a/src/Libraries/SmartStore.Data/Migrations/201809241947314_ForumGroupAcl.resx
+++ /dev/null
@@ -1,126 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<root>
-  <!-- 
-    Microsoft ResX Schema 
-    
-    Version 2.0
-    
-    The primary goals of this format is to allow a simple XML format 
-    that is mostly human readable. The generation and parsing of the 
-    various data types are done through the TypeConverter classes 
-    associated with the data types.
-    
-    Example:
-    
-    ... ado.net/XML headers & schema ...
-    <resheader name="resmimetype">text/microsoft-resx</resheader>
-    <resheader name="version">2.0</resheader>
-    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
-    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
-    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
-    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
-    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
-        <value>[base64 mime encoded serialized .NET Framework object]</value>
-    </data>
-    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
-        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
-        <comment>This is a comment</comment>
-    </data>
-                
-    There are any number of "resheader" rows that contain simple 
-    name/value pairs.
-    
-    Each data row contains a name, and value. The row also contains a 
-    type or mimetype. Type corresponds to a .NET class that support 
-    text/value conversion through the TypeConverter architecture. 
-    Classes that don't support this are serialized and stored with the 
-    mimetype set.
-    
-    The mimetype is used for serialized objects, and tells the 
-    ResXResourceReader how to depersist the object. This is currently not 
-    extensible. For a given mimetype the value must be set accordingly:
-    
-    Note - application/x-microsoft.net.object.binary.base64 is the format 
-    that the ResXResourceWriter will generate, however the reader can 
-    read any of the formats listed below.
-    
-    mimetype: application/x-microsoft.net.object.binary.base64
-    value   : The object must be serialized with 
-            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
-            : and then encoded with base64 encoding.
-    
-    mimetype: application/x-microsoft.net.object.soap.base64
-    value   : The object must be serialized with 
-            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
-            : and then encoded with base64 encoding.
-
-    mimetype: application/x-microsoft.net.object.bytearray.base64
-    value   : The object must be serialized into a byte array 
-            : using a System.ComponentModel.TypeConverter
-            : and then encoded with base64 encoding.
-    -->
-  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
-    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
-    <xsd:element name="root" msdata:IsDataSet="true">
-      <xsd:complexType>
-        <xsd:choice maxOccurs="unbounded">
-          <xsd:element name="metadata">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" />
-              </xsd:sequence>
-              <xsd:attribute name="name" use="required" type="xsd:string" />
-              <xsd:attribute name="type" type="xsd:string" />
-              <xsd:attribute name="mimetype" type="xsd:string" />
-              <xsd:attribute ref="xml:space" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="assembly">
-            <xsd:complexType>
-              <xsd:attribute name="alias" type="xsd:string" />
-              <xsd:attribute name="name" type="xsd:string" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="data">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
-                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
-              </xsd:sequence>
-              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
-              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
-              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
-              <xsd:attribute ref="xml:space" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="resheader">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
-              </xsd:sequence>
-              <xsd:attribute name="name" type="xsd:string" use="required" />
-            </xsd:complexType>
-          </xsd:element>
-        </xsd:choice>
-      </xsd:complexType>
-    </xsd:element>
-  </xsd:schema>
-  <resheader name="resmimetype">
-    <value>text/microsoft-resx</value>
-  </resheader>
-  <resheader name="version">
-    <value>2.0</value>
-  </resheader>
-  <resheader name="reader">
-    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </resheader>
-  <resheader name="writer">
-    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </resheader>
-  <data name="Target" xml:space="preserve">
-    <value>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</value>
-  </data>
-  <data name="DefaultSchema" xml:space="preserve">
-    <value>dbo</value>
-  </data>
-</root>
\ No newline at end of file
diff --git a/src/Libraries/SmartStore.Data/Migrations/201809241947314_ForumGroupAcl.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201809251233170_ForumGroupAcl.Designer.cs
similarity index 92%
rename from src/Libraries/SmartStore.Data/Migrations/201809241947314_ForumGroupAcl.Designer.cs
rename to src/Libraries/SmartStore.Data/Migrations/201809251233170_ForumGroupAcl.Designer.cs
index 5d82777a3a..9c8853796f 100644
--- a/src/Libraries/SmartStore.Data/Migrations/201809241947314_ForumGroupAcl.Designer.cs
+++ b/src/Libraries/SmartStore.Data/Migrations/201809251233170_ForumGroupAcl.Designer.cs
@@ -13,7 +13,7 @@ public sealed partial class ForumGroupAcl : IMigrationMetadata
         
         string IMigrationMetadata.Id
         {
-            get { return "201809241947314_ForumGroupAcl"; }
+            get { return "201809251233170_ForumGroupAcl"; }
         }
         
         string IMigrationMetadata.Source
diff --git a/src/Libraries/SmartStore.Data/Migrations/201809241947314_ForumGroupAcl.cs b/src/Libraries/SmartStore.Data/Migrations/201809251233170_ForumGroupAcl.cs
similarity index 57%
rename from src/Libraries/SmartStore.Data/Migrations/201809241947314_ForumGroupAcl.cs
rename to src/Libraries/SmartStore.Data/Migrations/201809251233170_ForumGroupAcl.cs
index 25876305cd..67781b9ef6 100644
--- a/src/Libraries/SmartStore.Data/Migrations/201809241947314_ForumGroupAcl.cs
+++ b/src/Libraries/SmartStore.Data/Migrations/201809251233170_ForumGroupAcl.cs
@@ -7,12 +7,16 @@ public partial class ForumGroupAcl : DbMigration
     {
         public override void Up()
         {
+            AddColumn("dbo.Forums_Post", "Published", c => c.Boolean(nullable: false, defaultValue: true));
+            AddColumn("dbo.Forums_Topic", "Published", c => c.Boolean(nullable: false, defaultValue: true));
             AddColumn("dbo.Forums_Group", "SubjectToAcl", c => c.Boolean(nullable: false));
         }
         
         public override void Down()
         {
             DropColumn("dbo.Forums_Group", "SubjectToAcl");
+            DropColumn("dbo.Forums_Topic", "Published");
+            DropColumn("dbo.Forums_Post", "Published");
         }
     }
 }
diff --git a/src/Libraries/SmartStore.Data/Migrations/201809251233170_ForumGroupAcl.resx b/src/Libraries/SmartStore.Data/Migrations/201809251233170_ForumGroupAcl.resx
new file mode 100644
index 0000000000..572cbd0572
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201809251233170_ForumGroupAcl.resx
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="Target" xml:space="preserve">
+    <value>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</value>
+  </data>
+  <data name="DefaultSchema" xml:space="preserve">
+    <value>dbo</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj
index 364baeac00..30a53f7b9a 100644
--- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj
+++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj
@@ -623,9 +623,9 @@
     <Compile Include="Migrations\201809171309522_NewsletterSubscriptionLanguage.Designer.cs">
       <DependentUpon>201809171309522_NewsletterSubscriptionLanguage.cs</DependentUpon>
     </Compile>
-    <Compile Include="Migrations\201809241947314_ForumGroupAcl.cs" />
-    <Compile Include="Migrations\201809241947314_ForumGroupAcl.Designer.cs">
-      <DependentUpon>201809241947314_ForumGroupAcl.cs</DependentUpon>
+    <Compile Include="Migrations\201809251233170_ForumGroupAcl.cs" />
+    <Compile Include="Migrations\201809251233170_ForumGroupAcl.Designer.cs">
+      <DependentUpon>201809251233170_ForumGroupAcl.cs</DependentUpon>
     </Compile>
     <Compile Include="ObjectContextBase.SaveChanges.cs" />
     <Compile Include="Setup\Builder\ActivityLogTypeMigrator.cs" />
@@ -1124,8 +1124,8 @@
     <EmbeddedResource Include="Migrations\201809171309522_NewsletterSubscriptionLanguage.resx">
       <DependentUpon>201809171309522_NewsletterSubscriptionLanguage.cs</DependentUpon>
     </EmbeddedResource>
-    <EmbeddedResource Include="Migrations\201809241947314_ForumGroupAcl.resx">
-      <DependentUpon>201809241947314_ForumGroupAcl.cs</DependentUpon>
+    <EmbeddedResource Include="Migrations\201809251233170_ForumGroupAcl.resx">
+      <DependentUpon>201809251233170_ForumGroupAcl.cs</DependentUpon>
     </EmbeddedResource>
     <EmbeddedResource Include="Sql\Indexes.sql" />
     <EmbeddedResource Include="Sql\StoredProcedures.sql" />
diff --git a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
index a6310b4388..ed57ca8b54 100644
--- a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
+++ b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
@@ -940,7 +940,8 @@ public ActionResult TopicCreate(EditForumTopicModel model, bool captchaValid)
                         ForumId = forum.Id,
                         CustomerId = customer.Id,
                         TopicTypeId = (int) topicType,
-                        Subject = subject
+                        Subject = subject,
+                        Published = true
                     };
                     _forumService.InsertTopic(forumTopic, true);
 
@@ -950,6 +951,7 @@ public ActionResult TopicCreate(EditForumTopicModel model, bool captchaValid)
                         CustomerId = customer.Id,
                         Text = text,
                         IPAddress = ipAddress,
+                        Published = true
                     };
                     _forumService.InsertPost(forumPost, false);
 
@@ -1122,6 +1124,7 @@ public ActionResult TopicEdit(EditForumTopicModel model, bool captchaValid)
                             CustomerId = forumTopic.CustomerId,
                             Text = text,
                             IPAddress = ipAddress,
+                            Published = true
                         };
 
                         _forumService.InsertPost(firstPost, false);
@@ -1327,7 +1330,8 @@ public ActionResult PostCreate(EditForumPostModel model, bool captchaValid)
                         TopicId = forumTopic.Id,
                         CustomerId = customer.Id,
                         Text = text,
-                        IPAddress = ipAddress
+                        IPAddress = ipAddress,
+                        Published = true
                     };
 
                     _forumService.InsertPost(forumPost, true);
diff --git a/src/Tests/SmartStore.Data.Tests/Forums/ForumPostPersistenceTests.cs b/src/Tests/SmartStore.Data.Tests/Forums/ForumPostPersistenceTests.cs
index c9be77bfa9..24b63e38d9 100644
--- a/src/Tests/SmartStore.Data.Tests/Forums/ForumPostPersistenceTests.cs
+++ b/src/Tests/SmartStore.Data.Tests/Forums/ForumPostPersistenceTests.cs
@@ -64,6 +64,7 @@ public void Can_save_and_load_forumpost()
                 UpdatedOnUtc = DateTime.UtcNow,
                 NumPosts = 100,
                 CustomerId = customerFromDb.Id,
+                Published = true
             };
 
             var forumTopicFromDb = SaveAndLoadEntity(forumTopic);
@@ -83,6 +84,7 @@ public void Can_save_and_load_forumpost()
                 CreatedOnUtc = DateTime.UtcNow,
                 UpdatedOnUtc = DateTime.UtcNow,
                 CustomerId = customerFromDb.Id,
+                Published = true
             };
 
             var forumPostFromDb = SaveAndLoadEntity(forumPost);
diff --git a/src/Tests/SmartStore.Data.Tests/Forums/ForumSubscriptionPersistenceTests.cs b/src/Tests/SmartStore.Data.Tests/Forums/ForumSubscriptionPersistenceTests.cs
index 2f1ac31fd4..a75aa8ee3d 100644
--- a/src/Tests/SmartStore.Data.Tests/Forums/ForumSubscriptionPersistenceTests.cs
+++ b/src/Tests/SmartStore.Data.Tests/Forums/ForumSubscriptionPersistenceTests.cs
@@ -65,6 +65,7 @@ public void Can_save_and_load_forum_subscription_forum_subscribed()
                 UpdatedOnUtc = DateTime.UtcNow,
                 NumPosts = 100,
                 CustomerId = customerFromDb.Id,
+                Published = true
             };
 
             var forumTopicFromDb = SaveAndLoadEntity(forumTopic);
@@ -146,6 +147,7 @@ public void Can_save_and_load_forum_subscription_topic_subscribed()
                 UpdatedOnUtc = DateTime.UtcNow,
                 NumPosts = 100,
                 CustomerId = customerFromDb.Id,
+                Published = true
             };
 
             var forumTopicFromDb = SaveAndLoadEntity(forumTopic);
diff --git a/src/Tests/SmartStore.Data.Tests/Forums/ForumTopicPersistenceTests.cs b/src/Tests/SmartStore.Data.Tests/Forums/ForumTopicPersistenceTests.cs
index fde859aeb4..28d2917caf 100644
--- a/src/Tests/SmartStore.Data.Tests/Forums/ForumTopicPersistenceTests.cs
+++ b/src/Tests/SmartStore.Data.Tests/Forums/ForumTopicPersistenceTests.cs
@@ -65,6 +65,7 @@ public void Can_save_and_load_forumtopic()
                 UpdatedOnUtc = DateTime.UtcNow,
                 NumPosts = 100,
                 CustomerId = customerFromDb.Id,
+                Published = true
             };
 
             var forumTopicFromDb = SaveAndLoadEntity(forumTopic);

From 8ba06cf63c3ced046ecf99176abf08b12931c24d Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Tue, 25 Sep 2018 21:26:42 +0200
Subject: [PATCH 09/71] Stated with published property of forum topic and forum
 post

---
 .../Domain/Forums/ForumSettings.cs            |  16 +-
 .../201806231547270_ScheduleTaskHistory.cs    |   6 -
 .../Migrations/MigrationsConfiguration.cs     |   6 +
 .../Forums/ForumService.cs                    |  75 ++-
 .../Forums/IForumService.cs                   |  13 +-
 .../Controllers/BoardsController.cs           | 555 ++++++++++--------
 .../Models/Boards/EditForumPostModel.cs       |   1 +
 .../Models/Boards/EditForumTopicModel.cs      |   1 +
 .../Models/Boards/ForumPostModel.cs           |   1 +
 .../Models/Boards/ForumTopicRowModel.cs       |   1 +
 .../Models/Boards/LastPostModel.cs            |   3 +-
 .../Views/Boards/TopicMove.cshtml             |   6 +-
 12 files changed, 364 insertions(+), 320 deletions(-)

diff --git a/src/Libraries/SmartStore.Core/Domain/Forums/ForumSettings.cs b/src/Libraries/SmartStore.Core/Domain/Forums/ForumSettings.cs
index 89406566f7..ed484dbb4f 100644
--- a/src/Libraries/SmartStore.Core/Domain/Forums/ForumSettings.cs
+++ b/src/Libraries/SmartStore.Core/Domain/Forums/ForumSettings.cs
@@ -11,22 +11,22 @@ public ForumSettings()
 			TopicSubjectMaxLength = 450;
 			PostMaxLength = 4000;
 			StrippedTopicMaxLength = 45;
-			TopicsPageSize = 10;
-			PostsPageSize = 10;
-            SearchResultsPageSize = 12;
+			TopicsPageSize = 20;
+			PostsPageSize = 20;
+            ForumFeedCount = 20;
+            SearchResultsPageSize = 20;
+            LatestCustomerPostsPageSize = 20;
             AllowSorting = true;
-            LatestCustomerPostsPageSize = 10;
-			ShowCustomersPostCount = true;
+            ShowCustomersPostCount = true;
 			ForumEditor = EditorType.BBCodeEditor;
 			SignaturesEnabled = true;
-			PrivateMessagesPageSize = 10;
-			ForumSubscriptionsPageSize = 10;
+			PrivateMessagesPageSize = 20;
+			ForumSubscriptionsPageSize = 20;
 			PMSubjectMaxLength = 450;
 			PMTextMaxLength = 4000;
 			HomePageActiveDiscussionsTopicCount = 5;
 			ActiveDiscussionsPageTopicCount = 50;
 			ActiveDiscussionsFeedCount = 25;
-			ForumFeedCount = 10;
 		}
 		
 		/// <summary>
diff --git a/src/Libraries/SmartStore.Data/Migrations/201806231547270_ScheduleTaskHistory.cs b/src/Libraries/SmartStore.Data/Migrations/201806231547270_ScheduleTaskHistory.cs
index 5d558c26db..f2d93452c9 100644
--- a/src/Libraries/SmartStore.Data/Migrations/201806231547270_ScheduleTaskHistory.cs
+++ b/src/Libraries/SmartStore.Data/Migrations/201806231547270_ScheduleTaskHistory.cs
@@ -85,12 +85,6 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder)
             builder.AddOrUpdate("Common.Succeeded", "Succeeded", "Erfolgreich");
             builder.AddOrUpdate("Common.MachineName", "Machine name", "Maschinenname");
 
-            builder.AddOrUpdate("Admin.System.ScheduleTasks.RunPerMachine",
-                "Run per machine",
-                "Pro Maschine ausf�hren",
-                "Indicates whether the task is executed decidedly on each machine of a web farm.",
-                "Gibt an, ob die Aufgabe auf jeder Maschine einer Webfarm dezidiert ausgef�hrt wird.");
-
             builder.AddOrUpdate("Admin.System.ScheduleTasks.HistoryCleanupNote",
                 "The history is cleaned up once a day: maximum {0} entries and none older than {1} days.",
                 "Die Historie wird einmal t�glich bereinigt: Maximal {0} Eintr�ge und keine �lter als {1} Tage.");
diff --git a/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs b/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
index 3a75d87c08..4e30f67e80 100644
--- a/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
+++ b/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
@@ -513,6 +513,12 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder)
             builder.AddOrUpdate("Plugins.CannotLoadModule",
                 "The plugin or provider \"{0}\" cannot be loaded.",
                 "Das Plugin oder der Provider \"{0}\" kann nicht geladen werden.");
+
+            builder.AddOrUpdate("Admin.System.ScheduleTasks.RunPerMachine",
+                "Run per machine",
+                "Pro Maschine ausführen",
+                "Indicates whether the task is executed decidedly on each machine of a web farm.",
+                "Gibt an, ob die Aufgabe auf jeder Maschine einer Webfarm dezidiert ausgeführt wird.");
         }
     }
 }
diff --git a/src/Libraries/SmartStore.Services/Forums/ForumService.cs b/src/Libraries/SmartStore.Services/Forums/ForumService.cs
index 80f0dea995..f2ae94acba 100644
--- a/src/Libraries/SmartStore.Services/Forums/ForumService.cs
+++ b/src/Libraries/SmartStore.Services/Forums/ForumService.cs
@@ -71,7 +71,7 @@ private void UpdateForumStats(int forumId)
             var queryLastValues = 
                 from ft in _forumTopicRepository.TableUntracked
                 join fp in _forumPostRepository.TableUntracked on ft.Id equals fp.TopicId
-                where ft.ForumId == forumId
+                where ft.ForumId == forumId && ft.Published && fp.Published
                 orderby fp.CreatedOnUtc descending, ft.CreatedOnUtc descending
                 select new
                 {
@@ -86,11 +86,11 @@ join fp in _forumPostRepository.TableUntracked on ft.Id equals fp.TopicId
             forum.LastPostId = lastValues?.LastPostId ?? 0;
             forum.LastPostCustomerId = lastValues?.LastPostCustomerId ?? 0;
             forum.LastPostTime = lastValues?.LastPostTime;
-            forum.NumTopics = _forumTopicRepository.Table.Where(x => x.ForumId == forumId).Count();
+            forum.NumTopics = _forumTopicRepository.Table.Where(x => x.ForumId == forumId && x.Published).Count();
             forum.NumPosts = (
                 from ft in _forumTopicRepository.Table
                 join fp in _forumPostRepository.Table on ft.Id equals fp.TopicId
-                where ft.ForumId == forumId
+                where ft.ForumId == forumId && ft.Published && fp.Published
                 select fp.Id).Count();
 
             UpdateForum(forum);
@@ -106,7 +106,7 @@ private void UpdateForumTopicStats(int forumTopicId)
 
             var queryLastValues = 
                 from fp in _forumPostRepository.TableUntracked
-                where fp.TopicId == forumTopicId
+                where fp.TopicId == forumTopicId && fp.Published
                 orderby fp.CreatedOnUtc descending
                 select new
                 {
@@ -119,7 +119,7 @@ orderby fp.CreatedOnUtc descending
             forumTopic.LastPostId = lastValues?.LastPostId ?? 0;
             forumTopic.LastPostCustomerId = lastValues?.LastPostCustomerId ?? 0;
             forumTopic.LastPostTime = lastValues?.LastPostTime;
-            forumTopic.NumPosts = _forumPostRepository.Table.Where(x => x.TopicId == forumTopicId).Count();
+            forumTopic.NumPosts = _forumPostRepository.Table.Where(x => x.TopicId == forumTopicId && x.Published).Count();
 
             UpdateTopic(forumTopic);
         }
@@ -131,7 +131,7 @@ private void UpdateCustomerStats(int customerId)
                 var customer = _customerService.GetCustomerById(customerId);
                 if (customer != null)
                 {
-                    var numPosts = _forumPostRepository.Table.Where(x => x.CustomerId == customerId).Count();
+                    var numPosts = _forumPostRepository.Table.Where(x => x.CustomerId == customerId && x.Published).Count();
 
                     _genericAttributeService.SaveAttribute(customer, SystemCustomerAttributeNames.ForumPostCount, numPosts);
                 }
@@ -235,17 +235,6 @@ public virtual Forum GetForumById(int forumId)
             return entity;
         }
 
-        public virtual IList<Forum> GetAllForumsByGroupId(int forumGroupId)
-        {
-			var query = from f in _forumRepository.Table
-						orderby f.DisplayOrder
-						where f.ForumGroupId == forumGroupId
-						select f;
-
-			var forums = query.ToListCached();
-			return forums;
-		}
-
         public virtual void InsertForum(Forum forum)
         {
             Guard.NotNull(forum, nameof(forum));
@@ -324,14 +313,21 @@ public virtual IList<ForumTopic> GetTopicsByIds(int[] topicIds)
             return query.OrderBySequence(topicIds).ToList();
         }
 
-        public virtual IPagedList<ForumTopic> GetAllTopics(int forumId, int pageIndex, int pageSize)
+        public virtual IPagedList<ForumTopic> GetAllTopics(int forumId, int pageIndex, int pageSize, bool showHidden = false)
         {
+            var customer = _services.WorkContext.CurrentCustomer;
             var query = _forumTopicRepository.TableUntracked;
+
             if (forumId != 0)
             {
                 query = query.Where(x => x.ForumId == forumId);
             }
 
+            if (!showHidden && !customer.IsForumModerator())
+            {
+                query = query.Where(x => x.Published || x.CustomerId == customer.Id);
+            }
+
             query = query
                 .OrderByDescending(x => x.TopicTypeId)
                 .ThenByDescending(x => x.LastPostTime)
@@ -344,11 +340,18 @@ public virtual IPagedList<ForumTopic> GetAllTopics(int forumId, int pageIndex, i
         public virtual IList<ForumTopic> GetActiveTopics(int forumId, int count, bool showHidden = false)
         {
             var joinApplied = false;
+            var customer = _services.WorkContext.CurrentCustomer;
+
             var query =
 				from ft in _forumTopicRepository.Table
-				where (forumId == 0 || ft.ForumId == forumId) && (ft.LastPostTime.HasValue)
+				where (forumId == 0 || ft.ForumId == forumId) && ft.LastPostTime.HasValue
 				select ft;
 
+            if (!showHidden && !customer.IsForumModerator())
+            {
+                query = query.Where(x => x.Published || x.CustomerId == customer.Id);
+            }
+
 			if (!QuerySettings.IgnoreMultiStore)
 			{
 				var currentStoreId = _services.StoreContext.CurrentStore.Id;
@@ -367,7 +370,7 @@ from sm in fg_sm.DefaultIfEmpty()
 
             if (!showHidden && !QuerySettings.IgnoreAcl)
             {
-                var allowedCustomerRolesIds = _services.WorkContext.CurrentCustomer.CustomerRoles.Where(x => x.Active).Select(x => x.Id).ToList();
+                var allowedCustomerRolesIds = customer.CustomerRoles.Where(x => x.Active).Select(x => x.Id).ToList();
 
                 query =
                     from ft in query
@@ -535,9 +538,17 @@ public virtual IList<ForumPost> GetPostsByIds(int[] postIds)
             return query.OrderBySequence(postIds).ToList();
         }
 
-        public virtual IPagedList<ForumPost> GetAllPosts(int forumTopicId, int customerId, bool ascSort, int pageIndex, int pageSize)
+        public virtual IPagedList<ForumPost> GetAllPosts(
+            int forumTopicId,
+            int customerId,
+            bool ascSort,
+            int pageIndex,
+            int pageSize,
+            bool showHidden = false)
         {
+            var customer = _services.WorkContext.CurrentCustomer;
             var query = _forumPostRepository.Table;
+
             if (forumTopicId > 0)
             {
                 query = query.Where(fp => forumTopicId == fp.TopicId);
@@ -546,6 +557,11 @@ public virtual IPagedList<ForumPost> GetAllPosts(int forumTopicId, int customerI
             {
                 query = query.Where(fp => customerId == fp.CustomerId);
             }
+            if (!showHidden && !customer.IsForumModerator())
+            {
+                query = query.Where(fp => fp.Published || fp.CustomerId == customer.Id);
+            }
+
             if (ascSort)
             {
                 query = query.OrderBy(fp => fp.CreatedOnUtc).ThenBy(fp => fp.Id);
@@ -578,7 +594,7 @@ public virtual void InsertPost(ForumPost forumPost, bool sendNotifications)
                 var subscriptions = GetAllSubscriptions(0, 0, forumTopic.Id, 0, int.MaxValue);
                 var friendlyTopicPageIndex = CalculateTopicPageIndex(
                     forumPost.TopicId,
-                    _forumSettings.PostsPageSize > 0 ? _forumSettings.PostsPageSize : 10,
+                    _forumSettings.PostsPageSize > 0 ? _forumSettings.PostsPageSize : 20,
                     forumPost.Id) + 1;
 
                 foreach (var subscription in subscriptions)
@@ -835,7 +851,7 @@ public virtual bool IsCustomerAllowedToEditTopic(Customer customer, ForumTopic t
                 return true;
             }
 
-            if (_forumSettings.AllowCustomersToEditPosts)
+            if (_forumSettings.AllowCustomersToEditPosts && topic.Published)
             {
                 var ownTopic = customer.Id == topic.CustomerId;
                 return ownTopic;
@@ -846,12 +862,7 @@ public virtual bool IsCustomerAllowedToEditTopic(Customer customer, ForumTopic t
 
         public virtual bool IsCustomerAllowedToMoveTopic(Customer customer, ForumTopic topic)
         {
-            if (topic == null || customer == null)
-            {
-                return false;
-            }
-
-            if (customer.IsGuest())
+            if (topic == null || customer == null || customer.IsGuest())
             {
                 return false;
             }
@@ -876,7 +887,7 @@ public virtual bool IsCustomerAllowedToDeleteTopic(Customer customer, ForumTopic
                 return true;
             }
 
-            if (_forumSettings.AllowCustomersToDeletePosts)
+            if (_forumSettings.AllowCustomersToDeletePosts && topic.Published)
             {
                 var ownTopic = customer.Id == topic.CustomerId;
                 return ownTopic;
@@ -912,7 +923,7 @@ public virtual bool IsCustomerAllowedToEditPost(Customer customer, ForumPost pos
                 return true;
             }
 
-            if (_forumSettings.AllowCustomersToEditPosts)
+            if (_forumSettings.AllowCustomersToEditPosts && post.Published)
             {
                 var ownPost = customer.Id == post.CustomerId;
                 return ownPost;
@@ -933,7 +944,7 @@ public virtual bool IsCustomerAllowedToDeletePost(Customer customer, ForumPost p
                 return true;
             }
 
-            if (_forumSettings.AllowCustomersToDeletePosts)
+            if (_forumSettings.AllowCustomersToDeletePosts && post.Published)
             {
                 var ownPost = customer.Id == post.CustomerId;
                 return ownPost;
diff --git a/src/Libraries/SmartStore.Services/Forums/IForumService.cs b/src/Libraries/SmartStore.Services/Forums/IForumService.cs
index ed991c0c8d..95459269ab 100644
--- a/src/Libraries/SmartStore.Services/Forums/IForumService.cs
+++ b/src/Libraries/SmartStore.Services/Forums/IForumService.cs
@@ -56,13 +56,6 @@ public partial interface IForumService
         /// <returns>Forum</returns>
         Forum GetForumById(int forumId);
 
-        /// <summary>
-        /// Gets forums by group identifier
-        /// </summary>
-        /// <param name="forumGroupId">The forum group identifier</param>
-        /// <returns>Forums</returns>
-        IList<Forum> GetAllForumsByGroupId(int forumGroupId);
-
         /// <summary>
         /// Deletes a forum
         /// </summary>
@@ -105,8 +98,9 @@ public partial interface IForumService
         /// <param name="forumId">The forum identifier</param>
         /// <param name="pageIndex">Page index</param>
         /// <param name="pageSize">Page size</param>
+        /// <param name="showHidden">Whether to load hidden records</param>
         /// <returns>Forum Topics</returns>
-        IPagedList<ForumTopic> GetAllTopics(int forumId, int pageIndex, int pageSize);
+        IPagedList<ForumTopic> GetAllTopics(int forumId, int pageIndex, int pageSize, bool showHidden = false);
 
         /// <summary>
         /// Gets active forum topics
@@ -179,8 +173,9 @@ public partial interface IForumService
         /// <param name="ascSort">Sort order</param>
         /// <param name="pageIndex">Page index</param>
         /// <param name="pageSize">Page size</param>
+        /// <param name="showHidden">Whether to load hidden records</param>
         /// <returns>Forum Posts</returns>
-        IPagedList<ForumPost> GetAllPosts(int forumTopicId, int customerId, bool ascSort, int pageIndex, int pageSize);
+        IPagedList<ForumPost> GetAllPosts(int forumTopicId, int customerId, bool ascSort, int pageIndex, int pageSize, bool showHidden = false);
 
         /// <summary>
         /// Deletes a forum post
diff --git a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
index ed57ca8b54..57e57fac1e 100644
--- a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
+++ b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
@@ -103,6 +103,7 @@ private ForumTopicRowModel PrepareForumTopicRowModel(
             var model = new ForumTopicRowModel
             {
                 Id = topic.Id,
+                Published = topic.Published,
                 Subject = topic.Subject,
                 SeName = topic.GetSeName(),
                 FirstPostId = firstPost?.Id ?? topic.FirstPostId,
@@ -159,9 +160,7 @@ private ForumGroupModel PrepareForumGroupModel(ForumGroup forumGroup)
 				SeName = forumGroup.GetSeName()
             };
 
-            var forums = _forumService.GetAllForumsByGroupId(forumGroup.Id);
-
-            var lastPostIds = forums
+            var lastPostIds = forumGroup.Forums
                 .Where(x => x.LastPostId != 0)
                 .Select(x => x.LastPostId)
                 .Distinct()
@@ -169,7 +168,7 @@ private ForumGroupModel PrepareForumGroupModel(ForumGroup forumGroup)
 
             var lastPosts = _forumService.GetPostsByIds(lastPostIds).ToDictionary(x => x.Id);
 
-            foreach (var forum in forums)
+            foreach (var forum in forumGroup.Forums)
             {
                 var forumModel = PrepareForumRowModel(forum, lastPosts);
                 forumModel.LastPost.ShowTopic = true;
@@ -192,6 +191,7 @@ private void PrepareLastPostModel(LastPostModel model, ForumPost post)
                 model.AllowViewingProfiles = _customerSettings.AllowViewingProfiles;
                 model.CustomerName = post.Customer.FormatUserName(true);
                 model.IsCustomerGuest = post.Customer.IsGuest();
+                model.Published = post.Published;
 
                 model.PostCreatedOnStr = _forumSettings.RelativeDateTimeFormattingEnabled
                     ? post.CreatedOnUtc.RelativeFormat(true, "f")
@@ -236,10 +236,13 @@ private IEnumerable<SelectListItem> ForumGroupsForumsList()
                 // Add the forum group with Value of 0 so it won't be used as a target forum.
                 forumsList.Add(new SelectListItem { Text = fg.GetLocalized(x => x.Name), Value = "0" });
 
-                var forums = _forumService.GetAllForumsByGroupId(fg.Id);
-                foreach (var f in forums)
+                foreach (var f in fg.Forums)
                 {
-                    forumsList.Add(new SelectListItem { Text = string.Format("{0}{1}", separator, f.GetLocalized(x => x.Name)), Value = f.Id.ToString() });
+                    forumsList.Add(new SelectListItem 
+                    {
+                        Text = separator + f.GetLocalized(x => x.Name),
+                        Value = f.Id.ToString()
+                    });
                 }
             }
 
@@ -309,6 +312,28 @@ private void SaveLastForumVisit(Customer customer)
             }
         }
 
+        private bool IsTopicVisible(ForumTopic topic, Customer customer)
+        {
+            if (topic == null)
+            {
+                return false;
+            }
+            if (!topic.Published && topic.CustomerId != customer.Id && !customer.IsForumModerator())
+            {
+                return false;
+            }
+            if (!_storeMappingService.Authorize(topic.Forum.ForumGroup))
+            {
+                return false;
+            }
+            if (!_aclService.Authorize(topic.Forum.ForumGroup))
+            {
+                return false;
+            }
+
+            return true;
+        }
+
         #endregion
 
         #region Forum group
@@ -364,7 +389,7 @@ public ActionResult Forum(int id, int page = 1)
         {
             if (!_forumSettings.ForumsEnabled)
             {
-				return HttpNotFound();
+                return HttpNotFound();
             }
 
             var customer = Services.WorkContext.CurrentCustomer;
@@ -374,11 +399,22 @@ public ActionResult Forum(int id, int page = 1)
                 return HttpNotFound();
             }
 
-            var model = new ForumPageModel();
-            model.Id = forum.Id;
-            model.Name = forum.GetLocalized(x => x.Name);
-            model.SeName = forum.GetSeName();
-            model.Description = forum.GetLocalized(x => x.Description);
+            var pageSize = _forumSettings.TopicsPageSize > 0 ? _forumSettings.TopicsPageSize : 20;
+            var topics = _forumService.GetAllTopics(forum.Id, page - 1, pageSize);
+
+            var model = new ForumPageModel
+            {
+                Id = forum.Id,
+                Name = forum.GetLocalized(x => x.Name),
+                SeName = forum.GetSeName(),
+                Description = forum.GetLocalized(x => x.Description),
+                TopicPageSize = topics.PageSize,
+                TopicTotalRecords = topics.TotalCount,
+                TopicPageIndex = topics.PageIndex,
+                IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer),
+                ForumFeedsEnabled = _forumSettings.ForumFeedsEnabled,
+                PostsPageSize = _forumSettings.PostsPageSize
+            };
 
             // Subscription.
             if (_forumService.IsCustomerAllowedToSubscribe(customer))
@@ -393,9 +429,6 @@ public ActionResult Forum(int id, int page = 1)
                 }
             }
 
-            var pageSize = _forumSettings.TopicsPageSize > 0 ? _forumSettings.TopicsPageSize : 10;
-            var topics = _forumService.GetAllTopics(forum.Id, (page - 1), pageSize);
-
             var lastPostIds = topics
                 .Where(x => x.LastPostId != 0)
                 .Select(x => x.LastPostId)
@@ -410,13 +443,6 @@ public ActionResult Forum(int id, int page = 1)
                 model.ForumTopics.Add(topicModel);
             }
 
-            model.TopicPageSize = topics.PageSize;
-            model.TopicTotalRecords = topics.TotalCount;
-            model.TopicPageIndex = topics.PageIndex;
-            model.IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer);
-            model.ForumFeedsEnabled = _forumSettings.ForumFeedsEnabled;
-            model.PostsPageSize = _forumSettings.PostsPageSize;
-
 			CreateForumBreadcrumb(forum: forum);
             SaveLastForumVisit(customer);
 
@@ -640,112 +666,109 @@ public ActionResult Topic(int id, int page = 1)
             }
 
             var customer = Services.WorkContext.CurrentCustomer;
-            var forumTopic = _forumService.GetTopicById(id);
+            var topic = _forumService.GetTopicById(id);
 
-            if (forumTopic != null)
+            if (!IsTopicVisible(topic, customer))
             {
-                if (!_storeMappingService.Authorize(forumTopic.Forum.ForumGroup) || !_aclService.Authorize(forumTopic.Forum.ForumGroup))
-                {
-                    return HttpNotFound();
-                }
+                return HttpNotFound();
+            }
 
-                var posts = _forumService.GetAllPosts(forumTopic.Id, 0, true, page - 1, _forumSettings.PostsPageSize);
+            var posts = _forumService.GetAllPosts(topic.Id, 0, true, page - 1, _forumSettings.PostsPageSize);
 
-                // If no posts area loaded, redirect to the first page.
-                if (posts.Count == 0 && page > 1)
-                {
-                    return RedirectToRoute("TopicSlug", new { id = forumTopic.Id, slug = forumTopic.GetSeName() });
-                }
+            // If no posts area loaded, redirect to the first page.
+            if (posts.Count == 0 && page > 1)
+            {
+                return RedirectToRoute("TopicSlug", new { id = topic.Id, slug = topic.GetSeName() });
+            }
 
-                // Update view count.
-                try
-                {
-                    if (!customer.Deleted && customer.Active && !customer.IsSystemAccount)
-                    {
-                        forumTopic.Views += 1;
-                        _forumService.UpdateTopic(forumTopic);
-                    }
-                }
-                catch (Exception ex)
+            // Update view count.
+            try
+            {
+                if (!customer.Deleted && customer.Active && !customer.IsSystemAccount)
                 {
-                    Logger.Error(ex);
+                    topic.Views += 1;
+                    _forumService.UpdateTopic(topic);
                 }
+            }
+            catch (Exception ex)
+            {
+                Logger.Error(ex);
+            }
 
-                var model = new ForumTopicPageModel();
-                model.Id = forumTopic.Id;
-                model.Subject= forumTopic.Subject;
-                model.SeName = forumTopic.GetSeName();
-                model.IsCustomerAllowedToEditTopic = _forumService.IsCustomerAllowedToEditTopic(customer, forumTopic);
-                model.IsCustomerAllowedToDeleteTopic = _forumService.IsCustomerAllowedToDeleteTopic(customer, forumTopic);
-                model.IsCustomerAllowedToMoveTopic = _forumService.IsCustomerAllowedToMoveTopic(customer, forumTopic);
-                model.IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer);
+            var model = new ForumTopicPageModel
+            {
+                Id = topic.Id,
+                Subject = topic.Subject,
+                SeName = topic.GetSeName(),
+                IsCustomerAllowedToEditTopic = _forumService.IsCustomerAllowedToEditTopic(customer, topic),
+                IsCustomerAllowedToDeleteTopic = _forumService.IsCustomerAllowedToDeleteTopic(customer, topic),
+                IsCustomerAllowedToMoveTopic = _forumService.IsCustomerAllowedToMoveTopic(customer, topic),
+                IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer),
+                PostsPageIndex = posts.PageIndex,
+                PostsPageSize = posts.PageSize,
+                PostsTotalRecords = posts.TotalCount
+            };
 
-                if (model.IsCustomerAllowedToSubscribe)
-                {
-                    model.WatchTopicText = T("Forum.WatchTopic");
+            if (model.IsCustomerAllowedToSubscribe)
+            {
+                model.WatchTopicText = T("Forum.WatchTopic");
 
-                    var forumTopicSubscription = _forumService.GetAllSubscriptions(customer.Id, 0, forumTopic.Id, 0, 1).FirstOrDefault();
-                    if (forumTopicSubscription != null)
-                    {
-                        model.WatchTopicText = T("Forum.UnwatchTopic");
-                    }
+                var forumTopicSubscription = _forumService.GetAllSubscriptions(customer.Id, 0, topic.Id, 0, 1).FirstOrDefault();
+                if (forumTopicSubscription != null)
+                {
+                    model.WatchTopicText = T("Forum.UnwatchTopic");
                 }
+            }
                 
-				model.PostsPageIndex = posts.PageIndex;
-                model.PostsPageSize = posts.PageSize;
-                model.PostsTotalRecords = posts.TotalCount;
-
-                foreach (var post in posts)
+            foreach (var post in posts)
+            {
+                var forumPostModel = new ForumPostModel
                 {
-                    var forumPostModel = new ForumPostModel
-                    {
-                        Id = post.Id,
-                        ForumTopicId =  post.TopicId,
-                        ForumTopicSeName = forumTopic.GetSeName(),
-                        FormattedText = post.FormatPostText(),
-                        IsCurrentCustomerAllowedToEditPost = _forumService.IsCustomerAllowedToEditPost(customer, post),
-                        IsCurrentCustomerAllowedToDeletePost = _forumService.IsCustomerAllowedToDeletePost(customer, post),
-                        CustomerId = post.CustomerId,
-                        AllowViewingProfiles = _customerSettings.AllowViewingProfiles,
-                        CustomerName = post.Customer.FormatUserName(_customerSettings, T, false),
-                        IsCustomerForumModerator = post.Customer.IsForumModerator(),
-                        IsCustomerGuest= post.Customer.IsGuest(),
-                        ShowCustomersPostCount = _forumSettings.ShowCustomersPostCount,
-                        ForumPostCount = post.Customer.GetAttribute<int>(SystemCustomerAttributeNames.ForumPostCount),
-                        ShowCustomersJoinDate = _customerSettings.ShowCustomersJoinDate,
-                        CustomerJoinDate = post.Customer.CreatedOnUtc,
-                        AllowPrivateMessages = _forumSettings.AllowPrivateMessages,
-                        SignaturesEnabled = _forumSettings.SignaturesEnabled,
-                        FormattedSignature = post.Customer.GetAttribute<string>(SystemCustomerAttributeNames.Signature).FormatForumSignatureText(),
-                    };
-
-                    forumPostModel.PostCreatedOnStr = _forumSettings.RelativeDateTimeFormattingEnabled
-                        ? post.CreatedOnUtc.RelativeFormat(true, "f")
-                        : _dateTimeHelper.ConvertToUserTime(post.CreatedOnUtc, DateTimeKind.Utc).ToString("f");
+                    Id = post.Id,
+                    Published = post.Published,
+                    ForumTopicId =  post.TopicId,
+                    ForumTopicSeName = topic.GetSeName(),
+                    FormattedText = post.FormatPostText(),
+                    IsCurrentCustomerAllowedToEditPost = _forumService.IsCustomerAllowedToEditPost(customer, post),
+                    IsCurrentCustomerAllowedToDeletePost = _forumService.IsCustomerAllowedToDeletePost(customer, post),
+                    CustomerId = post.CustomerId,
+                    AllowViewingProfiles = _customerSettings.AllowViewingProfiles,
+                    CustomerName = post.Customer.FormatUserName(_customerSettings, T, false),
+                    IsCustomerForumModerator = post.Customer.IsForumModerator(),
+                    IsCustomerGuest= post.Customer.IsGuest(),
+                    ShowCustomersPostCount = _forumSettings.ShowCustomersPostCount,
+                    ForumPostCount = post.Customer.GetAttribute<int>(SystemCustomerAttributeNames.ForumPostCount),
+                    ShowCustomersJoinDate = _customerSettings.ShowCustomersJoinDate,
+                    CustomerJoinDate = post.Customer.CreatedOnUtc,
+                    AllowPrivateMessages = _forumSettings.AllowPrivateMessages,
+                    SignaturesEnabled = _forumSettings.SignaturesEnabled,
+                    FormattedSignature = post.Customer.GetAttribute<string>(SystemCustomerAttributeNames.Signature).FormatForumSignatureText(),
+                };
 
-                    forumPostModel.Avatar = post.Customer.ToAvatarModel(_genericAttributeService, _pictureService, _customerSettings, _mediaSettings, Url, forumPostModel.CustomerName, true);
+                forumPostModel.PostCreatedOnStr = _forumSettings.RelativeDateTimeFormattingEnabled
+                    ? post.CreatedOnUtc.RelativeFormat(true, "f")
+                    : _dateTimeHelper.ConvertToUserTime(post.CreatedOnUtc, DateTimeKind.Utc).ToString("f");
 
-                    // Location.
-                    forumPostModel.ShowCustomersLocation = _customerSettings.ShowCustomersLocation;
-                    if (_customerSettings.ShowCustomersLocation)
-                    {
-                        var countryId = post.Customer.GetAttribute<int>(SystemCustomerAttributeNames.CountryId);
-                        var country = _countryService.GetCountryById(countryId);
-                        forumPostModel.CustomerLocation = country != null ? country.GetLocalized(x => x.Name) : string.Empty;
-                    }
+                forumPostModel.Avatar = post.Customer.ToAvatarModel(_genericAttributeService, _pictureService, _customerSettings, _mediaSettings, Url, forumPostModel.CustomerName, true);
 
-                    // Page number is needed for creating post link in _ForumPost partial view.
-                    forumPostModel.CurrentTopicPage = page;
-                    model.ForumPostModels.Add(forumPostModel);
+                // Location.
+                forumPostModel.ShowCustomersLocation = _customerSettings.ShowCustomersLocation;
+                if (_customerSettings.ShowCustomersLocation)
+                {
+                    var countryId = post.Customer.GetAttribute<int>(SystemCustomerAttributeNames.CountryId);
+                    var country = _countryService.GetCountryById(countryId);
+                    forumPostModel.CustomerLocation = country != null ? country.GetLocalized(x => x.Name) : string.Empty;
                 }
 
-				CreateForumBreadcrumb(topic: forumTopic);
-                SaveLastForumVisit(customer);
-
-                return View(model);
+                // Page number is needed for creating post link in _ForumPost partial view.
+                forumPostModel.CurrentTopicPage = page;
+                model.ForumPostModels.Add(forumPostModel);
             }
 
-            return RedirectToRoute("Boards");
+			CreateForumBreadcrumb(topic: topic);
+            SaveLastForumVisit(customer);
+
+            return View(model);
         }
 
         [HttpPost]
@@ -754,39 +777,31 @@ public ActionResult TopicWatch(int id)
             var subscribed = false;
             var returnText = T("Forum.WatchTopic").Text;
             var customer = Services.WorkContext.CurrentCustomer;
-            var forumTopic = _forumService.GetTopicById(id);
+            var topic = _forumService.GetTopicById(id);
 
-            if (forumTopic == null)
+            if (!IsTopicVisible(topic, customer) || !_forumService.IsCustomerAllowedToSubscribe(customer))
             {
                 return Json(new { Subscribed = subscribed, Text = returnText, Error = true });
             }
 
-            if (!_storeMappingService.Authorize(forumTopic.Forum.ForumGroup) ||
-                !_aclService.Authorize(forumTopic.Forum.ForumGroup) ||
-                !_forumService.IsCustomerAllowedToSubscribe(customer))
+            var subscription = _forumService.GetAllSubscriptions(customer.Id, 0, topic.Id, 0, 1).FirstOrDefault();
+            if (subscription == null)
             {
-                return Json(new { Subscribed = subscribed, Text = returnText, Error = true });
-            }
-
-            var forumSubscription = _forumService.GetAllSubscriptions(customer.Id, 0, forumTopic.Id, 0, 1).FirstOrDefault();
-
-            if (forumSubscription == null)
-            {
-                forumSubscription = new ForumSubscription
+                subscription = new ForumSubscription
                 {
                     SubscriptionGuid = Guid.NewGuid(),
                     CustomerId = customer.Id,
-                    TopicId = forumTopic.Id,
+                    TopicId = topic.Id,
                     CreatedOnUtc = DateTime.UtcNow
                 };
 
-                _forumService.InsertSubscription(forumSubscription);
+                _forumService.InsertSubscription(subscription);
                 subscribed = true;
                 returnText = T("Forum.UnwatchTopic");
             }
             else
             {
-                _forumService.DeleteSubscription(forumSubscription);
+                _forumService.DeleteSubscription(subscription);
                 subscribed = false;
             }
 
@@ -797,22 +812,30 @@ public ActionResult TopicMove(int id)
         {
             if (!_forumSettings.ForumsEnabled)
             {
-				return HttpNotFound();
+                return HttpNotFound();
             }
 
-            var forumTopic = _forumService.GetTopicById(id);
-            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup) || !_aclService.Authorize(forumTopic.Forum.ForumGroup))
+            var customer = Services.WorkContext.CurrentCustomer;
+            var topic = _forumService.GetTopicById(id);
+
+            if (!IsTopicVisible(topic, customer))
             {
-				return HttpNotFound();
+                return HttpNotFound();
+            }
+            if (!_forumService.IsCustomerAllowedToMoveTopic(customer, topic))
+            {
+                return new HttpUnauthorizedResult();
             }
 
-            var model = new TopicMoveModel();
+            var model = new TopicMoveModel
+            {
+                Id = topic.Id,
+                TopicSeName = topic.GetSeName(),
+                ForumSelected = topic.ForumId,
+            };
             model.ForumList = ForumGroupsForumsList();
-            model.Id = forumTopic.Id;
-            model.TopicSeName = forumTopic.GetSeName();
-            model.ForumSelected = forumTopic.ForumId;
 
-			CreateForumBreadcrumb(topic: forumTopic);
+            CreateForumBreadcrumb(topic: topic);
 
 			return View(model);
         }
@@ -825,55 +848,59 @@ public ActionResult TopicMove(TopicMoveModel model)
                 return HttpNotFound();
             }
 
-            var forumTopic = _forumService.GetTopicById(model.Id);
-            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup) || !_aclService.Authorize(forumTopic.Forum.ForumGroup))
+            var customer = Services.WorkContext.CurrentCustomer;
+            var topic = _forumService.GetTopicById(model.Id);
+
+            if (!IsTopicVisible(topic, customer))
             {
                 return HttpNotFound();
             }
 
             var newForumId = model.ForumSelected;
             var forum = _forumService.GetForumById(newForumId);
-
-            if (forum != null && forumTopic.ForumId != newForumId)
+            if (forum != null && topic.ForumId != newForumId)
             {
-                _forumService.MoveTopic(forumTopic.Id, newForumId);
+                _forumService.MoveTopic(topic.Id, newForumId);
             }
 
-            return RedirectToRoute("TopicSlug", new { id = forumTopic.Id, slug = forumTopic.GetSeName() });
+            return RedirectToRoute("TopicSlug", new { id = topic.Id, slug = topic.GetSeName() });
         }
 
-		[GdprConsent]
-		public ActionResult TopicCreate(int id)
+        [GdprConsent]
+        public ActionResult TopicCreate(int id)
         {
             if (!_forumSettings.ForumsEnabled)
             {
-				return HttpNotFound();
+                return HttpNotFound();
             }
 
             var customer = Services.WorkContext.CurrentCustomer;
             var forum = _forumService.GetForumById(id);
+
             if (forum == null || !_storeMappingService.Authorize(forum.ForumGroup) || !_aclService.Authorize(forum.ForumGroup))
             {
-				return HttpNotFound();
+                return HttpNotFound();
             }
-
             if (!_forumService.IsCustomerAllowedToCreateTopic(customer, forum))
             {
                 return new HttpUnauthorizedResult();
             }
 
-            var model = new EditForumTopicModel();
-            model.Id = 0;
-            model.IsEdit = false;
-            model.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnForumPage;
-            model.ForumId = forum.Id;
-            model.ForumName = forum.GetLocalized(x => x.Name);
-            model.ForumSeName = forum.GetSeName();
-            model.ForumEditor = _forumSettings.ForumEditor;
-            model.IsCustomerAllowedToSetTopicPriority = _forumService.IsCustomerAllowedToSetTopicPriority(customer);
-            model.TopicPriorities = ForumTopicTypesList();
-            model.IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer);
-            model.Subscribed = false;
+            var model = new EditForumTopicModel
+            {
+                Id = 0,
+                IsEdit = false,
+                Published = true,
+                DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnForumPage,
+                ForumId = forum.Id,
+                ForumName = forum.GetLocalized(x => x.Name),
+                ForumSeName = forum.GetSeName(),
+                ForumEditor = _forumSettings.ForumEditor,
+                IsCustomerAllowedToSetTopicPriority = _forumService.IsCustomerAllowedToSetTopicPriority(customer),
+                TopicPriorities = ForumTopicTypesList(),
+                IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer),
+                Subscribed = false,
+            };
 
 			CreateForumBreadcrumb(forum: forum);
 
@@ -897,7 +924,6 @@ public ActionResult TopicCreate(EditForumTopicModel model, bool captchaValid)
             {
                 return HttpNotFound();
             }
-
             if (!_forumService.IsCustomerAllowedToCreateTopic(customer, forum))
             {
                 return new HttpUnauthorizedResult();
@@ -935,7 +961,7 @@ public ActionResult TopicCreate(EditForumTopicModel model, bool captchaValid)
                         topicType = (ForumTopicType)Enum.ToObject(typeof (ForumTopicType), model.TopicTypeId);
                     }
 
-                    var forumTopic = new ForumTopic
+                    var topic = new ForumTopic
                     {
                         ForumId = forum.Id,
                         CustomerId = customer.Id,
@@ -943,24 +969,24 @@ public ActionResult TopicCreate(EditForumTopicModel model, bool captchaValid)
                         Subject = subject,
                         Published = true
                     };
-                    _forumService.InsertTopic(forumTopic, true);
+                    _forumService.InsertTopic(topic, true);
 
-                    var forumPost = new ForumPost
+                    var post = new ForumPost
                     {
-                        TopicId = forumTopic.Id,
+                        TopicId = topic.Id,
                         CustomerId = customer.Id,
                         Text = text,
                         IPAddress = ipAddress,
                         Published = true
                     };
-                    _forumService.InsertPost(forumPost, false);
+                    _forumService.InsertPost(post, false);
 
-                    forumTopic.NumPosts = 1;
-                    forumTopic.LastPostId = forumPost.Id;
-                    forumTopic.LastPostCustomerId = forumPost.CustomerId;
-                    forumTopic.LastPostTime = forumPost.CreatedOnUtc;
+                    topic.NumPosts = 1;
+                    topic.LastPostId = post.Id;
+                    topic.LastPostCustomerId = post.CustomerId;
+                    topic.LastPostTime = post.CreatedOnUtc;
 
-                    _forumService.UpdateTopic(forumTopic);
+                    _forumService.UpdateTopic(topic);
 
                     // Subscription.
                     if (_forumService.IsCustomerAllowedToSubscribe(customer))
@@ -971,7 +997,7 @@ public ActionResult TopicCreate(EditForumTopicModel model, bool captchaValid)
                             {
                                 SubscriptionGuid = Guid.NewGuid(),
                                 CustomerId = customer.Id,
-                                TopicId = forumTopic.Id,
+                                TopicId = topic.Id,
                                 CreatedOnUtc = utcNow
                             };
 
@@ -979,7 +1005,7 @@ public ActionResult TopicCreate(EditForumTopicModel model, bool captchaValid)
                         }
                     }
 
-                    return RedirectToRoute("TopicSlug", new {id = forumTopic.Id, slug = forumTopic.GetSeName()});
+                    return RedirectToRoute("TopicSlug", new {id = topic.Id, slug = topic.GetSeName()});
                 }
                 catch (Exception ex)
                 {
@@ -988,13 +1014,13 @@ public ActionResult TopicCreate(EditForumTopicModel model, bool captchaValid)
             }
 
             // Redisplay form.
+            model.Id = 0;
             model.TopicPriorities = ForumTopicTypesList();
             model.IsEdit = false;
             model.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnForumPage;
             model.ForumId = forum.Id;
             model.ForumName = forum.GetLocalized(x => x.Name);
             model.ForumSeName = forum.GetSeName();
-            model.Id = 0;
             model.IsCustomerAllowedToSetTopicPriority = _forumService.IsCustomerAllowedToSetTopicPriority(customer);
             model.IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer);
             model.ForumEditor = _forumSettings.ForumEditor;
@@ -1006,47 +1032,48 @@ public ActionResult TopicEdit(int id)
         {
             if (!_forumSettings.ForumsEnabled)
             {
-				return HttpNotFound();
+                return HttpNotFound();
             }
 
             var customer = Services.WorkContext.CurrentCustomer;
-            var forumTopic = _forumService.GetTopicById(id);
-            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup) || !_aclService.Authorize(forumTopic.Forum.ForumGroup))
+            var topic = _forumService.GetTopicById(id);
+
+            if (IsTopicVisible(topic, customer))
             {
                 return HttpNotFound();
             }
-
-            if (!_forumService.IsCustomerAllowedToEditTopic(customer, forumTopic))
+            if (!_forumService.IsCustomerAllowedToEditTopic(customer, topic))
             {
                 return new HttpUnauthorizedResult();
             }
 
-			var firstPost = forumTopic.GetFirstPost(_forumService);
-            var model = new EditForumTopicModel();
-
-            model.IsEdit = true;
-            model.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnForumPage;
-            model.TopicPriorities = ForumTopicTypesList();
-            model.ForumName = forumTopic.Forum.GetLocalized(x => x.Name);
-            model.ForumSeName = forumTopic.Forum.GetSeName();
-            model.Text = firstPost.Text;
-            model.Subject = forumTopic.Subject;
-            model.TopicTypeId = forumTopic.TopicTypeId;
-            model.Id = forumTopic.Id;
-            model.ForumId = forumTopic.Forum.Id;
-            model.ForumEditor = _forumSettings.ForumEditor;
-
-            model.IsCustomerAllowedToSetTopicPriority = _forumService.IsCustomerAllowedToSetTopicPriority(customer);
-            model.IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer);
+            var firstPost = topic.GetFirstPost(_forumService);
+            var model = new EditForumTopicModel
+            {
+                Id = topic.Id,
+                IsEdit = true,
+                Published = true,
+                DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnForumPage,
+                TopicPriorities = ForumTopicTypesList(),
+                ForumName = topic.Forum.GetLocalized(x => x.Name),
+                ForumSeName = topic.Forum.GetSeName(),
+                Text = firstPost?.Text,
+                Subject = topic.Subject,
+                TopicTypeId = topic.TopicTypeId,
+                ForumId = topic.Forum.Id,
+                ForumEditor = _forumSettings.ForumEditor,
+                IsCustomerAllowedToSetTopicPriority = _forumService.IsCustomerAllowedToSetTopicPriority(customer),
+                IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer)
+            };
 
             // Subscription.
             if (model.IsCustomerAllowedToSubscribe)
             {
-                var forumSubscription = _forumService.GetAllSubscriptions(customer.Id, 0, forumTopic.Id, 0, 1).FirstOrDefault();
+                var forumSubscription = _forumService.GetAllSubscriptions(customer.Id, 0, topic.Id, 0, 1).FirstOrDefault();
                 model.Subscribed = forumSubscription != null;
             }
 
-			CreateForumBreadcrumb(forum: forumTopic.Forum, topic: forumTopic);
+			CreateForumBreadcrumb(forum: topic.Forum, topic: topic);
 
 			return View(model);
         }
@@ -1063,11 +1090,11 @@ public ActionResult TopicEdit(EditForumTopicModel model, bool captchaValid)
 
             var customer = Services.WorkContext.CurrentCustomer;
             var forumTopic = _forumService.GetTopicById(model.Id);
-            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup) || !_aclService.Authorize(forumTopic.Forum.ForumGroup))
+
+            if (IsTopicVisible(forumTopic, customer))
             {
                 return HttpNotFound();
             }
-
             if (!_forumService.IsCustomerAllowedToEditTopic(customer, forumTopic))
             {
                 return new HttpUnauthorizedResult();
@@ -1171,6 +1198,7 @@ public ActionResult TopicEdit(EditForumTopicModel model, bool captchaValid)
             // Redisplay form.
             model.TopicPriorities = ForumTopicTypesList();
             model.IsEdit = true;
+            model.Published = forumTopic.Published;
             model.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnForumPage;
             model.ForumName = forumTopic.Forum.GetLocalized(x => x.Name);
             model.ForumSeName = forumTopic.Forum.GetSeName();
@@ -1190,19 +1218,20 @@ public ActionResult TopicDelete(int id)
                 return HttpNotFound();
             }
 
-            var forumTopic = _forumService.GetTopicById(id);
-            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup) || !_aclService.Authorize(forumTopic.Forum.ForumGroup))
+            var customer = Services.WorkContext.CurrentCustomer;
+            var topic = _forumService.GetTopicById(id);
+
+            if (IsTopicVisible(topic, customer))
             {
                 return HttpNotFound();
             }
-
-            if (!_forumService.IsCustomerAllowedToDeleteTopic(Services.WorkContext.CurrentCustomer, forumTopic))
+            if (!_forumService.IsCustomerAllowedToDeleteTopic(customer, topic))
             {
                 return new HttpUnauthorizedResult();
             }
 
-            var forum = _forumService.GetForumById(forumTopic.ForumId);
-            _forumService.DeleteTopic(forumTopic);
+            var forum = _forumService.GetForumById(topic.ForumId);
+            _forumService.DeleteTopic(topic);
 
             if (forum != null)
             {
@@ -1225,13 +1254,13 @@ public ActionResult PostCreate(int id, int? quote)
             }
 
             var customer = Services.WorkContext.CurrentCustomer;
-            var forumTopic = _forumService.GetTopicById(id);
-            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup) || !_aclService.Authorize(forumTopic.Forum.ForumGroup))
+            var topic = _forumService.GetTopicById(id);
+
+            if (topic == null || !_storeMappingService.Authorize(topic.Forum.ForumGroup) || !_aclService.Authorize(topic.Forum.ForumGroup))
             {
                 return HttpNotFound();
             }
-
-            if (!_forumService.IsCustomerAllowedToCreatePost(customer, forumTopic))
+            if (!_forumService.IsCustomerAllowedToCreatePost(customer, topic))
             {
                 return new HttpUnauthorizedResult();
             }
@@ -1239,21 +1268,22 @@ public ActionResult PostCreate(int id, int? quote)
             var model = new EditForumPostModel
             {
                 Id = 0,
-                ForumTopicId = forumTopic.Id,
+                ForumTopicId = topic.Id,
                 IsEdit = false,
+                Published = true,
                 DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnForumPage,
                 ForumEditor = _forumSettings.ForumEditor,
-                ForumName = forumTopic.Forum.GetLocalized(x => x.Name),
-                ForumTopicSubject = forumTopic.Subject,
-                ForumTopicSeName = forumTopic.GetSeName(),
+                ForumName = topic.Forum.GetLocalized(x => x.Name),
+                ForumTopicSubject = topic.Subject,
+                ForumTopicSeName = topic.GetSeName(),
                 IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer),
-                Subscribed = false,
+                Subscribed = false
             };
             
             // Subscription.
             if (model.IsCustomerAllowedToSubscribe)
             {
-                var forumSubscription = _forumService.GetAllSubscriptions(customer.Id, 0, forumTopic.Id, 0, 1).FirstOrDefault();
+                var forumSubscription = _forumService.GetAllSubscriptions(customer.Id, 0, topic.Id, 0, 1).FirstOrDefault();
                 model.Subscribed = forumSubscription != null;
             }
 
@@ -1262,7 +1292,7 @@ public ActionResult PostCreate(int id, int? quote)
             if (quote.HasValue)
             {
                 var quotePost = _forumService.GetPostById(quote.Value);
-                if (quotePost != null && quotePost.TopicId == forumTopic.Id)
+                if (quotePost != null && quotePost.TopicId == topic.Id)
                 {
                     var quotePostText = quotePost.Text;
 
@@ -1279,7 +1309,7 @@ public ActionResult PostCreate(int id, int? quote)
                 }
             }
 
-			CreateForumBreadcrumb(forum: forumTopic.Forum, topic: forumTopic);
+			CreateForumBreadcrumb(forum: topic.Forum, topic: topic);
 			return View(model);
         }
 
@@ -1295,13 +1325,13 @@ public ActionResult PostCreate(EditForumPostModel model, bool captchaValid)
             }
 
             var customer = Services.WorkContext.CurrentCustomer;
-            var forumTopic = _forumService.GetTopicById(model.ForumTopicId);
-            if (forumTopic == null || !_storeMappingService.Authorize(forumTopic.Forum.ForumGroup) || !_aclService.Authorize(forumTopic.Forum.ForumGroup))
+            var topic = _forumService.GetTopicById(model.ForumTopicId);
+
+            if (topic == null || !_storeMappingService.Authorize(topic.Forum.ForumGroup) || !_aclService.Authorize(topic.Forum.ForumGroup))
             {
                 return HttpNotFound();
             }
-
-            if (!_forumService.IsCustomerAllowedToCreatePost(customer, forumTopic))
+            if (!_forumService.IsCustomerAllowedToCreatePost(customer, topic))
             {
                 return new HttpUnauthorizedResult();
             }
@@ -1327,7 +1357,7 @@ public ActionResult PostCreate(EditForumPostModel model, bool captchaValid)
 
                     var forumPost = new ForumPost
                     {
-                        TopicId = forumTopic.Id,
+                        TopicId = topic.Id,
                         CustomerId = customer.Id,
                         Text = text,
                         IPAddress = ipAddress,
@@ -1364,8 +1394,8 @@ public ActionResult PostCreate(EditForumPostModel model, bool captchaValid)
                         }
                     }
 
-                    var pageSize = _forumSettings.PostsPageSize > 0 ? _forumSettings.PostsPageSize : 10;
-                    var pageIndex = (_forumService.CalculateTopicPageIndex(forumPost.TopicId, pageSize, forumPost.Id) + 1);
+                    var pageSize = _forumSettings.PostsPageSize > 0 ? _forumSettings.PostsPageSize : 20;
+                    var pageIndex = _forumService.CalculateTopicPageIndex(forumPost.TopicId, pageSize, forumPost.Id) + 1;
                     var url = string.Empty;
 
                     if (pageIndex > 1)
@@ -1389,10 +1419,10 @@ public ActionResult PostCreate(EditForumPostModel model, bool captchaValid)
             model.Id = 0;
             model.IsEdit = false;
             model.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnForumPage;
-            model.ForumName = forumTopic.Forum.GetLocalized(x => x.Name);
-            model.ForumTopicId = forumTopic.Id;
-            model.ForumTopicSubject = forumTopic.Subject;
-            model.ForumTopicSeName = forumTopic.GetSeName();
+            model.ForumName = topic.Forum.GetLocalized(x => x.Name);
+            model.ForumTopicId = topic.Id;
+            model.ForumTopicSubject = topic.Subject;
+            model.ForumTopicSeName = topic.GetSeName();
             model.IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer);
             model.ForumEditor = _forumSettings.ForumEditor;
             
@@ -1407,41 +1437,41 @@ public ActionResult PostEdit(int id)
             }
 
             var customer = Services.WorkContext.CurrentCustomer;
-            var forumPost = _forumService.GetPostById(id);
+            var post = _forumService.GetPostById(id);
 
-            if (forumPost == null || !_storeMappingService.Authorize(forumPost.ForumTopic.Forum.ForumGroup) || !_aclService.Authorize(forumPost.ForumTopic.Forum.ForumGroup))
+            if (post == null || !_storeMappingService.Authorize(post.ForumTopic.Forum.ForumGroup) || !_aclService.Authorize(post.ForumTopic.Forum.ForumGroup))
             {
                 return HttpNotFound();
             }
-
-            if (!_forumService.IsCustomerAllowedToEditPost(customer, forumPost))
+            if (!_forumService.IsCustomerAllowedToEditPost(customer, post))
             {
                 return new HttpUnauthorizedResult();
             }
 
             var model = new EditForumPostModel
             {
-                Id = forumPost.Id,
+                Id = post.Id,
                 IsEdit = true,
-                ForumTopicId = forumPost.ForumTopic.Id,
+                Published = true,
+                ForumTopicId = post.ForumTopic.Id,
                 DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnForumPage,
                 ForumEditor = _forumSettings.ForumEditor,
-                ForumName = forumPost.ForumTopic.Forum.GetLocalized(x => x.Name),
-                ForumTopicSubject = forumPost.ForumTopic.Subject,
-                ForumTopicSeName = forumPost.ForumTopic.GetSeName(),
+                ForumName = post.ForumTopic.Forum.GetLocalized(x => x.Name),
+                ForumTopicSubject = post.ForumTopic.Subject,
+                ForumTopicSeName = post.ForumTopic.GetSeName(),
                 IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer),
                 Subscribed = false,
-                Text = forumPost.Text,
+                Text = post.Text
             };
 
             // Subscription.
             if (model.IsCustomerAllowedToSubscribe)
             {
-                var forumSubscription = _forumService.GetAllSubscriptions(customer.Id, 0, forumPost.ForumTopic.Id, 0, 1).FirstOrDefault();
+                var forumSubscription = _forumService.GetAllSubscriptions(customer.Id, 0, post.ForumTopic.Id, 0, 1).FirstOrDefault();
                 model.Subscribed = forumSubscription != null;
             }
 
-			CreateForumBreadcrumb(forum: forumPost.ForumTopic.Forum, topic: forumPost.ForumTopic);
+			CreateForumBreadcrumb(forum: post.ForumTopic.Forum, topic: post.ForumTopic);
 
 			return View(model);
         }
@@ -1457,13 +1487,14 @@ public ActionResult PostEdit(EditForumPostModel model, bool captchaValid)
             }
 
             var customer = Services.WorkContext.CurrentCustomer;
-            var forumPost = _forumService.GetPostById(model.Id);
-            if (forumPost == null || !_storeMappingService.Authorize(forumPost.ForumTopic.Forum.ForumGroup) || !_aclService.Authorize(forumPost.ForumTopic.Forum.ForumGroup))
+            var post = _forumService.GetPostById(model.Id);
+
+            if (post == null || !_storeMappingService.Authorize(post.ForumTopic.Forum.ForumGroup) || !_aclService.Authorize(post.ForumTopic.Forum.ForumGroup))
             {
                 return HttpNotFound();
             }
 
-            if (!_forumService.IsCustomerAllowedToEditPost(customer, forumPost))
+            if (!_forumService.IsCustomerAllowedToEditPost(customer, post))
             {
                 return new HttpUnauthorizedResult();
             }
@@ -1485,14 +1516,14 @@ public ActionResult PostEdit(EditForumPostModel model, bool captchaValid)
                         text = text.Substring(0, maxPostLength);
                     }
 
-                    forumPost.Text = text;
+                    post.Text = text;
 
-                    _forumService.UpdatePost(forumPost);
+                    _forumService.UpdatePost(post);
 
                     // Subscription.
                     if (_forumService.IsCustomerAllowedToSubscribe(customer))
                     {
-                        var forumSubscription = _forumService.GetAllSubscriptions(customer.Id, 0, forumPost.TopicId, 0, 1).FirstOrDefault();
+                        var forumSubscription = _forumService.GetAllSubscriptions(customer.Id, 0, post.TopicId, 0, 1).FirstOrDefault();
                         if (model.Subscribed)
                         {
                             if (forumSubscription == null)
@@ -1501,7 +1532,7 @@ public ActionResult PostEdit(EditForumPostModel model, bool captchaValid)
                                 {
                                     SubscriptionGuid = Guid.NewGuid(),
                                     CustomerId = customer.Id,
-                                    TopicId = forumPost.TopicId,
+                                    TopicId = post.TopicId,
                                     CreatedOnUtc = utcNow
                                 };
 
@@ -1517,20 +1548,20 @@ public ActionResult PostEdit(EditForumPostModel model, bool captchaValid)
                         }
                     }
 
-                    var pageSize = _forumSettings.PostsPageSize > 0 ? _forumSettings.PostsPageSize : 10;
-                    var pageIndex = (_forumService.CalculateTopicPageIndex(forumPost.TopicId, pageSize, forumPost.Id) + 1);
+                    var pageSize = _forumSettings.PostsPageSize > 0 ? _forumSettings.PostsPageSize : 20;
+                    var pageIndex = (_forumService.CalculateTopicPageIndex(post.TopicId, pageSize, post.Id) + 1);
                     var url = string.Empty;
 
                     if (pageIndex > 1)
                     {
-                        url = Url.RouteUrl("TopicSlug", new { id = forumPost.TopicId, slug = forumPost.ForumTopic.GetSeName(), page = pageIndex });
+                        url = Url.RouteUrl("TopicSlug", new { id = post.TopicId, slug = post.ForumTopic.GetSeName(), page = pageIndex });
                     }
                     else
                     {
-                        url = Url.RouteUrl("TopicSlug", new { id = forumPost.TopicId, slug = forumPost.ForumTopic.GetSeName() });
+                        url = Url.RouteUrl("TopicSlug", new { id = post.TopicId, slug = post.ForumTopic.GetSeName() });
                     }
 
-                    return Redirect(string.Format("{0}#{1}", url, forumPost.Id));
+                    return Redirect(string.Format("{0}#{1}", url, post.Id));
                 }
                 catch (Exception ex)
                 {
@@ -1540,12 +1571,13 @@ public ActionResult PostEdit(EditForumPostModel model, bool captchaValid)
 
             // Redisplay form.
             model.IsEdit = true;
+            model.Published = post.Published;
             model.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnForumPage;
-            model.ForumName = forumPost.ForumTopic.Forum.GetLocalized(x => x.Name);
-            model.ForumTopicId = forumPost.ForumTopic.Id;
-            model.ForumTopicSubject = forumPost.ForumTopic.Subject;
-            model.ForumTopicSeName = forumPost.ForumTopic.GetSeName();
-            model.Id = forumPost.Id;
+            model.ForumName = post.ForumTopic.Forum.GetLocalized(x => x.Name);
+            model.ForumTopicId = post.ForumTopic.Id;
+            model.ForumTopicSubject = post.ForumTopic.Subject;
+            model.ForumTopicSeName = post.ForumTopic.GetSeName();
+            model.Id = post.Id;
             model.IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer);
             model.ForumEditor = _forumSettings.ForumEditor;
             
@@ -1559,25 +1591,26 @@ public ActionResult PostDelete(int id)
                 return HttpNotFound();
             }
 
-            var forumPost = _forumService.GetPostById(id);
-            if (forumPost == null || !_storeMappingService.Authorize(forumPost.ForumTopic.Forum.ForumGroup) || !_aclService.Authorize(forumPost.ForumTopic.Forum.ForumGroup))
+            var post = _forumService.GetPostById(id);
+
+            if (post == null || !_storeMappingService.Authorize(post.ForumTopic.Forum.ForumGroup) || !_aclService.Authorize(post.ForumTopic.Forum.ForumGroup))
             {
                 return HttpNotFound();
             }
 
-            if (!_forumService.IsCustomerAllowedToDeletePost(Services.WorkContext.CurrentCustomer, forumPost))
+            if (!_forumService.IsCustomerAllowedToDeletePost(Services.WorkContext.CurrentCustomer, post))
             {
                 return new HttpUnauthorizedResult();
             }
 
-            var forumTopic = forumPost.ForumTopic;
+            var forumTopic = post.ForumTopic;
             var forumId = forumTopic.Forum.Id;
             var forumSlug = forumTopic.Forum.GetSeName();
 
-            _forumService.DeletePost(forumPost);
+            _forumService.DeletePost(post);
 
             // Get topic one more time because it can be deleted (first or only post deleted).
-            forumTopic = _forumService.GetTopicById(forumPost.TopicId);
+            forumTopic = _forumService.GetTopicById(post.TopicId);
             if (forumTopic == null)
             {
                 return RedirectToRoute("ForumSlug", new { id = forumId, slug = forumSlug });
diff --git a/src/Presentation/SmartStore.Web/Models/Boards/EditForumPostModel.cs b/src/Presentation/SmartStore.Web/Models/Boards/EditForumPostModel.cs
index 1842af54ec..4e19404cf4 100644
--- a/src/Presentation/SmartStore.Web/Models/Boards/EditForumPostModel.cs
+++ b/src/Presentation/SmartStore.Web/Models/Boards/EditForumPostModel.cs
@@ -12,6 +12,7 @@ public partial class EditForumPostModel : EntityModelBase
     {
         public int ForumTopicId { get; set; }
         public bool IsEdit { get; set; }
+        public bool Published { get; set; }
         public bool DisplayCaptcha { get; set; }
 
         [AllowHtml]
diff --git a/src/Presentation/SmartStore.Web/Models/Boards/EditForumTopicModel.cs b/src/Presentation/SmartStore.Web/Models/Boards/EditForumTopicModel.cs
index d0ba916f22..80b2e7ec7d 100644
--- a/src/Presentation/SmartStore.Web/Models/Boards/EditForumTopicModel.cs
+++ b/src/Presentation/SmartStore.Web/Models/Boards/EditForumTopicModel.cs
@@ -18,6 +18,7 @@ public EditForumTopicModel()
 
         public bool IsEdit { get; set; }
         public bool DisplayCaptcha { get; set; }
+        public bool Published { get; set; }
 
         public int ForumId { get; set; }
         public LocalizedValue<string> ForumName { get; set; }
diff --git a/src/Presentation/SmartStore.Web/Models/Boards/ForumPostModel.cs b/src/Presentation/SmartStore.Web/Models/Boards/ForumPostModel.cs
index 1449c88c4a..b7c7806ab8 100644
--- a/src/Presentation/SmartStore.Web/Models/Boards/ForumPostModel.cs
+++ b/src/Presentation/SmartStore.Web/Models/Boards/ForumPostModel.cs
@@ -21,6 +21,7 @@ public partial class ForumPostModel : EntityModelBase
         public bool IsCustomerGuest { get; set; }
 
         public string PostCreatedOnStr { get; set; }
+        public bool Published { get; set; }
 
         public bool ShowCustomersPostCount { get; set; }
         public int ForumPostCount { get; set; }
diff --git a/src/Presentation/SmartStore.Web/Models/Boards/ForumTopicRowModel.cs b/src/Presentation/SmartStore.Web/Models/Boards/ForumTopicRowModel.cs
index 2464c9c9e7..527fbaf835 100644
--- a/src/Presentation/SmartStore.Web/Models/Boards/ForumTopicRowModel.cs
+++ b/src/Presentation/SmartStore.Web/Models/Boards/ForumTopicRowModel.cs
@@ -15,6 +15,7 @@ public ForumTopicRowModel()
         public string SeName { get; set; }
         public int FirstPostId { get; set; }
         public int LastPostId { get; set; }
+        public bool Published { get; set; }
 
         public ForumTopicType ForumTopicType { get; set; }
         public int NumPosts { get; set; }
diff --git a/src/Presentation/SmartStore.Web/Models/Boards/LastPostModel.cs b/src/Presentation/SmartStore.Web/Models/Boards/LastPostModel.cs
index f68fb56944..ee310c0f7e 100644
--- a/src/Presentation/SmartStore.Web/Models/Boards/LastPostModel.cs
+++ b/src/Presentation/SmartStore.Web/Models/Boards/LastPostModel.cs
@@ -14,7 +14,8 @@ public partial class LastPostModel : EntityModelBase
         public bool IsCustomerGuest { get; set; }
 
         public string PostCreatedOnStr { get; set; }
-        
+        public bool Published { get; set; }
+
         public bool ShowTopic { get; set; }
     }
 }
\ No newline at end of file
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/TopicMove.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/TopicMove.cshtml
index 477b4b85a7..be35d61a84 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/TopicMove.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/TopicMove.cshtml
@@ -1,5 +1,5 @@
-@model TopicMoveModel
-@using SmartStore.Web.Models.Boards;
+@using SmartStore.Web.Models.Boards;
+@model TopicMoveModel
 @{    
     Layout = "_Layout";
     Html.AddTitleParts(T("Forum.PageTitle.MoveTopic").Text);
@@ -23,7 +23,7 @@
                 <button type="submit" class="btn btn-primary">
 					<span>@T("Forum.Submit")</span>
 				</button>
-                <button class="btn btn-danger" onclick="setLocation('@Url.RouteUrl("TopicSlug", new { id = Model.Id, slug = Model.TopicSeName })')">
+                <button class="btn btn-secondary" onclick="setLocation('@Url.RouteUrl("TopicSlug", new { id = Model.Id, slug = Model.TopicSeName })')">
                     <span>@T("Forum.Cancel")</span>
                 </button>
             </div>

From dd6c3de5b3a209dd4df98b9baffa7a99d26abff0 Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Wed, 26 Sep 2018 03:22:55 +0200
Subject: [PATCH 10/71] More work on Storytelling feature

---
 .../Controllers/ContollerExtensions.cs                 |  3 +--
 .../UI/Blocks/BlockHandlerBase.cs                      | 10 ++++++----
 .../UI/Blocks/BlockMetadata.cs                         |  2 +-
 .../UI/Blocks/IBlockContainer.cs                       |  4 ++--
 .../UI/Blocks/IBlockHandler.cs                         |  5 ++---
 .../Administration/Controllers/PluginController.cs     |  1 +
 .../Views/CheckoutAttribute/ValueCreatePopup.cshtml    |  2 ++
 .../Views/CheckoutAttribute/ValueEditPopup.cshtml      |  2 ++
 src/Presentation/SmartStore.Web/Web.config             |  2 +-
 9 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/src/Presentation/SmartStore.Web.Framework/Controllers/ContollerExtensions.cs b/src/Presentation/SmartStore.Web.Framework/Controllers/ContollerExtensions.cs
index c6171c46a5..94e9ff679c 100644
--- a/src/Presentation/SmartStore.Web.Framework/Controllers/ContollerExtensions.cs
+++ b/src/Presentation/SmartStore.Web.Framework/Controllers/ContollerExtensions.cs
@@ -75,8 +75,7 @@ public static string RenderPartialViewToString(this ControllerBase controller, s
 			{
 				controller.ViewData.AddRange(CommonHelper.ObjectToDictionary(additionalViewData));
 
-				var vdd = additionalViewData as ViewDataDictionary;
-				if (vdd != null)
+				if (additionalViewData is ViewDataDictionary vdd)
 				{
 					controller.ViewData.TemplateInfo.HtmlFieldPrefix = vdd.TemplateInfo.HtmlFieldPrefix;
 				}
diff --git a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockHandlerBase.cs b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockHandlerBase.cs
index 02b7d36ab7..93c100e955 100644
--- a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockHandlerBase.cs
+++ b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockHandlerBase.cs
@@ -62,12 +62,12 @@ public virtual void Save(T block, IBlockEntity entity)
 			entity.Model = JsonConvert.SerializeObject(block, Formatting.None, settings);
 		}
 
-		public void Render(IBlockContainer<T> element, string[] templates, HtmlHelper htmlHelper)
+		public void Render(IBlockContainer element, string[] templates, HtmlHelper htmlHelper)
 		{
 			RenderCore(element, templates, htmlHelper, htmlHelper.ViewContext.Writer);
 		}
 
-		public IHtmlString ToHtmlString(IBlockContainer<T> element, string[] templates, HtmlHelper htmlHelper)
+		public IHtmlString ToHtmlString(IBlockContainer element, string[] templates, HtmlHelper htmlHelper)
 		{
 			using (var writer = new StringWriter(CultureInfo.CurrentCulture))
 			{
@@ -76,7 +76,7 @@ public IHtmlString ToHtmlString(IBlockContainer<T> element, string[] templates,
 			}
 		}
 
-		protected virtual void RenderCore(IBlockContainer<T> element, string[] templates, HtmlHelper htmlHelper, TextWriter textWriter)
+		protected virtual void RenderCore(IBlockContainer element, string[] templates, HtmlHelper htmlHelper, TextWriter textWriter)
 		{
 			Guard.NotNull(element, nameof(element));
 			Guard.NotNull(templates, nameof(templates));
@@ -89,6 +89,8 @@ protected virtual void RenderCore(IBlockContainer<T> element, string[] templates
 				throw new InvalidOperationException("The return value of the 'GetRoute()' method cannot be NULL.");
 			}
 
+			routeInfo.RouteValues["model"] = element.Block;
+
 			var originalWriter = htmlHelper.ViewContext.Writer;
 			htmlHelper.ViewContext.Writer = textWriter;
 
@@ -98,7 +100,7 @@ protected virtual void RenderCore(IBlockContainer<T> element, string[] templates
 			}
 		}
 
-		protected abstract RouteInfo GetRoute(IBlockContainer<T> element, string template);
+		protected abstract RouteInfo GetRoute(IBlockContainer element, string template);
 
 		/// <summary>
 		/// Add locales for localizable entities
diff --git a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockMetadata.cs b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockMetadata.cs
index ca5b8a1a7b..952d7690be 100644
--- a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockMetadata.cs
+++ b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockMetadata.cs
@@ -19,7 +19,7 @@ public BlockAttribute(string systemName)
 		public bool IsInternal { get; set; }
 	}
 
-	public class IBlockMetadata
+	public interface IBlockMetadata
 	{
 		string SystemName { get; }
 		string FriendlyName { get; }
diff --git a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockContainer.cs b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockContainer.cs
index 71c18aa7b4..1cd523a213 100644
--- a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockContainer.cs
+++ b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockContainer.cs
@@ -2,10 +2,10 @@
 
 namespace SmartStore.Web.Framework.UI.Blocks
 {
-	public interface IBlockContainer<out T> where T : IBlock
+	public interface IBlockContainer
 	{
 		string BlockType { get; }
-		T Block { get; }
+		IBlock Block { get; }
 		IBlockMetadata Metadata { get; }
 		//IBlockHandler<T> Handler { get; }
 		
diff --git a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockHandler.cs b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockHandler.cs
index 3d982722b5..5032cb037e 100644
--- a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockHandler.cs
+++ b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockHandler.cs
@@ -6,6 +6,8 @@ namespace SmartStore.Web.Framework.UI.Blocks
 {
 	public interface IBlockHandler
 	{
+		void Render(IBlockContainer element, string[] templates, HtmlHelper htmlHeper);
+		IHtmlString ToHtmlString(IBlockContainer element, string[] templates, HtmlHelper htmlHelper);
 	}
 
 	public interface IBlockHandler<T> : IBlockHandler where T : IBlock
@@ -13,8 +15,5 @@ public interface IBlockHandler<T> : IBlockHandler where T : IBlock
 		T Create(IBlockEntity entity);
 		T Load(IBlockEntity entity, bool editMode);
 		void Save(T block, IBlockEntity entity);
-
-		void Render(IBlockContainer<T> element, string[] templates, HtmlHelper htmlHeper);
-		IHtmlString ToHtmlString(IBlockContainer<T> element, string[] templates, HtmlHelper htmlHelper);
 	}
 }
diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/PluginController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/PluginController.cs
index 5627bacdc2..54795e1195 100644
--- a/src/Presentation/SmartStore.Web/Administration/Controllers/PluginController.cs
+++ b/src/Presentation/SmartStore.Web/Administration/Controllers/PluginController.cs
@@ -589,6 +589,7 @@ public ActionResult EditProviderPopup(string btnId, ProviderModel model)
 
 			ViewBag.RefreshPage = true;
 			ViewBag.btnId = btnId;
+
 			return View(model);
 		}
 
diff --git a/src/Presentation/SmartStore.Web/Administration/Views/CheckoutAttribute/ValueCreatePopup.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/CheckoutAttribute/ValueCreatePopup.cshtml
index e8a09b0d6c..12af5a9b10 100644
--- a/src/Presentation/SmartStore.Web/Administration/Views/CheckoutAttribute/ValueCreatePopup.cshtml
+++ b/src/Presentation/SmartStore.Web/Administration/Views/CheckoutAttribute/ValueCreatePopup.cshtml
@@ -1,8 +1,10 @@
 @model CheckoutAttributeValueModel
+
 @{
 	Layout = "_AdminPopupLayout";
 	ViewBag.Title = T("Admin.Catalog.Attributes.CheckoutAttributes.Values.AddNew").Text;
 }
+
 @using (Html.BeginForm())
 {
     <div class="section-header">
diff --git a/src/Presentation/SmartStore.Web/Administration/Views/CheckoutAttribute/ValueEditPopup.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/CheckoutAttribute/ValueEditPopup.cshtml
index feed2b2e16..1095ec1afe 100644
--- a/src/Presentation/SmartStore.Web/Administration/Views/CheckoutAttribute/ValueEditPopup.cshtml
+++ b/src/Presentation/SmartStore.Web/Administration/Views/CheckoutAttribute/ValueEditPopup.cshtml
@@ -1,8 +1,10 @@
 @model CheckoutAttributeValueModel
+
 @{
     Layout = "_AdminPopupLayout";
     ViewBag.Title = T("Admin.Catalog.Attributes.CheckoutAttributes.Values.EditValueDetails").Text;
 }
+
 @using (Html.BeginForm())
 {
     <div class="section-header">
diff --git a/src/Presentation/SmartStore.Web/Web.config b/src/Presentation/SmartStore.Web/Web.config
index 2a6a78e3f7..bbc22f262e 100644
--- a/src/Presentation/SmartStore.Web/Web.config
+++ b/src/Presentation/SmartStore.Web/Web.config
@@ -79,7 +79,7 @@
     <sessionState configSource="Config\SessionState.config" />
     <trace enabled="true" localOnly="true" pageOutput="true" requestLimit="40" />
     <httpRuntime targetFramework="4.5.2" maxRequestLength="1536000" executionTimeout="5400" maxQueryStringLength="16384" fcnMode="Single" />
-    <compilation debug="true" targetFramework="4.6.1" numRecompilesBeforeAppRestart="254" batch="true" optimizeCompilations="true">
+    <compilation debug="true" targetFramework="4.6.1" numRecompilesBeforeAppRestart="256" batch="true" optimizeCompilations="true">
       <assemblies>
         <add assembly="System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
         <add assembly="System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />

From aedfad773e34cc20636bdbc3b0a982875b4c0380 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Wed, 26 Sep 2018 12:39:41 +0200
Subject: [PATCH 11/71] Please execute "update-database -TargetMigration
 NewsletterSubscriptionLanguage"

---
 .../SmartStore.Core/Domain/Forums/Forum.cs    |  3 ++
 .../Domain/Forums/ForumGroup.cs               | 12 +++--
 .../Domain/Forums/ForumPost.cs                |  4 +-
 .../Domain/Forums/ForumTopic.cs               |  8 ++++
 .../201809251233170_ForumGroupAcl.cs          | 22 ---------
 ...201809261026134_ForumGroupAcl.Designer.cs} |  2 +-
 .../201809261026134_ForumGroupAcl.cs          | 48 +++++++++++++++++++
 ...esx => 201809261026134_ForumGroupAcl.resx} |  2 +-
 .../SmartStore.Data/SmartStore.Data.csproj    | 10 ++--
 9 files changed, 77 insertions(+), 34 deletions(-)
 delete mode 100644 src/Libraries/SmartStore.Data/Migrations/201809251233170_ForumGroupAcl.cs
 rename src/Libraries/SmartStore.Data/Migrations/{201809251233170_ForumGroupAcl.Designer.cs => 201809261026134_ForumGroupAcl.Designer.cs} (92%)
 create mode 100644 src/Libraries/SmartStore.Data/Migrations/201809261026134_ForumGroupAcl.cs
 rename src/Libraries/SmartStore.Data/Migrations/{201809251233170_ForumGroupAcl.resx => 201809261026134_ForumGroupAcl.resx} (72%)

diff --git a/src/Libraries/SmartStore.Core/Domain/Forums/Forum.cs b/src/Libraries/SmartStore.Core/Domain/Forums/Forum.cs
index 0b268be1f1..b4cedb8d01 100644
--- a/src/Libraries/SmartStore.Core/Domain/Forums/Forum.cs
+++ b/src/Libraries/SmartStore.Core/Domain/Forums/Forum.cs
@@ -1,4 +1,5 @@
 using System;
+using System.ComponentModel.DataAnnotations.Schema;
 using SmartStore.Core.Domain.Localization;
 using SmartStore.Core.Domain.Seo;
 
@@ -12,6 +13,7 @@ public partial class Forum : BaseEntity, IAuditable, ILocalizedEntity, ISlugSupp
         /// <summary>
         /// Gets or sets the forum group identifier
         /// </summary>
+        [Index("IX_ForumGroupId_DisplayOrder", Order = 0)]
         public int ForumGroupId { get; set; }
 
         /// <summary>
@@ -57,6 +59,7 @@ public partial class Forum : BaseEntity, IAuditable, ILocalizedEntity, ISlugSupp
         /// <summary>
         /// Gets or sets the display order
         /// </summary>
+        [Index("IX_ForumGroupId_DisplayOrder", Order = 1)]
         public int DisplayOrder { get; set; }
 
         /// <summary>
diff --git a/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs b/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs
index 7974973f45..ae83f4f8f9 100644
--- a/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs
+++ b/src/Libraries/SmartStore.Core/Domain/Forums/ForumGroup.cs
@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations.Schema;
 using SmartStore.Core.Domain.Localization;
 using SmartStore.Core.Domain.Security;
 using SmartStore.Core.Domain.Seo;
@@ -27,6 +28,7 @@ public partial class ForumGroup : BaseEntity, IAuditable, IStoreMappingSupported
         /// <summary>
         /// Gets or sets the display order
         /// </summary>
+        [Index]
         public int DisplayOrder { get; set; }
 
         /// <summary>
@@ -39,14 +41,16 @@ public partial class ForumGroup : BaseEntity, IAuditable, IStoreMappingSupported
         /// </summary>
         public DateTime UpdatedOnUtc { get; set; }
 
-		/// <summary>
-		/// Gets or sets a value indicating whether the entity is limited/restricted to certain stores
-		/// </summary>
-		public bool LimitedToStores { get; set; }
+        /// <summary>
+        /// Gets or sets a value indicating whether the entity is limited/restricted to certain stores
+        /// </summary>
+        [Index]
+        public bool LimitedToStores { get; set; }
 
         /// <summary>
         /// Gets or sets a value indicating whether the entity is subject to ACL
         /// </summary>
+        [Index]
         public bool SubjectToAcl { get; set; }
 
         /// <summary>
diff --git a/src/Libraries/SmartStore.Core/Domain/Forums/ForumPost.cs b/src/Libraries/SmartStore.Core/Domain/Forums/ForumPost.cs
index 2cfecbfe97..292615a8d3 100644
--- a/src/Libraries/SmartStore.Core/Domain/Forums/ForumPost.cs
+++ b/src/Libraries/SmartStore.Core/Domain/Forums/ForumPost.cs
@@ -1,4 +1,5 @@
 using System;
+using System.ComponentModel.DataAnnotations.Schema;
 using SmartStore.Core.Domain.Customers;
 
 namespace SmartStore.Core.Domain.Forums
@@ -31,6 +32,7 @@ public partial class ForumPost : BaseEntity, IAuditable
         /// <summary>
         /// Gets or sets the date and time of instance creation
         /// </summary>
+        [Index]
         public DateTime CreatedOnUtc { get; set; }
 
         /// <summary>
@@ -41,6 +43,7 @@ public partial class ForumPost : BaseEntity, IAuditable
         /// <summary>
         /// Gets or sets a value indicating whether the entity is published
         /// </summary>
+        [Index]
         public bool Published { get; set; }
 
         /// <summary>
@@ -52,6 +55,5 @@ public partial class ForumPost : BaseEntity, IAuditable
         /// Gets the customer
         /// </summary>
         public virtual Customer Customer { get; set; }
-
     }
 }
diff --git a/src/Libraries/SmartStore.Core/Domain/Forums/ForumTopic.cs b/src/Libraries/SmartStore.Core/Domain/Forums/ForumTopic.cs
index b77c216592..c31e029a50 100644
--- a/src/Libraries/SmartStore.Core/Domain/Forums/ForumTopic.cs
+++ b/src/Libraries/SmartStore.Core/Domain/Forums/ForumTopic.cs
@@ -1,4 +1,5 @@
 using System;
+using System.ComponentModel.DataAnnotations.Schema;
 using SmartStore.Core.Domain.Customers;
 
 namespace SmartStore.Core.Domain.Forums
@@ -11,6 +12,7 @@ public partial class ForumTopic : BaseEntity, IAuditable
         /// <summary>
         /// Gets or sets the forum identifier
         /// </summary>
+        [Index("IX_ForumId_Published", Order = 0)]
         public int ForumId { get; set; }
 
         /// <summary>
@@ -21,16 +23,19 @@ public partial class ForumTopic : BaseEntity, IAuditable
         /// <summary>
         /// Gets or sets the topic type identifier
         /// </summary>
+        [Index("IX_TopicTypeId_LastPostTime", Order = 0)]
         public int TopicTypeId { get; set; }
 
         /// <summary>
         /// Gets or sets the subject
         /// </summary>
+        [Index]
         public string Subject { get; set; }
 
         /// <summary>
         /// Gets or sets the number of posts
         /// </summary>
+        [Index]
         public int NumPosts { get; set; }
 
         /// <summary>
@@ -57,11 +62,13 @@ public partial class ForumTopic : BaseEntity, IAuditable
         /// <summary>
         /// Gets or sets the last post date and time
         /// </summary>
+        [Index("IX_TopicTypeId_LastPostTime", Order = 1)]
         public DateTime? LastPostTime { get; set; }
 
         /// <summary>
         /// Gets or sets the date and time of instance creation
         /// </summary>
+        [Index]
         public DateTime CreatedOnUtc { get; set; }
 
         /// <summary>
@@ -72,6 +79,7 @@ public partial class ForumTopic : BaseEntity, IAuditable
         /// <summary>
         /// Gets or sets a value indicating whether the entity is published
         /// </summary>
+        [Index("IX_ForumId_Published", Order = 1)]
         public bool Published { get; set; }
 
         /// <summary>
diff --git a/src/Libraries/SmartStore.Data/Migrations/201809251233170_ForumGroupAcl.cs b/src/Libraries/SmartStore.Data/Migrations/201809251233170_ForumGroupAcl.cs
deleted file mode 100644
index 67781b9ef6..0000000000
--- a/src/Libraries/SmartStore.Data/Migrations/201809251233170_ForumGroupAcl.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-namespace SmartStore.Data.Migrations
-{
-    using System;
-    using System.Data.Entity.Migrations;
-    
-    public partial class ForumGroupAcl : DbMigration
-    {
-        public override void Up()
-        {
-            AddColumn("dbo.Forums_Post", "Published", c => c.Boolean(nullable: false, defaultValue: true));
-            AddColumn("dbo.Forums_Topic", "Published", c => c.Boolean(nullable: false, defaultValue: true));
-            AddColumn("dbo.Forums_Group", "SubjectToAcl", c => c.Boolean(nullable: false));
-        }
-        
-        public override void Down()
-        {
-            DropColumn("dbo.Forums_Group", "SubjectToAcl");
-            DropColumn("dbo.Forums_Topic", "Published");
-            DropColumn("dbo.Forums_Post", "Published");
-        }
-    }
-}
diff --git a/src/Libraries/SmartStore.Data/Migrations/201809251233170_ForumGroupAcl.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201809261026134_ForumGroupAcl.Designer.cs
similarity index 92%
rename from src/Libraries/SmartStore.Data/Migrations/201809251233170_ForumGroupAcl.Designer.cs
rename to src/Libraries/SmartStore.Data/Migrations/201809261026134_ForumGroupAcl.Designer.cs
index 9c8853796f..55b7fcd313 100644
--- a/src/Libraries/SmartStore.Data/Migrations/201809251233170_ForumGroupAcl.Designer.cs
+++ b/src/Libraries/SmartStore.Data/Migrations/201809261026134_ForumGroupAcl.Designer.cs
@@ -13,7 +13,7 @@ public sealed partial class ForumGroupAcl : IMigrationMetadata
         
         string IMigrationMetadata.Id
         {
-            get { return "201809251233170_ForumGroupAcl"; }
+            get { return "201809261026134_ForumGroupAcl"; }
         }
         
         string IMigrationMetadata.Source
diff --git a/src/Libraries/SmartStore.Data/Migrations/201809261026134_ForumGroupAcl.cs b/src/Libraries/SmartStore.Data/Migrations/201809261026134_ForumGroupAcl.cs
new file mode 100644
index 0000000000..c4d74dbe8a
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201809261026134_ForumGroupAcl.cs
@@ -0,0 +1,48 @@
+namespace SmartStore.Data.Migrations
+{
+    using System;
+    using System.Data.Entity.Migrations;
+    
+    public partial class ForumGroupAcl : DbMigration
+    {
+        public override void Up()
+        {
+            DropIndex("dbo.Forums_Topic", new[] { "ForumId" });
+            DropIndex("dbo.Forums_Forum", new[] { "ForumGroupId" });
+            AddColumn("dbo.Forums_Post", "Published", c => c.Boolean(nullable: false));
+            AddColumn("dbo.Forums_Topic", "Published", c => c.Boolean(nullable: false));
+            AddColumn("dbo.Forums_Group", "SubjectToAcl", c => c.Boolean(nullable: false));
+            CreateIndex("dbo.Forums_Post", "CreatedOnUtc");
+            CreateIndex("dbo.Forums_Post", "Published");
+            CreateIndex("dbo.Forums_Topic", new[] { "ForumId", "Published" });
+            CreateIndex("dbo.Forums_Topic", new[] { "TopicTypeId", "LastPostTime" });
+            CreateIndex("dbo.Forums_Topic", "Subject");
+            CreateIndex("dbo.Forums_Topic", "NumPosts");
+            CreateIndex("dbo.Forums_Topic", "CreatedOnUtc");
+            CreateIndex("dbo.Forums_Forum", new[] { "ForumGroupId", "DisplayOrder" });
+            CreateIndex("dbo.Forums_Group", "DisplayOrder");
+            CreateIndex("dbo.Forums_Group", "LimitedToStores");
+            CreateIndex("dbo.Forums_Group", "SubjectToAcl");
+        }
+        
+        public override void Down()
+        {
+            DropIndex("dbo.Forums_Group", new[] { "SubjectToAcl" });
+            DropIndex("dbo.Forums_Group", new[] { "LimitedToStores" });
+            DropIndex("dbo.Forums_Group", new[] { "DisplayOrder" });
+            DropIndex("dbo.Forums_Forum", new[] { "ForumGroupId", "DisplayOrder" });
+            DropIndex("dbo.Forums_Topic", new[] { "CreatedOnUtc" });
+            DropIndex("dbo.Forums_Topic", new[] { "NumPosts" });
+            DropIndex("dbo.Forums_Topic", new[] { "Subject" });
+            DropIndex("dbo.Forums_Topic", new[] { "TopicTypeId", "LastPostTime" });
+            DropIndex("dbo.Forums_Topic", new[] { "ForumId", "Published" });
+            DropIndex("dbo.Forums_Post", new[] { "Published" });
+            DropIndex("dbo.Forums_Post", new[] { "CreatedOnUtc" });
+            DropColumn("dbo.Forums_Group", "SubjectToAcl");
+            DropColumn("dbo.Forums_Topic", "Published");
+            DropColumn("dbo.Forums_Post", "Published");
+            CreateIndex("dbo.Forums_Forum", "ForumGroupId");
+            CreateIndex("dbo.Forums_Topic", "ForumId");
+        }
+    }
+}
diff --git a/src/Libraries/SmartStore.Data/Migrations/201809251233170_ForumGroupAcl.resx b/src/Libraries/SmartStore.Data/Migrations/201809261026134_ForumGroupAcl.resx
similarity index 72%
rename from src/Libraries/SmartStore.Data/Migrations/201809251233170_ForumGroupAcl.resx
rename to src/Libraries/SmartStore.Data/Migrations/201809261026134_ForumGroupAcl.resx
index 572cbd0572..07a094ec2a 100644
--- a/src/Libraries/SmartStore.Data/Migrations/201809251233170_ForumGroupAcl.resx
+++ b/src/Libraries/SmartStore.Data/Migrations/201809261026134_ForumGroupAcl.resx
@@ -118,7 +118,7 @@
     <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
   <data name="Target" xml:space="preserve">
-    <value>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</value>
+    <value>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</value>
   </data>
   <data name="DefaultSchema" xml:space="preserve">
     <value>dbo</value>
diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj
index 30a53f7b9a..cc9da1dd58 100644
--- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj
+++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj
@@ -623,9 +623,9 @@
     <Compile Include="Migrations\201809171309522_NewsletterSubscriptionLanguage.Designer.cs">
       <DependentUpon>201809171309522_NewsletterSubscriptionLanguage.cs</DependentUpon>
     </Compile>
-    <Compile Include="Migrations\201809251233170_ForumGroupAcl.cs" />
-    <Compile Include="Migrations\201809251233170_ForumGroupAcl.Designer.cs">
-      <DependentUpon>201809251233170_ForumGroupAcl.cs</DependentUpon>
+    <Compile Include="Migrations\201809261026134_ForumGroupAcl.cs" />
+    <Compile Include="Migrations\201809261026134_ForumGroupAcl.Designer.cs">
+      <DependentUpon>201809261026134_ForumGroupAcl.cs</DependentUpon>
     </Compile>
     <Compile Include="ObjectContextBase.SaveChanges.cs" />
     <Compile Include="Setup\Builder\ActivityLogTypeMigrator.cs" />
@@ -1124,8 +1124,8 @@
     <EmbeddedResource Include="Migrations\201809171309522_NewsletterSubscriptionLanguage.resx">
       <DependentUpon>201809171309522_NewsletterSubscriptionLanguage.cs</DependentUpon>
     </EmbeddedResource>
-    <EmbeddedResource Include="Migrations\201809251233170_ForumGroupAcl.resx">
-      <DependentUpon>201809251233170_ForumGroupAcl.cs</DependentUpon>
+    <EmbeddedResource Include="Migrations\201809261026134_ForumGroupAcl.resx">
+      <DependentUpon>201809261026134_ForumGroupAcl.cs</DependentUpon>
     </EmbeddedResource>
     <EmbeddedResource Include="Sql\Indexes.sql" />
     <EmbeddedResource Include="Sql\StoredProcedures.sql" />

From a2e806384754615db9c19b7055d5af5a76c5fc35 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Wed, 26 Sep 2018 16:04:42 +0200
Subject: [PATCH 12/71] More on published property of forum topic and forum
 post

---
 .../201809261026134_ForumGroupAcl.cs          |   4 +-
 .../Forums/ForumService.cs                    | 112 +++-----
 .../Forums/IForumService.cs                   |   7 -
 .../Controllers/BoardsController.cs           | 260 ++++++++----------
 .../Models/Boards/EditForumPostModel.cs       |   4 +
 .../Models/Boards/EditForumTopicModel.cs      |   6 +-
 .../Models/Boards/TopicMoveModel.cs           |   2 +
 .../Boards/Partials/_CreateUpdatePost.cshtml  |  20 +-
 .../Boards/Partials/_CreateUpdateTopic.cshtml |  33 ++-
 9 files changed, 216 insertions(+), 232 deletions(-)

diff --git a/src/Libraries/SmartStore.Data/Migrations/201809261026134_ForumGroupAcl.cs b/src/Libraries/SmartStore.Data/Migrations/201809261026134_ForumGroupAcl.cs
index c4d74dbe8a..4abd203c4a 100644
--- a/src/Libraries/SmartStore.Data/Migrations/201809261026134_ForumGroupAcl.cs
+++ b/src/Libraries/SmartStore.Data/Migrations/201809261026134_ForumGroupAcl.cs
@@ -9,8 +9,8 @@ public override void Up()
         {
             DropIndex("dbo.Forums_Topic", new[] { "ForumId" });
             DropIndex("dbo.Forums_Forum", new[] { "ForumGroupId" });
-            AddColumn("dbo.Forums_Post", "Published", c => c.Boolean(nullable: false));
-            AddColumn("dbo.Forums_Topic", "Published", c => c.Boolean(nullable: false));
+            AddColumn("dbo.Forums_Post", "Published", c => c.Boolean(nullable: false, defaultValue: true));
+            AddColumn("dbo.Forums_Topic", "Published", c => c.Boolean(nullable: false, defaultValue: true));
             AddColumn("dbo.Forums_Group", "SubjectToAcl", c => c.Boolean(nullable: false));
             CreateIndex("dbo.Forums_Post", "CreatedOnUtc");
             CreateIndex("dbo.Forums_Post", "Published");
diff --git a/src/Libraries/SmartStore.Services/Forums/ForumService.cs b/src/Libraries/SmartStore.Services/Forums/ForumService.cs
index f2ae94acba..2e55625acf 100644
--- a/src/Libraries/SmartStore.Services/Forums/ForumService.cs
+++ b/src/Libraries/SmartStore.Services/Forums/ForumService.cs
@@ -841,20 +841,18 @@ public virtual bool IsCustomerAllowedToCreateTopic(Customer customer, Forum foru
 
         public virtual bool IsCustomerAllowedToEditTopic(Customer customer, ForumTopic topic)
         {
-            if (topic == null || customer == null || customer.IsGuest())
+            if (customer != null && topic != null)
             {
-                return false;
-            }
-
-            if (customer.IsForumModerator())
-            {
-                return true;
-            }
+                if (customer.IsForumModerator())
+                {
+                    return true;
+                }
 
-            if (_forumSettings.AllowCustomersToEditPosts && topic.Published)
-            {
-                var ownTopic = customer.Id == topic.CustomerId;
-                return ownTopic;
+                if (_forumSettings.AllowCustomersToEditPosts && topic.Published)
+                {
+                    var ownTopic = customer.Id == topic.CustomerId;
+                    return ownTopic;
+                }
             }
 
             return false;
@@ -862,12 +860,7 @@ public virtual bool IsCustomerAllowedToEditTopic(Customer customer, ForumTopic t
 
         public virtual bool IsCustomerAllowedToMoveTopic(Customer customer, ForumTopic topic)
         {
-            if (topic == null || customer == null || customer.IsGuest())
-            {
-                return false;
-            }
-
-            if (customer.IsForumModerator())
+            if (customer != null && customer.IsForumModerator())
             {
                 return true;
             }
@@ -877,20 +870,18 @@ public virtual bool IsCustomerAllowedToMoveTopic(Customer customer, ForumTopic t
 
         public virtual bool IsCustomerAllowedToDeleteTopic(Customer customer, ForumTopic topic)
         {
-            if (topic == null || customer == null || customer.IsGuest())
+            if (topic != null && customer != null)
             {
-                return false;
-            }
-
-            if (customer.IsForumModerator())
-            {
-                return true;
-            }
+                if (customer.IsForumModerator())
+                {
+                    return true;
+                }
 
-            if (_forumSettings.AllowCustomersToDeletePosts && topic.Published)
-            {
-                var ownTopic = customer.Id == topic.CustomerId;
-                return ownTopic;
+                if (_forumSettings.AllowCustomersToDeletePosts && topic.Published)
+                {
+                    var ownTopic = customer.Id == topic.CustomerId;
+                    return ownTopic;
+                }
             }
 
             return false;
@@ -903,7 +894,7 @@ public virtual bool IsCustomerAllowedToCreatePost(Customer customer, ForumTopic
                 return false;
             }
 
-            if (customer.IsGuest() && !_forumSettings.AllowGuestsToCreatePosts)
+            if (!_forumSettings.AllowGuestsToCreatePosts && customer.IsGuest())
             {
                 return false;
             }
@@ -913,20 +904,18 @@ public virtual bool IsCustomerAllowedToCreatePost(Customer customer, ForumTopic
 
         public virtual bool IsCustomerAllowedToEditPost(Customer customer, ForumPost post)
         {
-            if (post == null || customer == null || customer.IsGuest())
-            {
-                return false;
-            }
-
-            if (customer.IsForumModerator())
+            if (post != null && customer != null)
             {
-                return true;
-            }
+                if (customer.IsForumModerator())
+                {
+                    return true;
+                }
 
-            if (_forumSettings.AllowCustomersToEditPosts && post.Published)
-            {
-                var ownPost = customer.Id == post.CustomerId;
-                return ownPost;
+                if (_forumSettings.AllowCustomersToEditPosts && post.Published)
+                {
+                    var ownPost = customer.Id == post.CustomerId;
+                    return ownPost;
+                }
             }
 
             return false;
@@ -934,37 +923,20 @@ public virtual bool IsCustomerAllowedToEditPost(Customer customer, ForumPost pos
 
         public virtual bool IsCustomerAllowedToDeletePost(Customer customer, ForumPost post)
         {
-            if (post == null || customer == null || customer.IsGuest())
+            if (post != null && customer != null)
             {
-                return false;
-            }
-
-            if (customer.IsForumModerator())
-            {
-                return true;
-            }
-
-            if (_forumSettings.AllowCustomersToDeletePosts && post.Published)
-            {
-                var ownPost = customer.Id == post.CustomerId;
-                return ownPost;
-            }
-
-            return false;
-        }
+                if (customer.IsForumModerator())
+                {
+                    return true;
+                }
 
-        public virtual bool IsCustomerAllowedToSetTopicPriority(Customer customer)
-        {
-            if (customer == null || customer.IsGuest())
-            {
-                return false;
+                if (_forumSettings.AllowCustomersToDeletePosts && post.Published)
+                {
+                    var ownPost = customer.Id == post.CustomerId;
+                    return ownPost;
+                }
             }
 
-            if (customer.IsForumModerator())
-            {
-                return true;
-            }            
-
             return false;
         }
 
diff --git a/src/Libraries/SmartStore.Services/Forums/IForumService.cs b/src/Libraries/SmartStore.Services/Forums/IForumService.cs
index 95459269ab..361e1720fb 100644
--- a/src/Libraries/SmartStore.Services/Forums/IForumService.cs
+++ b/src/Libraries/SmartStore.Services/Forums/IForumService.cs
@@ -348,13 +348,6 @@ IPagedList<ForumSubscription> GetAllSubscriptions(int customerId, int forumId,
         /// <returns>True if allowed, otherwise false</returns>
         bool IsCustomerAllowedToDeletePost(Customer customer, ForumPost post);
 
-        /// <summary>
-        /// Check whether customer is allowed to set topic priority
-        /// </summary>
-        /// <param name="customer">Customer</param>
-        /// <returns>True if allowed, otherwise false</returns>
-        bool IsCustomerAllowedToSetTopicPriority(Customer customer);
-
         /// <summary>
         /// Check whether customer is allowed to watch topics
         /// </summary>
diff --git a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
index 57e57fac1e..5f4203551f 100644
--- a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
+++ b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
@@ -434,7 +434,6 @@ public ActionResult Forum(int id, int page = 1)
                 .Select(x => x.LastPostId)
                 .Distinct()
                 .ToArray();
-
             var lastPosts = _forumService.GetPostsByIds(lastPostIds).ToDictionary(x => x.Id);
 
             foreach (var topic in topics)
@@ -822,17 +821,21 @@ public ActionResult TopicMove(int id)
             {
                 return HttpNotFound();
             }
-            if (!_forumService.IsCustomerAllowedToMoveTopic(customer, topic))
-            {
-                return new HttpUnauthorizedResult();
-            }
 
             var model = new TopicMoveModel
             {
                 Id = topic.Id,
                 TopicSeName = topic.GetSeName(),
                 ForumSelected = topic.ForumId,
+                CustomerId = topic.CustomerId,
+                IsCustomerAllowedToEdit = _forumService.IsCustomerAllowedToMoveTopic(customer, topic)
             };
+
+            if (!model.IsCustomerAllowedToEdit && customer.Id != topic.CustomerId)
+            {
+                return new HttpUnauthorizedResult();
+            }
+
             model.ForumList = ForumGroupsForumsList();
 
             CreateForumBreadcrumb(topic: topic);
@@ -855,6 +858,10 @@ public ActionResult TopicMove(TopicMoveModel model)
             {
                 return HttpNotFound();
             }
+            if (!_forumService.IsCustomerAllowedToMoveTopic(customer, topic))
+            {
+                return new HttpUnauthorizedResult();
+            }
 
             var newForumId = model.ForumSelected;
             var forum = _forumService.GetForumById(newForumId);
@@ -891,12 +898,13 @@ public ActionResult TopicCreate(int id)
                 Id = 0,
                 IsEdit = false,
                 Published = true,
+                SeName = string.Empty,
                 DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnForumPage,
                 ForumId = forum.Id,
                 ForumName = forum.GetLocalized(x => x.Name),
                 ForumSeName = forum.GetSeName(),
                 ForumEditor = _forumSettings.ForumEditor,
-                IsCustomerAllowedToSetTopicPriority = _forumService.IsCustomerAllowedToSetTopicPriority(customer),
+                IsModerator = customer.IsForumModerator(),
                 TopicPriorities = ForumTopicTypesList(),
                 IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer),
                 Subscribed = false,
@@ -938,47 +946,38 @@ public ActionResult TopicCreate(EditForumTopicModel model, bool captchaValid)
             {
                 try
                 {
-                    var subject = model.Subject;
-                    var maxSubjectLength = _forumSettings.TopicSubjectMaxLength;
-                    if (maxSubjectLength > 0 && subject.Length > maxSubjectLength)
+                    var topic = new ForumTopic
                     {
-                        subject = subject.Substring(0, maxSubjectLength);
-                    }
+                        ForumId = forum.Id,
+                        CustomerId = customer.Id,
+                        Published = true,
+                        TopicTypeId = (int)ForumTopicType.Normal
+                    };
 
-                    var text = model.Text;
-                    var maxPostLength = _forumSettings.PostMaxLength;
-                    if (maxPostLength > 0 && text.Length > maxPostLength)
+                    if (customer.IsForumModerator())
                     {
-                        text = text.Substring(0, maxPostLength);
+                        model.Published = model.Published;
+                        model.TopicTypeId = model.TopicTypeId;
                     }
 
-                    var topicType = ForumTopicType.Normal;
-					var utcNow = DateTime.UtcNow;
-                    var ipAddress = Services.WebHelper.GetCurrentIpAddress();
-
-                    if (_forumService.IsCustomerAllowedToSetTopicPriority(customer))
-                    {
-                        topicType = (ForumTopicType)Enum.ToObject(typeof (ForumTopicType), model.TopicTypeId);
-                    }
+                    topic.Subject = _forumSettings.TopicSubjectMaxLength > 0 && model.Subject.Length > _forumSettings.TopicSubjectMaxLength
+                        ? model.Subject.Substring(0, _forumSettings.TopicSubjectMaxLength)
+                        : model.Subject;
 
-                    var topic = new ForumTopic
-                    {
-                        ForumId = forum.Id,
-                        CustomerId = customer.Id,
-                        TopicTypeId = (int) topicType,
-                        Subject = subject,
-                        Published = true
-                    };
                     _forumService.InsertTopic(topic, true);
 
                     var post = new ForumPost
                     {
                         TopicId = topic.Id,
                         CustomerId = customer.Id,
-                        Text = text,
-                        IPAddress = ipAddress,
+                        IPAddress = Services.WebHelper.GetCurrentIpAddress(),
                         Published = true
                     };
+
+                    post.Text = _forumSettings.PostMaxLength > 0 && model.Text.Length > _forumSettings.PostMaxLength
+                        ? model.Text.Substring(0, _forumSettings.PostMaxLength)
+                        : model.Text;
+
                     _forumService.InsertPost(post, false);
 
                     topic.NumPosts = 1;
@@ -998,7 +997,7 @@ public ActionResult TopicCreate(EditForumTopicModel model, bool captchaValid)
                                 SubscriptionGuid = Guid.NewGuid(),
                                 CustomerId = customer.Id,
                                 TopicId = topic.Id,
-                                CreatedOnUtc = utcNow
+                                CreatedOnUtc = DateTime.UtcNow
                             };
 
                             _forumService.InsertSubscription(forumSubscription);
@@ -1021,7 +1020,7 @@ public ActionResult TopicCreate(EditForumTopicModel model, bool captchaValid)
             model.ForumId = forum.Id;
             model.ForumName = forum.GetLocalized(x => x.Name);
             model.ForumSeName = forum.GetSeName();
-            model.IsCustomerAllowedToSetTopicPriority = _forumService.IsCustomerAllowedToSetTopicPriority(customer);
+            model.IsModerator = customer.IsForumModerator();
             model.IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer);
             model.ForumEditor = _forumSettings.ForumEditor;
 
@@ -1038,21 +1037,18 @@ public ActionResult TopicEdit(int id)
             var customer = Services.WorkContext.CurrentCustomer;
             var topic = _forumService.GetTopicById(id);
 
-            if (IsTopicVisible(topic, customer))
+            if (!IsTopicVisible(topic, customer))
             {
                 return HttpNotFound();
             }
-            if (!_forumService.IsCustomerAllowedToEditTopic(customer, topic))
-            {
-                return new HttpUnauthorizedResult();
-            }
 
             var firstPost = topic.GetFirstPost(_forumService);
             var model = new EditForumTopicModel
             {
                 Id = topic.Id,
                 IsEdit = true,
-                Published = true,
+                Published = topic.Published,
+                SeName = topic.GetSeName(),
                 DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnForumPage,
                 TopicPriorities = ForumTopicTypesList(),
                 ForumName = topic.Forum.GetLocalized(x => x.Name),
@@ -1062,10 +1058,17 @@ public ActionResult TopicEdit(int id)
                 TopicTypeId = topic.TopicTypeId,
                 ForumId = topic.Forum.Id,
                 ForumEditor = _forumSettings.ForumEditor,
-                IsCustomerAllowedToSetTopicPriority = _forumService.IsCustomerAllowedToSetTopicPriority(customer),
-                IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer)
+                CustomerId = topic.CustomerId,
+                IsModerator = customer.IsForumModerator(),
+                IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer),
+                IsCustomerAllowedToEdit = _forumService.IsCustomerAllowedToEditTopic(customer, topic)
             };
 
+            if (!model.IsCustomerAllowedToEdit && customer.Id != topic.CustomerId)
+            {
+                return new HttpUnauthorizedResult();
+            }
+
             // Subscription.
             if (model.IsCustomerAllowedToSubscribe)
             {
@@ -1089,13 +1092,13 @@ public ActionResult TopicEdit(EditForumTopicModel model, bool captchaValid)
             }
 
             var customer = Services.WorkContext.CurrentCustomer;
-            var forumTopic = _forumService.GetTopicById(model.Id);
+            var topic = _forumService.GetTopicById(model.Id);
 
-            if (IsTopicVisible(forumTopic, customer))
+            if (!IsTopicVisible(topic, customer))
             {
                 return HttpNotFound();
             }
-            if (!_forumService.IsCustomerAllowedToEditTopic(customer, forumTopic))
+            if (!_forumService.IsCustomerAllowedToEditTopic(customer, topic))
             {
                 return new HttpUnauthorizedResult();
             }
@@ -1109,35 +1112,23 @@ public ActionResult TopicEdit(EditForumTopicModel model, bool captchaValid)
             {
                 try
                 {
-                    var subject = model.Subject;
-                    var maxSubjectLength = _forumSettings.TopicSubjectMaxLength;
-                    if (maxSubjectLength > 0 && subject.Length > maxSubjectLength)
+                    if (customer.IsForumModerator())
                     {
-                        subject = subject.Substring(0, maxSubjectLength);
+                        topic.Published = model.Published;
+                        topic.TopicTypeId = model.TopicTypeId;
                     }
 
-                    var text = model.Text;
-                    var maxPostLength = _forumSettings.PostMaxLength;
-                    if (maxPostLength > 0 && text.Length > maxPostLength)
-                    {
-                        text = text.Substring(0, maxPostLength);
-                    }
-
-                    var topicType = ForumTopicType.Normal;
-                    var ipAddress = Services.WebHelper.GetCurrentIpAddress();
-                    var utcNow = DateTime.UtcNow;
-
-                    if (_forumService.IsCustomerAllowedToSetTopicPriority(customer))
-                    {
-                        topicType = (ForumTopicType) Enum.ToObject(typeof (ForumTopicType), model.TopicTypeId);
-                    }
+                    topic.Subject = _forumSettings.TopicSubjectMaxLength > 0 && model.Subject.Length > _forumSettings.TopicSubjectMaxLength
+                        ? model.Subject.Substring(0, _forumSettings.TopicSubjectMaxLength)
+                        : model.Subject;
 
-                    forumTopic.TopicTypeId = (int) topicType;
-                    forumTopic.Subject = subject;
+                    _forumService.UpdateTopic(topic);
 
-                    _forumService.UpdateTopic(forumTopic);
+                    var text = _forumSettings.PostMaxLength > 0 && model.Text.Length > _forumSettings.PostMaxLength
+                        ? model.Text.Substring(0, _forumSettings.PostMaxLength)
+                        : model.Text;
 
-                    var firstPost = forumTopic.GetFirstPost(_forumService);
+                    var firstPost = topic.GetFirstPost(_forumService);
                     if (firstPost != null)
                     {
                         firstPost.Text = text;
@@ -1147,10 +1138,10 @@ public ActionResult TopicEdit(EditForumTopicModel model, bool captchaValid)
                     {
                         firstPost = new ForumPost
                         {
-                            TopicId = forumTopic.Id,
-                            CustomerId = forumTopic.CustomerId,
+                            TopicId = topic.Id,
+                            CustomerId = topic.CustomerId,
                             Text = text,
-                            IPAddress = ipAddress,
+                            IPAddress = Services.WebHelper.GetCurrentIpAddress(),
                             Published = true
                         };
 
@@ -1160,7 +1151,7 @@ public ActionResult TopicEdit(EditForumTopicModel model, bool captchaValid)
                     // Subscription.
                     if (_forumService.IsCustomerAllowedToSubscribe(customer))
                     {
-                        var forumSubscription = _forumService.GetAllSubscriptions(customer.Id, 0, forumTopic.Id, 0, 1).FirstOrDefault();
+                        var forumSubscription = _forumService.GetAllSubscriptions(customer.Id, 0, topic.Id, 0, 1).FirstOrDefault();
 
                         if (model.Subscribed)
                         {
@@ -1170,8 +1161,8 @@ public ActionResult TopicEdit(EditForumTopicModel model, bool captchaValid)
                                 {
                                     SubscriptionGuid = Guid.NewGuid(),
                                     CustomerId = customer.Id,
-                                    TopicId = forumTopic.Id,
-                                    CreatedOnUtc = utcNow
+                                    TopicId = topic.Id,
+                                    CreatedOnUtc = DateTime.UtcNow
                                 };
 
                                 _forumService.InsertSubscription(forumSubscription);
@@ -1187,7 +1178,7 @@ public ActionResult TopicEdit(EditForumTopicModel model, bool captchaValid)
                     }
 
                     // Redirect to the topic page with the topic slug.
-                    return RedirectToRoute("TopicSlug", new {id = forumTopic.Id, slug = forumTopic.GetSeName()});
+                    return RedirectToRoute("TopicSlug", new {id = topic.Id, slug = topic.GetSeName()});
                 }
                 catch (Exception ex)
                 {
@@ -1198,14 +1189,14 @@ public ActionResult TopicEdit(EditForumTopicModel model, bool captchaValid)
             // Redisplay form.
             model.TopicPriorities = ForumTopicTypesList();
             model.IsEdit = true;
-            model.Published = forumTopic.Published;
+            model.Published = topic.Published;
             model.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnForumPage;
-            model.ForumName = forumTopic.Forum.GetLocalized(x => x.Name);
-            model.ForumSeName = forumTopic.Forum.GetSeName();
-            model.ForumId = forumTopic.Forum.Id;
+            model.ForumName = topic.Forum.GetLocalized(x => x.Name);
+            model.ForumSeName = topic.Forum.GetSeName();
+            model.ForumId = topic.Forum.Id;
             model.ForumEditor = _forumSettings.ForumEditor;
-
-            model.IsCustomerAllowedToSetTopicPriority = _forumService.IsCustomerAllowedToSetTopicPriority(customer);
+            model.CustomerId = customer.Id;
+            model.IsModerator = customer.IsForumModerator();
             model.IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer);
 
             return View(model);
@@ -1221,7 +1212,7 @@ public ActionResult TopicDelete(int id)
             var customer = Services.WorkContext.CurrentCustomer;
             var topic = _forumService.GetTopicById(id);
 
-            if (IsTopicVisible(topic, customer))
+            if (!IsTopicVisible(topic, customer))
             {
                 return HttpNotFound();
             }
@@ -1276,6 +1267,7 @@ public ActionResult PostCreate(int id, int? quote)
                 ForumName = topic.Forum.GetLocalized(x => x.Name),
                 ForumTopicSubject = topic.Subject,
                 ForumTopicSeName = topic.GetSeName(),
+                IsModerator = customer.IsForumModerator(),
                 IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer),
                 Subscribed = false
             };
@@ -1345,31 +1337,29 @@ public ActionResult PostCreate(EditForumPostModel model, bool captchaValid)
             {
                 try
                 {
-                    var text = model.Text;
-                    var maxPostLength = _forumSettings.PostMaxLength;
-                    if (maxPostLength > 0 && text.Length > maxPostLength)
-                    {
-                        text = text.Substring(0, maxPostLength);
-                    }
-
-					var utcNow = DateTime.UtcNow;
-                    var ipAddress = Services.WebHelper.GetCurrentIpAddress();
-
-                    var forumPost = new ForumPost
+                    var post = new ForumPost
                     {
                         TopicId = topic.Id,
                         CustomerId = customer.Id,
-                        Text = text,
-                        IPAddress = ipAddress,
+                        IPAddress = Services.WebHelper.GetCurrentIpAddress(),
                         Published = true
                     };
 
-                    _forumService.InsertPost(forumPost, true);
+                    if (customer.IsForumModerator())
+                    {
+                        post.Published = model.Published;
+                    }
+
+                    post.Text = _forumSettings.PostMaxLength > 0 && model.Text.Length > _forumSettings.PostMaxLength
+                        ? model.Text.Substring(0, _forumSettings.PostMaxLength)
+                        : model.Text;
+
+                    _forumService.InsertPost(post, true);
 
                     // Subscription.
                     if (_forumService.IsCustomerAllowedToSubscribe(customer))
                     {
-                        var forumSubscription = _forumService.GetAllSubscriptions(customer.Id, 0, forumPost.TopicId, 0, 1).FirstOrDefault();
+                        var forumSubscription = _forumService.GetAllSubscriptions(customer.Id, 0, post.TopicId, 0, 1).FirstOrDefault();
                         if (model.Subscribed)
                         {
                             if (forumSubscription == null)
@@ -1378,8 +1368,8 @@ public ActionResult PostCreate(EditForumPostModel model, bool captchaValid)
                                 {
                                     SubscriptionGuid = Guid.NewGuid(),
                                     CustomerId = customer.Id,
-                                    TopicId = forumPost.TopicId,
-                                    CreatedOnUtc = utcNow
+                                    TopicId = post.TopicId,
+                                    CreatedOnUtc = DateTime.UtcNow
                                 };
 
                                 _forumService.InsertSubscription(forumSubscription);
@@ -1395,19 +1385,13 @@ public ActionResult PostCreate(EditForumPostModel model, bool captchaValid)
                     }
 
                     var pageSize = _forumSettings.PostsPageSize > 0 ? _forumSettings.PostsPageSize : 20;
-                    var pageIndex = _forumService.CalculateTopicPageIndex(forumPost.TopicId, pageSize, forumPost.Id) + 1;
-                    var url = string.Empty;
+                    var pageIndex = _forumService.CalculateTopicPageIndex(post.TopicId, pageSize, post.Id) + 1;
 
-                    if (pageIndex > 1)
-                    {
-                        url = Url.RouteUrl("TopicSlug", new { id = forumPost.TopicId, slug = forumPost.ForumTopic.GetSeName(), page = pageIndex });
-                    }
-                    else
-                    {
-                        url = Url.RouteUrl("TopicSlug", new { id = forumPost.TopicId, slug = forumPost.ForumTopic.GetSeName() });
-                    }
+                    var url = pageIndex > 1
+                        ? Url.RouteUrl("TopicSlug", new { id = post.TopicId, slug = post.ForumTopic.GetSeName(), page = pageIndex })
+                        : Url.RouteUrl("TopicSlug", new { id = post.TopicId, slug = post.ForumTopic.GetSeName() });
 
-                    return Redirect(string.Format("{0}#{1}", url, forumPost.Id));
+                    return Redirect(string.Concat(url, "#", post.Id));
                 }
                 catch (Exception ex)
                 {
@@ -1423,6 +1407,7 @@ public ActionResult PostCreate(EditForumPostModel model, bool captchaValid)
             model.ForumTopicId = topic.Id;
             model.ForumTopicSubject = topic.Subject;
             model.ForumTopicSeName = topic.GetSeName();
+            model.IsModerator = customer.IsForumModerator();
             model.IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer);
             model.ForumEditor = _forumSettings.ForumEditor;
             
@@ -1443,10 +1428,6 @@ public ActionResult PostEdit(int id)
             {
                 return HttpNotFound();
             }
-            if (!_forumService.IsCustomerAllowedToEditPost(customer, post))
-            {
-                return new HttpUnauthorizedResult();
-            }
 
             var model = new EditForumPostModel
             {
@@ -1459,11 +1440,19 @@ public ActionResult PostEdit(int id)
                 ForumName = post.ForumTopic.Forum.GetLocalized(x => x.Name),
                 ForumTopicSubject = post.ForumTopic.Subject,
                 ForumTopicSeName = post.ForumTopic.GetSeName(),
-                IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer),
                 Subscribed = false,
-                Text = post.Text
+                Text = post.Text,
+                CustomerId = customer.Id,
+                IsModerator = customer.IsForumModerator(),
+                IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer),
+                IsCustomerAllowedToEdit = _forumService.IsCustomerAllowedToEditPost(customer, post)
             };
 
+            if (!model.IsCustomerAllowedToEdit && customer.Id != post.CustomerId)
+            {
+                return new HttpUnauthorizedResult();
+            }
+
             // Subscription.
             if (model.IsCustomerAllowedToSubscribe)
             {
@@ -1493,7 +1482,6 @@ public ActionResult PostEdit(EditForumPostModel model, bool captchaValid)
             {
                 return HttpNotFound();
             }
-
             if (!_forumService.IsCustomerAllowedToEditPost(customer, post))
             {
                 return new HttpUnauthorizedResult();
@@ -1508,15 +1496,14 @@ public ActionResult PostEdit(EditForumPostModel model, bool captchaValid)
             {
                 try
                 {
-                    var utcNow = DateTime.UtcNow;
-                    var text = model.Text;
-                    var maxPostLength = _forumSettings.PostMaxLength;
-                    if (maxPostLength > 0 && text.Length > maxPostLength)
+                    if (customer.IsForumModerator())
                     {
-                        text = text.Substring(0, maxPostLength);
+                        post.Published = model.Published;
                     }
 
-                    post.Text = text;
+                    post.Text = _forumSettings.PostMaxLength > 0 && model.Text.Length > _forumSettings.PostMaxLength
+                        ? model.Text.Substring(0, _forumSettings.PostMaxLength)
+                        : model.Text;
 
                     _forumService.UpdatePost(post);
 
@@ -1533,7 +1520,7 @@ public ActionResult PostEdit(EditForumPostModel model, bool captchaValid)
                                     SubscriptionGuid = Guid.NewGuid(),
                                     CustomerId = customer.Id,
                                     TopicId = post.TopicId,
-                                    CreatedOnUtc = utcNow
+                                    CreatedOnUtc = DateTime.UtcNow
                                 };
 
                                 _forumService.InsertSubscription(forumSubscription);
@@ -1549,19 +1536,13 @@ public ActionResult PostEdit(EditForumPostModel model, bool captchaValid)
                     }
 
                     var pageSize = _forumSettings.PostsPageSize > 0 ? _forumSettings.PostsPageSize : 20;
-                    var pageIndex = (_forumService.CalculateTopicPageIndex(post.TopicId, pageSize, post.Id) + 1);
-                    var url = string.Empty;
+                    var pageIndex = _forumService.CalculateTopicPageIndex(post.TopicId, pageSize, post.Id) + 1;
 
-                    if (pageIndex > 1)
-                    {
-                        url = Url.RouteUrl("TopicSlug", new { id = post.TopicId, slug = post.ForumTopic.GetSeName(), page = pageIndex });
-                    }
-                    else
-                    {
-                        url = Url.RouteUrl("TopicSlug", new { id = post.TopicId, slug = post.ForumTopic.GetSeName() });
-                    }
+                    var url = pageIndex > 1
+                        ? Url.RouteUrl("TopicSlug", new { id = post.TopicId, slug = post.ForumTopic.GetSeName(), page = pageIndex })
+                        : Url.RouteUrl("TopicSlug", new { id = post.TopicId, slug = post.ForumTopic.GetSeName() });
 
-                    return Redirect(string.Format("{0}#{1}", url, post.Id));
+                    return Redirect(string.Concat(url, "#", post.Id));
                 }
                 catch (Exception ex)
                 {
@@ -1578,9 +1559,11 @@ public ActionResult PostEdit(EditForumPostModel model, bool captchaValid)
             model.ForumTopicSubject = post.ForumTopic.Subject;
             model.ForumTopicSeName = post.ForumTopic.GetSeName();
             model.Id = post.Id;
-            model.IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer);
             model.ForumEditor = _forumSettings.ForumEditor;
-            
+            model.CustomerId = customer.Id;
+            model.IsModerator = customer.IsForumModerator();
+            model.IsCustomerAllowedToSubscribe = _forumService.IsCustomerAllowedToSubscribe(customer);
+
             return View(model);
         }
 
@@ -1597,7 +1580,6 @@ public ActionResult PostDelete(int id)
             {
                 return HttpNotFound();
             }
-
             if (!_forumService.IsCustomerAllowedToDeletePost(Services.WorkContext.CurrentCustomer, post))
             {
                 return new HttpUnauthorizedResult();
diff --git a/src/Presentation/SmartStore.Web/Models/Boards/EditForumPostModel.cs b/src/Presentation/SmartStore.Web/Models/Boards/EditForumPostModel.cs
index 4e19404cf4..4f8ac6cb96 100644
--- a/src/Presentation/SmartStore.Web/Models/Boards/EditForumPostModel.cs
+++ b/src/Presentation/SmartStore.Web/Models/Boards/EditForumPostModel.cs
@@ -23,8 +23,12 @@ public partial class EditForumPostModel : EntityModelBase
         public string ForumTopicSubject { get; set; }
         public string ForumTopicSeName { get; set; }
 
+        public bool IsModerator { get; set; }
         public bool IsCustomerAllowedToSubscribe { get; set; }
         public bool Subscribed { get; set; }
+
+        public bool IsCustomerAllowedToEdit { get; set; }
+        public int CustomerId { get; set; }
     }
 
     public class EditForumPostValidator : AbstractValidator<EditForumPostModel>
diff --git a/src/Presentation/SmartStore.Web/Models/Boards/EditForumTopicModel.cs b/src/Presentation/SmartStore.Web/Models/Boards/EditForumTopicModel.cs
index 80b2e7ec7d..4f27772b58 100644
--- a/src/Presentation/SmartStore.Web/Models/Boards/EditForumTopicModel.cs
+++ b/src/Presentation/SmartStore.Web/Models/Boards/EditForumTopicModel.cs
@@ -19,6 +19,7 @@ public EditForumTopicModel()
         public bool IsEdit { get; set; }
         public bool DisplayCaptcha { get; set; }
         public bool Published { get; set; }
+        public string SeName { get; set; }
 
         public int ForumId { get; set; }
         public LocalizedValue<string> ForumName { get; set; }
@@ -33,11 +34,14 @@ public EditForumTopicModel()
         [AllowHtml]
         public string Text { get; set; }
         
-        public bool IsCustomerAllowedToSetTopicPriority { get; set; }
+        public bool IsModerator { get; set; }
         public IEnumerable<SelectListItem> TopicPriorities { get; set; }
 
         public bool IsCustomerAllowedToSubscribe { get; set; }
         public bool Subscribed { get; set; }
+
+        public bool IsCustomerAllowedToEdit { get; set; }
+        public int CustomerId { get; set; }
     }
 
     public class EditForumTopicValidator : AbstractValidator<EditForumTopicModel>
diff --git a/src/Presentation/SmartStore.Web/Models/Boards/TopicMoveModel.cs b/src/Presentation/SmartStore.Web/Models/Boards/TopicMoveModel.cs
index c88dc4c6b4..b784c10cbd 100644
--- a/src/Presentation/SmartStore.Web/Models/Boards/TopicMoveModel.cs
+++ b/src/Presentation/SmartStore.Web/Models/Boards/TopicMoveModel.cs
@@ -13,6 +13,8 @@ public TopicMoveModel()
 
         public int ForumSelected { get; set; }
         public string TopicSeName { get; set; }
+        public bool IsCustomerAllowedToEdit { get; set; }
+        public int CustomerId { get; set; }
 
         public IEnumerable<SelectListItem> ForumList { get; set; }
     }
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/Partials/_CreateUpdatePost.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/Partials/_CreateUpdatePost.cshtml
index 97165cc9b2..48d3d6a5df 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/Partials/_CreateUpdatePost.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/Partials/_CreateUpdatePost.cshtml
@@ -37,12 +37,26 @@
             </div>
         </div>
 
+        @if (Model.IsModerator)
+        {
+            <div class="row justify-content-end">
+                <div class="col-sm-9">
+					<div class="form-check">
+                        @Html.CheckBoxFor(model => model.Published, new { @class = "form-check-input" })
+			            <label class="form-check-label" for="@Html.IdFor(model => model.Published)">
+				            @T("Common.Published")
+			            </label>
+					</div>
+                </div>
+            </div>
+        }
+
         @if (Model.IsCustomerAllowedToSubscribe)
         {
             <div class="row justify-content-end">
                 <div class="col-sm-9">
 					<div class="form-check">
-						@Html.CheckBox("Subscribed", @Model.Subscribed, new { @class = "form-check-input" })
+						@Html.CheckBoxFor(model => model.Subscribed, new { @class = "form-check-input" })
 						<label class="form-check-label" for="Subscribed">@T("Forum.NotifyWhenSomeonePostsInThisTopic")</label>
 					</div>
                 </div>
@@ -72,10 +86,10 @@
                     <i class="fa fa-reply"></i>
                     <span>@T("Forum.Submit")</span>
                 </button>
-                <button class="btn btn-secondary" onclick="setLocation('@Url.RouteUrl("TopicSlug", new { id = Model.ForumTopicId, slug = Model.ForumTopicSeName })'); return false;">
+                <a class="btn btn-secondary" href="@Url.RouteUrl("TopicSlug", new { id = Model.ForumTopicId, slug = Model.ForumTopicSeName })">
                     <i class="fa fa-times"></i>
                     <span>@T("Forum.Cancel")</span>
-                </button>
+                </a>
             </div>
         </div>
     </div>
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/Partials/_CreateUpdateTopic.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/Partials/_CreateUpdateTopic.cshtml
index f7f69aa490..4bc57726f8 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/Partials/_CreateUpdateTopic.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/Partials/_CreateUpdateTopic.cshtml
@@ -1,7 +1,12 @@
-@model EditForumTopicModel
-@using SmartStore.Core.Domain.Forums;
+@using SmartStore.Core.Domain.Forums;
 @using SmartStore.Web;
 @using SmartStore.Web.Models.Boards;
+@model EditForumTopicModel
+@{
+    var cancelUrl = Model.Id == 0 ? 
+        Url.RouteUrl("ForumSlug", new { id = Model.ForumId, slug = Model.ForumSeName }) :
+        Url.RouteUrl("TopicSlug", new { id = Model.Id, slug = Model.SeName });
+}
 
 @using (Html.BeginForm())
 {
@@ -41,7 +46,7 @@
             </div>
         </div>
 
-        @if (Model.IsCustomerAllowedToSetTopicPriority)
+        @if (Model.IsModerator)
         {
             <div class="form-group row">
                 <label class="col-sm-3 col-form-label">@T("Forum.Priority")</label>
@@ -49,14 +54,22 @@
                     @Html.DropDownList("TopicTypeId", new SelectList(Model.TopicPriorities, "Value", "Text", Model.TopicTypeId), new { @class = "form-control" } )
                 </div>
             </div>
-        }
-                           
-        @if (Model.IsCustomerAllowedToSubscribe)
-        {
+
+            <div class="row justify-content-end">
+                <div class="col-sm-9">
+					<div class="form-check">
+                        @Html.CheckBoxFor(model => model.Published, new { @class = "form-check-input" })
+			            <label class="form-check-label" for="@Html.IdFor(model => model.Published)">
+				            @T("Common.Published")
+			            </label>
+					</div>
+                </div>
+            </div>
+
             <div class="row justify-content-end">
                 <div class="col-sm-9">
 					<div class="form-check">
-						@Html.CheckBox("Subscribed", @Model.Subscribed, new { @class = "form-check-input" })
+						@Html.CheckBoxFor(model => model.Subscribed, new { @class = "form-check-input" })
 						<label class="form-check-label" for="Subscribed">@T("Forum.NotifyWhenSomeonePostsInThisTopic")</label>
 					</div>
                 </div>
@@ -86,10 +99,10 @@
 					<i class="fa fa-reply"></i>
                     <span>@T("Forum.Submit")</span>
 				</button>
-                <button class="btn btn-secondary" onclick="setLocation('@Url.RouteUrl("ForumSlug", new { id = Model.ForumId, slug = Model.ForumSeName })'); return false;">
+                <a class="btn btn-secondary" href="@cancelUrl">
                     <i class="fa fa-times"></i>
                     <span>@T("Forum.Cancel")</span>
-                </button>
+                </a>
             </div>
         </div>
     </div>

From 56ad33c908d4f20713b64ff4bc789d9ca0e462d9 Mon Sep 17 00:00:00 2001
From: Michael Herzog <herzog@smartstore.com>
Date: Wed, 26 Sep 2018 20:22:04 +0200
Subject: [PATCH 13/71] Closes #1499 Add hint to forms indicating that fields
 with an asterisk (*) are mandatory

---
 .../Migrations/MigrationsConfiguration.cs            |  7 +++++++
 .../Views/Customer/ChangePassword.cshtml             |  6 ++++++
 .../SmartStore.Web/Views/Customer/Info.cshtml        |  6 ++++++
 .../SmartStore.Web/Views/Customer/Register.cshtml    |  6 ++++++
 .../SmartStore.Web/Views/Home/ContactUs.cshtml       |  7 +++++++
 .../SmartStore.Web/Views/Product/AskQuestion.cshtml  |  6 ++++++
 .../SmartStore.Web/Views/Product/EmailAFriend.cshtml | 12 +++++++++---
 .../SmartStore.Web/Views/Product/Reviews.cshtml      | 10 ++++++++--
 .../Shared/Partials/_CreateOrUpdateAddress.cshtml    |  2 +-
 .../Views/ShoppingCart/EmailWishlist.cshtml          | 12 +++++++++---
 10 files changed, 65 insertions(+), 9 deletions(-)

diff --git a/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs b/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
index 4e30f67e80..7deca315ce 100644
--- a/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
+++ b/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
@@ -519,6 +519,13 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder)
                 "Pro Maschine ausführen",
                 "Indicates whether the task is executed decidedly on each machine of a web farm.",
                 "Gibt an, ob die Aufgabe auf jeder Maschine einer Webfarm dezidiert ausgeführt wird.");
+
+            builder.Delete("Address.Fields.Required.Hint");
+
+            builder.AddOrUpdate("Common.FormFields.Required.Hint",
+                "* Input elements with asterisk are required and have to be filled out.",
+                "* Eingabefelder mit Sternchen sind Pflichfelder und müssen ausgefüllt werden.");
+
         }
     }
 }
diff --git a/src/Presentation/SmartStore.Web/Views/Customer/ChangePassword.cshtml b/src/Presentation/SmartStore.Web/Views/Customer/ChangePassword.cshtml
index e4c1c51bb6..fe65dbef52 100644
--- a/src/Presentation/SmartStore.Web/Views/Customer/ChangePassword.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Customer/ChangePassword.cshtml
@@ -48,6 +48,12 @@
         </div>
     </div>
 
+    <div class="form-group row">
+        <div class="col col-sm-auto offset-sm-4 text-muted">
+            @T("Common.FormFields.Required.Hint")
+        </div>
+    </div>
+
     <div class="form-group row">
         <div class="col">
             <button type="submit" class="btn btn-lg btn-primary">
diff --git a/src/Presentation/SmartStore.Web/Views/Customer/Info.cshtml b/src/Presentation/SmartStore.Web/Views/Customer/Info.cshtml
index 1d85d0d82c..4f099e776a 100644
--- a/src/Presentation/SmartStore.Web/Views/Customer/Info.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Customer/Info.cshtml
@@ -286,6 +286,12 @@
         </fieldset>
     }
 
+    <div class="form-group row">
+        <div class="col-12 text-muted">
+            @T("Common.FormFields.Required.Hint")
+        </div>
+    </div>
+
     <div class="form-group row">
         <div class="col">
             <button type="submit" name="save-info-button" class="btn btn-primary btn-lg save-customer-info-button">
diff --git a/src/Presentation/SmartStore.Web/Views/Customer/Register.cshtml b/src/Presentation/SmartStore.Web/Views/Customer/Register.cshtml
index b2346da2e7..0f8f0b1cd6 100644
--- a/src/Presentation/SmartStore.Web/Views/Customer/Register.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Customer/Register.cshtml
@@ -247,6 +247,12 @@
 					</fieldset>
 				}
 
+                <div class="form-group row">
+                    <div class="col-12 text-muted">
+                        @T("Common.FormFields.Required.Hint")
+                    </div>
+                </div>
+
 				<div class="form-group row">
 					<div class="col">
 						<button type="submit" class="btn btn-primary btn-lg" name="register-button">
diff --git a/src/Presentation/SmartStore.Web/Views/Home/ContactUs.cshtml b/src/Presentation/SmartStore.Web/Views/Home/ContactUs.cshtml
index c729ae5157..c48eada596 100644
--- a/src/Presentation/SmartStore.Web/Views/Home/ContactUs.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Home/ContactUs.cshtml
@@ -51,6 +51,13 @@
 						@Html.ValidationMessageFor(model => model.Enquiry)
 					</div>
 				</div>
+
+                <div class="form-group row">
+                    <div class="col col-sm-auto offset-sm-3 text-muted">
+                        @T("Common.FormFields.Required.Hint")
+                    </div>
+                </div>
+
 				<div class="row justify-content-end">
 					<div class="col-sm-9">
 						@{ Html.RenderWidget("gdpr_consent"); }
diff --git a/src/Presentation/SmartStore.Web/Views/Product/AskQuestion.cshtml b/src/Presentation/SmartStore.Web/Views/Product/AskQuestion.cshtml
index 7594c9ae57..5c7cc79ddb 100644
--- a/src/Presentation/SmartStore.Web/Views/Product/AskQuestion.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Product/AskQuestion.cshtml
@@ -60,6 +60,12 @@
                 @Html.ValidationMessageFor(model => model.Question, null, new { @class = "text-danger" })
             </div>
 
+            <div class="form-group row">
+                <div class="col-12 text-muted">
+                    @T("Common.FormFields.Required.Hint")
+                </div>
+            </div>
+
 			@{ Html.RenderWidget("gdpr_consent"); }
 
             @if (Model.DisplayCaptcha)
diff --git a/src/Presentation/SmartStore.Web/Views/Product/EmailAFriend.cshtml b/src/Presentation/SmartStore.Web/Views/Product/EmailAFriend.cshtml
index 5e446d75ee..7c45610a27 100644
--- a/src/Presentation/SmartStore.Web/Views/Product/EmailAFriend.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Product/EmailAFriend.cshtml
@@ -28,13 +28,13 @@
                 </p>
                      
                 <div class="form-group">
-                    @Html.LabelFor(model => model.FriendEmail, new { @for = "FriendEmail" })
+                    @Html.LabelFor(model => model.FriendEmail, new { @for = "FriendEmail", @class = "col-form-label required" })
                     @Html.TextBoxFor(model => model.FriendEmail, new { @class = "fullname form-control", placeholder = T("Products.EmailAFriend.FriendEmail.Hint") })
                     @Html.ValidationMessageFor(model => model.FriendEmail, null, new { @class = "text-danger" })
                 </div>
 
                 <div class="form-group">
-                    @Html.LabelFor(model => model.YourEmailAddress, new { @for = "YourEmailAddress" })
+                    @Html.LabelFor(model => model.YourEmailAddress, new { @for = "YourEmailAddress", @class = "col-form-label" })
                     @if (Model.AllowChangedCustomerEmail)
                     {
                         @Html.TextBoxFor(model => model.YourEmailAddress, new { @class = "fullname form-control", placeholder = T("Products.EmailAFriend.YourEmailAddress.Hint") })
@@ -47,11 +47,17 @@
                 </div>
 
                 <div class="form-group">
-                    @Html.LabelFor(model => model.PersonalMessage, new { @for = "PersonalMessage" })
+                    @Html.LabelFor(model => model.PersonalMessage, new { @for = "PersonalMessage", @class = "col-form-label" })
                     @Html.TextAreaFor(model => model.PersonalMessage, new { @class = "personal-message form-control", placeholder = T("Products.EmailAFriend.PersonalMessage.Hint") })
                     @Html.ValidationMessageFor(model => model.PersonalMessage, null, new { @class = "text-danger" })
                 </div>
 
+                <div class="form-group">
+                    <div class="col-12 text-muted">
+                        @T("Common.FormFields.Required.Hint")
+                    </div>
+                </div>
+
 				@{ Html.RenderWidget("gdpr_consent"); }
 
                 @if (Model.DisplayCaptcha)
diff --git a/src/Presentation/SmartStore.Web/Views/Product/Reviews.cshtml b/src/Presentation/SmartStore.Web/Views/Product/Reviews.cshtml
index 4314b61d2f..563fbcab8e 100644
--- a/src/Presentation/SmartStore.Web/Views/Product/Reviews.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Product/Reviews.cshtml
@@ -58,19 +58,25 @@
                         </div>
                     </div>
                     <div class="form-group row">
-                        @Html.LabelFor(model => model.Title, new { @class = "form-control-label col-form-label col-md-3" })
+                        @Html.LabelFor(model => model.Title, new { @class = "form-control-label col-form-label col-md-3 required" })
 						<div class="col-md-9">
 							@Html.TextBoxFor(model => model.Title, Model.CanCurrentCustomerLeaveReview ? (object)(new { @class = "form-control" }) : (object)(new { @class = "form-control", disabled = "disabled" }))
 							@Html.ValidationMessageFor(model => model.Title, null)
 						</div>
                     </div>
                     <div class="form-group row">
-                        @Html.LabelFor(model => model.ReviewText, new { @class = "form-control-label col-form-label col-md-3" })
+                        @Html.LabelFor(model => model.ReviewText, new { @class = "form-control-label col-form-label col-md-3 required" })
 						<div class="col-md-9">
 							@Html.TextAreaFor(model => model.ReviewText, 4, 1, Model.CanCurrentCustomerLeaveReview ? (object)(new { @class = "form-control" }) : (object)(new { @class = "form-control", disabled = "disabled" }))
 							@Html.ValidationMessageFor(model => model.ReviewText, null)
 						</div>
                     </div>
+                    
+                    <div class="form-group">
+                        <div class="col col-sm-auto offset-sm-3 text-muted">
+                            @T("Common.FormFields.Required.Hint")
+                        </div>
+                    </div>
 
 					<div class="row justify-content-end">
 						<div class="col-sm-9">
diff --git a/src/Presentation/SmartStore.Web/Views/Shared/Partials/_CreateOrUpdateAddress.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/Partials/_CreateOrUpdateAddress.cshtml
index ebae675586..f5ac141f36 100644
--- a/src/Presentation/SmartStore.Web/Views/Shared/Partials/_CreateOrUpdateAddress.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Shared/Partials/_CreateOrUpdateAddress.cshtml
@@ -129,7 +129,7 @@
 
     <div class="form-group row">
         <div class="offset-@breakpoint-3 col-@breakpoint-9 text-muted address-required-hint">
-            @T("Address.Fields.Required.Hint")
+            @T("Common.FormFields.Required.Hint")
         </div>
     </div>
 
diff --git a/src/Presentation/SmartStore.Web/Views/ShoppingCart/EmailWishlist.cshtml b/src/Presentation/SmartStore.Web/Views/ShoppingCart/EmailWishlist.cshtml
index 7ef0ad471b..eaa29675f4 100644
--- a/src/Presentation/SmartStore.Web/Views/ShoppingCart/EmailWishlist.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/ShoppingCart/EmailWishlist.cshtml
@@ -32,23 +32,29 @@
                     </p>
                 
                     <div class="form-group">
-                        @Html.LabelFor(model => model.FriendEmail, new { @for = "FriendEmail" })
+                        @Html.LabelFor(model => model.FriendEmail, new { @for = "FriendEmail", @class = "col-form-label required" })
                         @Html.TextBoxFor(model => model.FriendEmail, new { @class = "friend-email form-control", placeholder = T("Wishlist.EmailAFriend.FriendEmail.Hint") })
                         @Html.ValidationMessageFor(model => model.FriendEmail)
                     </div>
 
                     <div class="form-group">
-                        @Html.LabelFor(model => model.YourEmailAddress, new { @for = "YourEmailAddress" })
+                        @Html.LabelFor(model => model.YourEmailAddress, new { @for = "YourEmailAddress", @class = "col-form-label required" })
                         @Html.TextBoxFor(model => model.YourEmailAddress, new { @class = "your-email form-control", placeholder = T("Wishlist.EmailAFriend.YourEmailAddress.Hint") })
                         @Html.ValidationMessageFor(model => model.YourEmailAddress)
                     </div>
 
                     <div class="form-group">
-                        @Html.LabelFor(model => model.PersonalMessage, new { @for = "PersonalMessage" })
+                        @Html.LabelFor(model => model.PersonalMessage, new { @for = "PersonalMessage", @class = "col-form-label" })
                         @Html.TextAreaFor(model => model.PersonalMessage, new { @class = "personal-message form-control", placeholder = T("Wishlist.EmailAFriend.PersonalMessage.Hint") })
                         @Html.ValidationMessageFor(model => model.PersonalMessage)
                     </div>
 
+                    <div class="form-group row">
+                        <div class="col-12 text-muted">
+                            @T("Common.FormFields.Required.Hint")
+                        </div>
+                    </div>
+
 					@{ Html.RenderWidget("gdpr_consent"); }
 
                     @if (Model.DisplayCaptcha)

From 22dcc7683b73103741ec9cf07204c23f2fde0649 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Wed, 26 Sep 2018 21:40:58 +0200
Subject: [PATCH 14/71] More on published property of forum topic and forum
 post

---
 .../SmartStore.Web/Content/shared/_card.scss     | 16 ++++++++++++----
 .../Controllers/BoardsController.cs              |  8 ++++----
 .../Themes/Flex/Content/_forum.scss              |  5 +++++
 .../SmartStore.Web/Views/Boards/Forum.cshtml     |  4 ++--
 .../Views/Boards/Partials/_ActiveTopics.cshtml   |  4 ++--
 .../Boards/Partials/_CreateUpdatePost.cshtml     |  9 ++++++++-
 .../Views/Boards/Partials/_ForumPost.cshtml      | 15 +++++++--------
 .../SmartStore.Web/Views/Boards/Topic.cshtml     | 10 ++++------
 .../SmartStore.Web/Views/Boards/TopicMove.cshtml |  6 ++----
 9 files changed, 46 insertions(+), 31 deletions(-)

diff --git a/src/Presentation/SmartStore.Web/Content/shared/_card.scss b/src/Presentation/SmartStore.Web/Content/shared/_card.scss
index 6134f0f9b3..676fd52e9b 100644
--- a/src/Presentation/SmartStore.Web/Content/shared/_card.scss
+++ b/src/Presentation/SmartStore.Web/Content/shared/_card.scss
@@ -29,44 +29,52 @@
     margin-bottom: 0 !important;
 }
 
+.card-body.disabled { 
+    opacity: .5;
+}
 
 // "Real" responsive card decks & groups
 // Remove this, once BS4 natively supports responsive card decks & groups
 // ======================================================================
-
 @mixin card-deck-responsive($breakpoint) {
     $m: $card-deck-margin * 2;
+
     .card-deck {
         &.card-cols-#{$breakpoint}-1 .card {
             -ms-flex: 1 0 100% !important;
             flex: 1 0 calc(100% - #{$m}) !important;
             max-width: calc(100% - #{$m});
         }
+
         &.card-cols-#{$breakpoint}-2 .card {
             -ms-flex: 0 0 50% !important;
             flex: 0 0 calc(50% - #{$m}) !important;
             max-width: calc(50% - #{$m});
         }
-        &.card-cols-#{$breakpoint}-3 .card { 
-            -ms-flex: 0 0 33.333% !important; 
+
+        &.card-cols-#{$breakpoint}-3 .card {
+            -ms-flex: 0 0 33.333% !important;
             flex: 0 0 calc(33.333% - #{$m}) !important;
             max-width: calc(33.333% - #{$m});
         }
+
         &.card-cols-#{$breakpoint}-4 .card {
             -ms-flex: 0 0 25% !important;
             flex: 0 0 calc(25% - #{$m}) !important;
             max-width: calc(25% - #{$m});
         }
+
         &.card-cols-#{$breakpoint}-5 .card {
             -ms-flex: 0 0 20% !important;
             flex: 0 0 calc(20% - #{$m}) !important;
             max-width: calc(20% - #{$m});
         }
+
         &.card-cols-#{$breakpoint}-6 .card {
             -ms-flex: 0 0 16.666% !important;
             flex: 0 0 calc(16.666% - #{$m}) !important;
             max-width: calc(16.666% - #{$m});
-        }   
+        }
     }
 }
 
diff --git a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
index 5f4203551f..96003cf4f5 100644
--- a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
+++ b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
@@ -273,7 +273,7 @@ private void CreateForumBreadcrumb(ForumGroup group = null, Forum forum = null,
 			forum = forum ?? topic?.Forum;
 			if (forum != null)
 			{
-				var forumName = group.GetLocalized(x => x.Name);
+				var forumName = forum.GetLocalized(x => x.Name);
 				_breadcrumb.Track(new MenuItem
 				{
 					Text = forumName,
@@ -1064,7 +1064,7 @@ public ActionResult TopicEdit(int id)
                 IsCustomerAllowedToEdit = _forumService.IsCustomerAllowedToEditTopic(customer, topic)
             };
 
-            if (!model.IsCustomerAllowedToEdit && customer.Id != topic.CustomerId)
+            if (!model.IsCustomerAllowedToEdit)
             {
                 return new HttpUnauthorizedResult();
             }
@@ -1433,7 +1433,7 @@ public ActionResult PostEdit(int id)
             {
                 Id = post.Id,
                 IsEdit = true,
-                Published = true,
+                Published = post.Published,
                 ForumTopicId = post.ForumTopic.Id,
                 DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnForumPage,
                 ForumEditor = _forumSettings.ForumEditor,
@@ -1448,7 +1448,7 @@ public ActionResult PostEdit(int id)
                 IsCustomerAllowedToEdit = _forumService.IsCustomerAllowedToEditPost(customer, post)
             };
 
-            if (!model.IsCustomerAllowedToEdit && customer.Id != post.CustomerId)
+            if (!model.IsCustomerAllowedToEdit)
             {
                 return new HttpUnauthorizedResult();
             }
diff --git a/src/Presentation/SmartStore.Web/Themes/Flex/Content/_forum.scss b/src/Presentation/SmartStore.Web/Themes/Flex/Content/_forum.scss
index fde5be7236..971984f6e3 100644
--- a/src/Presentation/SmartStore.Web/Themes/Flex/Content/_forum.scss
+++ b/src/Presentation/SmartStore.Web/Themes/Flex/Content/_forum.scss
@@ -69,6 +69,11 @@ $forum-unobstrusive-link-color: #646464;
 	white-space: nowrap;
 }
 
+.topics-group .topic.disabled {
+    opacity: .5;
+}
+
+
 /* Forum Topic
 ================================================ */
 .forum-topic {
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/Forum.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/Forum.cshtml
index 5751f09138..ac5022ded4 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/Forum.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/Forum.cshtml
@@ -58,7 +58,7 @@
     <div>
         <div class="actions my-3 row sm-gutters">
             <div class="col col-sm-auto mt-1 mt-sm-0">
-                <a href='@Url.Action("TopicCreate", new { id = Model.Id })' class="btn btn-primary newtopic btn-block" rel="nofollow">
+                <a href="@Url.Action("TopicCreate", new { id = Model.Id })" class="btn btn-primary newtopic btn-block" rel="nofollow">
                     <i class="fa fa-plus"></i>
                     <span>@T("Forum.NewTopic")</span>
                 </a>
@@ -101,7 +101,7 @@
             }
             @foreach (var topic in Model.ForumTopics)
             {
-                <tr class="topic">
+                <tr class="topic@(topic.Published ? "" : " disabled")">
                     <td class="image">
                         @{ Html.RenderPartial("Customer.Avatar", topic.Avatar); }
                     </td>
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ActiveTopics.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ActiveTopics.cshtml
index ed406257d6..f59ca9deb5 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ActiveTopics.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ActiveTopics.cshtml
@@ -30,10 +30,10 @@
             
             @if (isPartial)
             {        
-                <button class="btn btn-outline-info btn-flat" onclick="setLocation('@Url.Action("ActiveDiscussions")')">
+                <a class="btn btn-outline-info btn-flat" href="@Url.Action("ActiveDiscussions")">
                     <i class="fa fa-th-list"></i>
                     <span>@T("Forum.ActiveDiscussions.ViewAll")</span>
-                </button>
+                </a>
             }
         </div>
     </div>
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/Partials/_CreateUpdatePost.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/Partials/_CreateUpdatePost.cshtml
index 48d3d6a5df..e578941f00 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/Partials/_CreateUpdatePost.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/Partials/_CreateUpdatePost.cshtml
@@ -2,6 +2,13 @@
 @using SmartStore.Web;
 @using SmartStore.Web.Models.Boards;
 @model EditForumPostModel
+@{
+    var cancelUrl = Url.RouteUrl("TopicSlug", new { id = Model.ForumTopicId, slug = Model.ForumTopicSeName });
+    if (Model.Id != 0)
+    {
+        cancelUrl = string.Concat(cancelUrl, "#", Model.Id);
+    }
+}
 @using (Html.BeginForm())
 {
     <div class="page post-edit">
@@ -86,7 +93,7 @@
                     <i class="fa fa-reply"></i>
                     <span>@T("Forum.Submit")</span>
                 </button>
-                <a class="btn btn-secondary" href="@Url.RouteUrl("TopicSlug", new { id = Model.ForumTopicId, slug = Model.ForumTopicSeName })">
+                <a class="btn btn-secondary" href="@cancelUrl">
                     <i class="fa fa-times"></i>
                     <span>@T("Forum.Cancel")</span>
                 </a>
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ForumPost.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ForumPost.cshtml
index a05c41b657..e257858c2c 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ForumPost.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ForumPost.cshtml
@@ -2,7 +2,7 @@
 @model ForumPostModel
 @Html.Raw("<a name=\"{0}\"></a>".FormatInvariant(Model.Id))
 
-<div class="block block-bordered forum-post card" id="@Html.Encode(String.Format("post{0}", Model.Id))">
+<div class="block block-bordered forum-post card" id="post@(Model.Id)">
     <div class="block-title card-header">
         @if (Model.CustomerId > 0)
         {
@@ -17,7 +17,6 @@
         }
 
         <div class="d-flex align-items-center">
-
             @if (Model.IsCurrentCustomerAllowedToEditPost)
             {
                 <i class="fa fa-pencil-square-o"></i>
@@ -41,7 +40,7 @@
         </div>
     </div>
 
-    <div class="block-body card-body row">
+    <div class="block-body card-body row@(Model.Published ? "" : " disabled")">
         <div class="post-info col-2 d-none d-sm-block">
             <div class="user-info mt-3 text-center">
                 <div class="avatar">
@@ -69,7 +68,7 @@
 							<span class="stat-value">@Model.CustomerJoinDate.ToNativeString("d")</span>
                         </div>
                     }
-                    @if (Model.ShowCustomersLocation && !Model.IsCustomerGuest & !String.IsNullOrEmpty(Model.CustomerLocation))
+                    @if (Model.ShowCustomersLocation && !Model.IsCustomerGuest && Model.CustomerLocation.HasValue())
                     {
                         <div class="location">
                             <span class="pr-1">@T("Forum.Location"):</span>
@@ -78,7 +77,7 @@
                     }
                     @if (Model.AllowPrivateMessages && !Model.IsCustomerGuest)
 				    {
-                        <a class="btn btn btn-outline-info btn-flat button-pm mt-2" rel="nofollow" href='@Url.Action("Send", "PrivateMessages", new { id = Model.CustomerId })'>
+                        <a class="btn btn btn-outline-info btn-flat button-pm mt-2" rel="nofollow" href="@Url.Action("Send", "PrivateMessages", new { id = Model.CustomerId })">
                             <i class="fa fa-user"></i>
                             <span>@T("Forum.PrivateMessages.PM")</span>
                         </a>
@@ -98,7 +97,7 @@
                 @Html.Hidden("Id", Model.Id)
             </div>
 
-            @if (Model.SignaturesEnabled & !String.IsNullOrEmpty(Model.FormattedSignature))
+            @if (Model.SignaturesEnabled && Model.FormattedSignature.HasValue())
             {
                 <div class="signature text-muted" dir="auto">
                     @Html.Raw(Model.FormattedSignature)
@@ -112,10 +111,10 @@
             <a href="#" class="btn btn-link btn-sm font-weight-600">
                 @T("Forum.Top")
             </a>
-            <button class="btn btn-outline-info btn-flat btn-sm" onclick="setLocation('@Url.Action("PostCreate", new { id = Model.ForumTopicId, quote = Model.Id })')">
+            <a class="btn btn-outline-info btn-flat btn-sm" href="@Url.Action("PostCreate", new { id = Model.ForumTopicId, quote = Model.Id })">
                 <i class="fa fa-quote-left"></i>
                 <span>@T("Forum.QuotePost")</span>
-            </button>
+            </a>
         </div>
     </div>
 </div>
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/Topic.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/Topic.cshtml
index 08c8b03b72..cd633b0952 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/Topic.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/Topic.cshtml
@@ -52,14 +52,13 @@
     @ButtonBar()
 
     <div class="posts">
-        @foreach (var post in @Model.ForumPostModels)
+        @foreach (var post in Model.ForumPostModels)
         {
             Html.RenderPartial("_ForumPost", post);
         }
     </div>
 
     @ButtonBar()
-
 </div>
 
 @helper ButtonBar()
@@ -72,12 +71,11 @@
 
     <div class="topic-options row my-2">
 		<div class="col">
-			<button class="btn btn-primary" onclick="setLocation('@Url.Action("PostCreate", new { id = @Model.Id })')">
+			<a class="btn btn-primary" href="@Url.Action("PostCreate", new { id = Model.Id })">
 				<i class="fa fa-share"></i>
 				<span>@T("Forum.Reply")</span>
-			</button>
+			</a>
 		</div>
-        
 
         @if (Model.IsCustomerAllowedToSubscribe)
         {
@@ -85,7 +83,7 @@
                 <i class="fa fa-bookmark"></i>
                 @Ajax.ActionLink(Model.WatchTopicText,
                     "TopicWatch",
-                    new { id = @Model.Id },
+                    new { id = Model.Id },
                     new AjaxOptions { HttpMethod = "Post", OnSuccess = "handleTopicWatch" },
                     new { @class = "watch-topic-link-button" })
             </div>
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/TopicMove.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/TopicMove.cshtml
index be35d61a84..15e314e63c 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/TopicMove.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/TopicMove.cshtml
@@ -11,10 +11,8 @@
         <div class="page-title">
             <h2>@T("Forum.MoveTopic")</h2>
         </div>
-
         <div class="page-body">
             <h4 class="my-3">@T("Forum.SelectTheForumToMoveTopic")</h4>
-
             <div>
                 @Html.DropDownList("ForumSelected", new SelectList(Model.ForumList, "Value", "Text"), new { @class = "form-control" })
             </div>
@@ -23,9 +21,9 @@
                 <button type="submit" class="btn btn-primary">
 					<span>@T("Forum.Submit")</span>
 				</button>
-                <button class="btn btn-secondary" onclick="setLocation('@Url.RouteUrl("TopicSlug", new { id = Model.Id, slug = Model.TopicSeName })')">
+                <a class="btn btn-secondary" href="@Url.RouteUrl("TopicSlug", new { id = Model.Id, slug = Model.TopicSeName })">
                     <span>@T("Forum.Cancel")</span>
-                </button>
+                </a>
             </div>
         </div>
     </div>

From 7924067fbd0b0a6856491786be38e7e03fc50d77 Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Thu, 27 Sep 2018 01:08:01 +0200
Subject: [PATCH 15/71] Implemented FastInvoker for speeding up dynamic method
 invocation

---
 .../ComponentModel/FastActivator.cs           |   4 +-
 .../ComponentModel/FastInvoker.cs             | 228 ++++++++++++++++++
 .../ComponentModel/FastProperty.cs            |   2 +-
 .../SmartStore.Core/SmartStore.Core.csproj    |   1 +
 .../UI/Blocks/BlockHandlerBase.cs             |   2 +-
 5 files changed, 233 insertions(+), 4 deletions(-)
 create mode 100644 src/Libraries/SmartStore.Core/ComponentModel/FastInvoker.cs

diff --git a/src/Libraries/SmartStore.Core/ComponentModel/FastActivator.cs b/src/Libraries/SmartStore.Core/ComponentModel/FastActivator.cs
index d37ec07015..dea60d7a62 100644
--- a/src/Libraries/SmartStore.Core/ComponentModel/FastActivator.cs
+++ b/src/Libraries/SmartStore.Core/ComponentModel/FastActivator.cs
@@ -44,6 +44,8 @@ public object Activate(params object[] parameters)
 			return Invoker(parameters);
 		}
 
+		#region Static
+
 		/// <summary>
 		/// Creates a single fast constructor invoker. The result is not cached.
 		/// </summary>
@@ -78,8 +80,6 @@ public static Func<object[], object> MakeFastInvoker(ConstructorInfo constructor
 			return lambda.Compile();
 		}
 
-		#region Static
-
 		/// <summary>
 		/// Creates and caches fast constructor invokers 
 		/// </summary>
diff --git a/src/Libraries/SmartStore.Core/ComponentModel/FastInvoker.cs b/src/Libraries/SmartStore.Core/ComponentModel/FastInvoker.cs
new file mode 100644
index 0000000000..d88dbc43ae
--- /dev/null
+++ b/src/Libraries/SmartStore.Core/ComponentModel/FastInvoker.cs
@@ -0,0 +1,228 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Linq.Expressions;
+using System.Collections.Concurrent;
+using SmartStore.Utilities;
+
+namespace SmartStore.ComponentModel
+{
+	public class FastInvoker
+	{
+		private static readonly ConcurrentDictionary<MethodKey, FastInvoker> _invokersCache = new ConcurrentDictionary<MethodKey, FastInvoker>();
+
+		public FastInvoker(MethodInfo methodInfo)
+		{
+			Guard.NotNull(methodInfo, nameof(methodInfo));
+
+			Method = methodInfo;
+			Invoker = MakeFastInvoker(methodInfo);
+			ParameterTypes = methodInfo.GetParameters().Select(p => p.ParameterType).ToArray();
+		}
+
+		/// <summary>
+		/// Gets the backing <see cref="MethodInfo"/>.
+		/// </summary>
+		public MethodInfo Method { get; private set; }
+
+		/// <summary>
+		/// Gets the parameter types from the backing <see cref="MethodInfo"/>
+		/// </summary>
+		public Type[] ParameterTypes { get; private set; }
+
+		/// <summary>
+		/// Gets the method invoker.
+		/// </summary>
+		public Func<object, object[], object> Invoker { get; private set; }
+
+		/// <summary>
+		/// Invokes the method using the specified parameters.
+		/// </summary>
+		/// <returns>The method invocation result.</returns>
+		public object Invoke(object obj, params object[] parameters)
+		{
+			return Invoker(obj, parameters);
+		}
+
+		#region Static
+
+		/// <summary>
+		/// Creates a single fast method invoker. The result is not cached.
+		/// </summary>
+		/// <param name="method">Method to create invoker for.</param>
+		/// <returns>The fast method invoker delegate.</returns>
+		public static Func<object, object[], object> MakeFastInvoker(MethodInfo method)
+		{
+			Guard.NotNull(method, nameof(method));
+
+			var instanceParameterExpression = Expression.Parameter(typeof(object), "instance");
+			var argumentsParameterExpression = Expression.Parameter(typeof(object[]), "args");
+			var index = 0;
+
+			var argumentExtractionExpressions =
+				method
+			   .GetParameters()
+			   .Select(parameter =>
+				  Expression.Convert(
+					 Expression.ArrayAccess(
+						argumentsParameterExpression,
+						Expression.Constant(index++)
+					 ),
+					 parameter.ParameterType
+				  )
+			   ).ToList();
+
+			var callExpression = method.IsStatic
+			   ? Expression.Call(method, argumentExtractionExpressions)
+			   : Expression.Call(
+				  Expression.Convert(
+					 instanceParameterExpression,
+					 method.DeclaringType
+				  ),
+				  method,
+				  argumentExtractionExpressions
+			   );
+
+			var endLabel = Expression.Label(typeof(object));
+
+			var finalExpression = method.ReturnType == typeof(void)
+			   ? (Expression)Expression.Block(
+					callExpression,
+					Expression.Return(endLabel, Expression.Constant(null)),
+					Expression.Label(endLabel, Expression.Constant(null))
+				 )
+			   : Expression.Convert(callExpression, typeof(object));
+
+			var lambdaExpression = Expression.Lambda<Func<object, object[], object>>(
+			   finalExpression,
+			   instanceParameterExpression,
+			   argumentsParameterExpression
+			);
+
+			var lamdba = lambdaExpression.Compile();
+			return lamdba;
+		}
+
+		/// <summary>
+		/// Invokes a method using the specified object and parameter instances.
+		/// </summary>
+		/// <param name="obj">The objectinstance</param>
+		/// <param name="methodName">Method name</param>
+		/// <param name="parameterTypes">Argument types of the matching method overload (in exact order)</param>
+		/// <param name="parameters">Parameter instances to pass to invocation</param>
+		/// <returns>The method invocation result.</returns>
+		public static object Invoke(object obj, string methodName, Type[] parameterTypes, object[] parameters)
+		{
+			Guard.NotNull(obj, nameof(obj));
+
+			FastInvoker invoker;
+
+			if (parameterTypes == null || parameterTypes.Length == 0)
+			{
+				invoker = GetInvoker(obj.GetType(), methodName);
+			}
+			else
+			{
+				invoker = GetInvoker(obj.GetType(), methodName, parameterTypes);
+			}
+
+			//var hasAnyNullParam = parameters.Any(x => x == null);
+			//if (hasAnyNullParam)
+			//{
+			//	throw new ArgumentException("When invoking a method with parameter instances, no instance must be null.", nameof(parameters));
+			//}
+
+			return invoker.Invoke(obj, parameters ?? Array.Empty<object>());
+		}
+
+		/// <summary>
+		/// Creates and caches a fast method invoker.
+		/// </summary>
+		/// <param name="methodInfo">Method info instance to create an invoker for.</param>
+		/// <returns>The fast method invoker.</returns>
+		public static FastInvoker GetInvoker(MethodInfo methodInfo)
+		{
+			Guard.NotNull(methodInfo, nameof(methodInfo));
+
+			return GetInvoker(
+				methodInfo.DeclaringType, 
+				methodInfo.Name,
+				methodInfo.GetParameters().Select(x => x.ParameterType).ToArray());
+		}
+
+		/// <summary>
+		/// Creates and caches a fast method invoker.
+		/// </summary>
+		/// <param name="methodName">Name of method to create an invoker for.</param>
+		/// <param name="argTypes">Argument types of method to create an invoker for.</param>
+		/// <returns>The fast method invoker.</returns>
+		public static FastInvoker GetInvoker<T>(string methodName, params Type[] argTypes)
+		{
+			return GetInvoker(typeof(T), methodName, argTypes);
+		}
+
+		/// <summary>
+		/// Creates and caches a fast method invoker.
+		/// </summary>
+		/// <param name="type">The type to extract fast method invoker for.</param>
+		/// <param name="methodName">Name of method to create an invoker for.</param>
+		/// <param name="argTypes">Argument types of method to create an invoker for.</param>
+		/// <returns>The fast method invoker.</returns>
+		public static FastInvoker GetInvoker(Type type, string methodName, params Type[] argTypes)
+		{
+			Guard.NotNull(type, nameof(type));
+			Guard.NotEmpty(methodName, nameof(methodName));
+
+			var cacheKey = MethodKey.Create(type, methodName, argTypes);
+
+			if (!_invokersCache.TryGetValue(cacheKey, out var invoker))
+			{
+				var method = FindMatchingMethod(type, methodName, argTypes);
+
+				if (method == null)
+				{
+					throw new MethodAccessException("Could not find a matching method '{0}' in type {1}.".FormatInvariant(methodName, type));
+				}
+
+				invoker = new FastInvoker(method);
+				_invokersCache.TryAdd(cacheKey, invoker);
+			}
+
+			return invoker;
+		}
+
+		private static MethodInfo FindMatchingMethod(Type type, string methodName, Type[] argTypes)
+		{
+			var method = argTypes == null || argTypes.Length == 0 
+				? type.GetMethod(methodName)
+				: type.GetMethod(
+					methodName,
+					BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
+					null,
+					argTypes ?? new Type[0],
+					null);
+
+			return method;
+		}
+
+		#endregion
+
+		class MethodKey : Tuple<Type, string, int>
+		{
+			public MethodKey(Type type, string methodName, int parametersHash)
+				: base(type, methodName, parametersHash)
+			{
+			}
+			public Type Type { get { return base.Item1; } }
+			public string MethodName { get { return base.Item2; } }
+			public int ParameterHash { get { return base.Item3; } }
+
+			public static MethodKey Create(Type type, string methodName, IEnumerable<Type> parameterTypes)
+			{
+				var hashCombiner = HashCodeCombiner.Start().Add(parameterTypes);
+				return new MethodKey(type, methodName, hashCombiner.CombinedHash);
+			}
+		}
+	}
+}
diff --git a/src/Libraries/SmartStore.Core/ComponentModel/FastProperty.cs b/src/Libraries/SmartStore.Core/ComponentModel/FastProperty.cs
index 4ad5aebee4..7aafa809cd 100644
--- a/src/Libraries/SmartStore.Core/ComponentModel/FastProperty.cs
+++ b/src/Libraries/SmartStore.Core/ComponentModel/FastProperty.cs
@@ -543,7 +543,7 @@ protected static IDictionary<string, FastProperty> GetVisibleProperties(
 			{
 				return result;
 			}
-
+			
 			// The simple and common case, this is normal POCO object - no need to allocate.
 			var allPropertiesDefinedOnType = true;
 			var allProperties = GetProperties(type, createPropertyHelper, allPropertiesCache);
diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj
index 98f3bb0cb0..2a4eafc78f 100644
--- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj
+++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj
@@ -181,6 +181,7 @@
     <Compile Include="Collections\Querystring.cs" />
     <Compile Include="Collections\TopologicalSorter.cs" />
     <Compile Include="Collections\TreeNodeBase.cs" />
+    <Compile Include="ComponentModel\FastInvoker.cs" />
     <Compile Include="ComponentModel\MiniMapper.cs" />
     <Compile Include="Collections\ReferenceEqualityComparer.cs" />
     <Compile Include="ComponentModel\TypeConversion\BooleanConverter.cs" />
diff --git a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockHandlerBase.cs b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockHandlerBase.cs
index 93c100e955..0d395920de 100644
--- a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockHandlerBase.cs
+++ b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockHandlerBase.cs
@@ -89,7 +89,7 @@ protected virtual void RenderCore(IBlockContainer element, string[] templates, H
 				throw new InvalidOperationException("The return value of the 'GetRoute()' method cannot be NULL.");
 			}
 
-			routeInfo.RouteValues["model"] = element.Block;
+			//routeInfo.RouteValues["model"] = element.Block;
 
 			var originalWriter = htmlHelper.ViewContext.Writer;
 			htmlHelper.ViewContext.Writer = textWriter;

From 9668c0a404b737155455c6b0c0e62290d7584f25 Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Thu, 27 Sep 2018 03:14:41 +0200
Subject: [PATCH 16/71] CSS enhancements in admin theme

---
 .../Administration/Content/_admin.scss        | 65 ++++++++++---------
 .../Scripts/admin.globalinit.js               |  2 +-
 2 files changed, 35 insertions(+), 32 deletions(-)

diff --git a/src/Presentation/SmartStore.Web/Administration/Content/_admin.scss b/src/Presentation/SmartStore.Web/Administration/Content/_admin.scss
index 6c00126382..c0180abd6b 100644
--- a/src/Presentation/SmartStore.Web/Administration/Content/_admin.scss
+++ b/src/Presentation/SmartStore.Web/Administration/Content/_admin.scss
@@ -3,6 +3,17 @@
 /// <reference path="../../Content/shared/_mixins.scss" />
 /// <reference path="../../Content/bs4/scss/bootstrap.scss" />
 
+$section-header-height: 70px;
+
+:root {
+    --content-padding-x: $content-padding-x / 2;
+    --content-padding-y: $content-padding-y;
+
+    @include media-breakpoint-up(lg) {
+        --content-padding-x: $content-padding-x;
+    }
+}
+
 //
 // Legacy BS elements
 // --------------------------------------------------
@@ -122,22 +133,19 @@ body {
 
 #content {
 	position: relative;
-	margin: 0 ($content-padding-x / 2);
-	padding: $content-padding-y ($content-padding-x / 2);
-	padding-bottom: $content-padding-x * 2;
+	margin: 0 var(--content-padding-x);
+	padding-left: var(--content-padding-x);
+    padding-right: var(--content-padding-x);
+    padding-top: $section-header-height;
+    padding-bottom: $content-padding-x * 2;
+
     box-shadow: 0 8px 16px rgba(#32325d, .1), 0 -2px 8px rgba(#000, .09);
 	border-radius: $border-radius-lg $border-radius-lg 0 0;
     background-color: #fff;
     grid-column: 1 / -1;
     grid-row: 2 / -1;
     z-index: 9;
-
-	@include media-breakpoint-up(lg) {
-		margin-left: $content-padding-x;
-		margin-right: $content-padding-x;
-		padding-left: $content-padding-x;
-		padding-right: $content-padding-x;
-	}
+    overflow-x: hidden;
 
     .popup & {
 	    margin: 0;
@@ -149,7 +157,6 @@ body {
 }
 
 .cph {
-    position: relative;
     display: flex;
     flex-flow: column;
 }
@@ -167,9 +174,16 @@ body {
 }
 
 .section-header {
-    padding-bottom: 0.75rem;
-	transition: background-color 0.1s ease-in-out;
-
+    position: absolute;
+    left: 0;
+    top: 0;
+    right: 0;
+    padding-left: var(--content-padding-x);
+	padding-right: var(--content-padding-x);
+    padding-top: var(--content-padding-y);
+    padding-bottom: var(--content-padding-y);
+    transition: box-shadow 0.25s ease;
+    
 	@include make-row();
 	flex-wrap: nowrap;
 	margin-left: 0;
@@ -245,29 +259,18 @@ body {
 	&.sticky {
 		position: fixed;
 		z-index: 600;
-		left: $content-padding-x / 2;
-		right: $content-padding-x / 2;
-        top: 0;
-		padding-left: $content-padding-x / 2;
-		padding-right: $content-padding-x / 2;
-        padding-top: $content-padding-y;
-		margin-left: 0 !important;
-		margin-right: 0 !important;
-		background: $gray-100;
+		left: var(--content-padding-x);
+		right: var(--content-padding-x);
+        padding-left: var(--content-padding-x);
+		padding-right: var(--content-padding-x);
 		background: #fff;
-		border-bottom: 1px solid rgba(0,0,0, 0.08);
+		//border-bottom: 1px solid rgba(0,0,0, 0.08); 
+        box-shadow: 0 8px 16px 0 rgba(#32325d, .1), 0 2px 7px 0 rgba(#000, .07);
 
 		.modal-open & {
 			// add the killed scrollbar width
 			margin-right: 17px !important;
 		}
-
-	    @include media-breakpoint-up(lg) {
-			left: $content-padding-x;
-			right: $content-padding-x;
-            padding-left: $content-padding-x;
-		    padding-right: $content-padding-x;
-	    }
 	}
 }
 
diff --git a/src/Presentation/SmartStore.Web/Administration/Scripts/admin.globalinit.js b/src/Presentation/SmartStore.Web/Administration/Scripts/admin.globalinit.js
index f5197676da..07c3abeb5f 100644
--- a/src/Presentation/SmartStore.Web/Administration/Scripts/admin.globalinit.js
+++ b/src/Presentation/SmartStore.Web/Administration/Scripts/admin.globalinit.js
@@ -123,7 +123,7 @@
 
         // sticky section-header
         var navbar = $("#navbar");
-        var navbarHeight = navbar.height() || 0;
+        var navbarHeight = navbar.height() || 1;
         var sectionHeader = $('.section-header');
         var sectionHeaderHasButtons = undefined;
 

From 4df91fd42f9fbbf2121ad8590ebc88dee2123a2c Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Thu, 27 Sep 2018 09:30:15 +0200
Subject: [PATCH 17/71] Removed default avatar setting (obsolete)

---
 .../Domain/Customers/CustomerSettings.cs          |   6 ------
 .../SmartStore.Core/Domain/Media/PictureType.cs   |   5 +----
 .../Migrations/MigrationsConfiguration.cs         |   1 +
 .../SmartStore.Services/Media/PictureService.cs   |  10 ++--------
 .../Models/Settings/CustomerUserSettingsModel.cs  |   5 +----
 .../Views/Setting/CustomerUser.cshtml             |  11 +----------
 .../Content/Images/default-avatar.jpg             | Bin 901 -> 0 bytes
 .../Extensions/MappingExtensions.cs               |  14 +-------------
 .../SmartStore.Web/SmartStore.Web.csproj          |   1 -
 9 files changed, 7 insertions(+), 46 deletions(-)
 delete mode 100644 src/Presentation/SmartStore.Web/Content/Images/default-avatar.jpg

diff --git a/src/Libraries/SmartStore.Core/Domain/Customers/CustomerSettings.cs b/src/Libraries/SmartStore.Core/Domain/Customers/CustomerSettings.cs
index 74beb552c2..7c51a9ced5 100644
--- a/src/Libraries/SmartStore.Core/Domain/Customers/CustomerSettings.cs
+++ b/src/Libraries/SmartStore.Core/Domain/Customers/CustomerSettings.cs
@@ -14,7 +14,6 @@ public CustomerSettings()
 			PasswordMinLength = 6;
 			UserRegistrationType = UserRegistrationType.Standard;
 			AvatarMaximumSizeBytes = 512000;
-			DefaultAvatarEnabled = false;
 			CustomerNameFormat = CustomerNameFormat.ShowFirstName;
 			CustomerNameFormatMaxLength = 64;
 			GenderEnabled = true;
@@ -82,11 +81,6 @@ public CustomerSettings()
         /// </summary>
         public int AvatarMaximumSizeBytes { get; set; }
 
-        /// <summary>
-        /// Gets or sets a value indicating whether to display default user avatar.
-        /// </summary>
-        public bool DefaultAvatarEnabled { get; set; }
-
         /// <summary>
         /// Gets or sets a value indicating whether customers location is shown
         /// </summary>
diff --git a/src/Libraries/SmartStore.Core/Domain/Media/PictureType.cs b/src/Libraries/SmartStore.Core/Domain/Media/PictureType.cs
index 84d245f3be..94eb05184c 100644
--- a/src/Libraries/SmartStore.Core/Domain/Media/PictureType.cs
+++ b/src/Libraries/SmartStore.Core/Domain/Media/PictureType.cs
@@ -6,14 +6,11 @@ namespace SmartStore.Core.Domain.Media
     public enum FallbackPictureType
     {
 		NoFallback = 0,
+
 		/// <summary>
 		/// Entities (products, categories, manufacturers)
 		/// </summary>
 		Entity = 1,
-        /// <summary>
-        /// Avatar
-        /// </summary>
-        Avatar = 10,
     }
 
     public enum ThumbnailScaleMode
diff --git a/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs b/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
index 7deca315ce..b656f275f9 100644
--- a/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
+++ b/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
@@ -453,6 +453,7 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder)
             builder.Delete(
                 "Admin.Configuration.Settings.Search.DefaultSortOrderMode",
                 "Admin.Configuration.Settings.Search.InstantSearchNumberOfProducts",
+                "Admin.Configuration.Settings.CustomerUser.DefaultAvatarEnabled",
                 "Forum.Search.LimitResultsToPrevious.AllResults",
                 "Forum.Search.LimitResultsToPrevious.1day",
                 "Forum.Search.LimitResultsToPrevious.7days",
diff --git a/src/Libraries/SmartStore.Services/Media/PictureService.cs b/src/Libraries/SmartStore.Services/Media/PictureService.cs
index 4f033c9ec7..e15b780795 100644
--- a/src/Libraries/SmartStore.Services/Media/PictureService.cs
+++ b/src/Libraries/SmartStore.Services/Media/PictureService.cs
@@ -1,5 +1,4 @@
 using System;
-using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Data.Entity;
 using System.Drawing;
@@ -25,7 +24,7 @@
 
 namespace SmartStore.Services.Media
 {
-	[Serializable]
+    [Serializable]
 	public class PictureInfo
 	{
 		public int Id { get; set; }
@@ -53,7 +52,6 @@ public partial class PictureService : IPictureService
         private readonly IImageProcessor _imageProcessor;
         private readonly IImageCache _imageCache;
 		private readonly Provider<IMediaStorageProvider> _storageProvider;
-		private readonly IStoreContext _storeContext;
 		private readonly HttpContextBase _httpContext;
 		private readonly ICacheManager _cacheManager;
 
@@ -78,7 +76,7 @@ public PictureService(
             IImageProcessor imageProcessor,
             IImageCache imageCache,
 			IProviderManager providerManager,
-			IStoreContext storeContext,
+            IStoreContext storeContext,
 			HttpContextBase httpContext,
 			ICacheManager cacheManager)
         {
@@ -89,7 +87,6 @@ public PictureService(
             _mediaSettings = mediaSettings;
             _imageProcessor = imageProcessor;
             _imageCache = imageCache;
-			_storeContext = storeContext;
 			_httpContext = httpContext;
 			_cacheManager = cacheManager;
 
@@ -143,9 +140,6 @@ protected virtual string GetFallbackImageFileName(FallbackPictureType defaultPic
 				case FallbackPictureType.Entity:
 					defaultImageFileName = _settingService.GetSettingByKey("Media.DefaultImageName", "default-image.png");
 					break;
-				case FallbackPictureType.Avatar:
-					defaultImageFileName = _settingService.GetSettingByKey("Media.Customer.DefaultAvatarImageName", "default-avatar.jpg");
-					break;
 				default:
 					defaultImageFileName = _settingService.GetSettingByKey("Media.DefaultImageName", "default-image.png");
 					break;
diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Settings/CustomerUserSettingsModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Settings/CustomerUserSettingsModel.cs
index d3537e1464..e2052ea7e6 100644
--- a/src/Presentation/SmartStore.Web/Administration/Models/Settings/CustomerUserSettingsModel.cs
+++ b/src/Presentation/SmartStore.Web/Administration/Models/Settings/CustomerUserSettingsModel.cs
@@ -7,7 +7,7 @@
 
 namespace SmartStore.Admin.Models.Settings
 {
-	public partial class CustomerUserSettingsModel : ModelBase, ILocalizedModel<CustomerUserSettingsLocalizedModel>
+    public partial class CustomerUserSettingsModel : ModelBase, ILocalizedModel<CustomerUserSettingsLocalizedModel>
 	{
         public CustomerUserSettingsModel()
         {
@@ -57,9 +57,6 @@ public partial class CustomerSettingsModel
 			[SmartResourceDisplayName("Admin.Configuration.Settings.CustomerUser.AllowCustomersToUploadAvatars")]
             public bool AllowCustomersToUploadAvatars { get; set; }
 
-            [SmartResourceDisplayName("Admin.Configuration.Settings.CustomerUser.DefaultAvatarEnabled")]
-            public bool DefaultAvatarEnabled { get; set; }
-
             [SmartResourceDisplayName("Admin.Configuration.Settings.CustomerUser.ShowCustomersLocation")]
             public bool ShowCustomersLocation { get; set; }
 
diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Setting/CustomerUser.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Setting/CustomerUser.cshtml
index 65a1bf4f4a..be6dea2058 100644
--- a/src/Presentation/SmartStore.Web/Administration/Views/Setting/CustomerUser.cshtml
+++ b/src/Presentation/SmartStore.Web/Administration/Views/Setting/CustomerUser.cshtml
@@ -146,19 +146,10 @@
             </td>
             <td class="adminData">
 				@Html.SettingEditorFor(model => model.CustomerSettings.AllowCustomersToUploadAvatars, 
-					Html.CheckBoxFor(model => model.CustomerSettings.AllowCustomersToUploadAvatars, new { data_toggler_for = "#pnlDefaultAvatarEnabled" }))
+					Html.CheckBoxFor(model => model.CustomerSettings.AllowCustomersToUploadAvatars))
                 @Html.ValidationMessageFor(model => model.CustomerSettings.AllowCustomersToUploadAvatars)
             </td>
         </tr>
-        <tr id="pnlDefaultAvatarEnabled">
-            <td class="adminTitle">
-                @Html.SmartLabelFor(model => model.CustomerSettings.DefaultAvatarEnabled)
-            </td>
-            <td class="adminData">
-                @Html.SettingEditorFor(model => model.CustomerSettings.DefaultAvatarEnabled)
-                @Html.ValidationMessageFor(model => model.CustomerSettings.DefaultAvatarEnabled)
-            </td>
-        </tr>
         <tr>
             <td class="adminTitle">
                 @Html.SmartLabelFor(model => model.CustomerSettings.ShowCustomersLocation)
diff --git a/src/Presentation/SmartStore.Web/Content/Images/default-avatar.jpg b/src/Presentation/SmartStore.Web/Content/Images/default-avatar.jpg
deleted file mode 100644
index 3f8947a5e937b10a5bea323221b6cc155a0fb64c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 901
zcmex=<NpH&0WUXCHwH#VMur3+WcYuZ!I^=Bjg6g+m4ls~os*M;i${c)hnt&6Qb?Fz
zL{>^(PF6}rMnOeST|r4lSw=>~TvNxu(8R<<Uft5x!pKI?*u)5A2qPyaCl5D|1TU|I
zk)n*E5y{~H0R}-127d;BW=16jCP7AKLB{__7~~lk7+Ha?1vwZB7@3$^SlQS)IJvli
z3bqO`FflSSGqEtUva+xMRo4RL8CV2ag%k}P*@OcV*_8@Kj2b5{<WP3ncu+Lx;s+Ju
zq@pHHE-`TlNhwt|bq!4|6H_yD3rj0!7gslT4^OY)kkGL3h{&kql+?8JjLfX!lG3vB
zipr|yme#iRj?S)0lc!9bHhsp-S&J4gS-Ncbij}K2ZQinV+x8thcO5!><mj>ECr+Na
zbot8FYu9hwy!G(W<0ns_J%91?)yGetzkL1n{m0K=Ab&A3Fhjfr_ZgbM1cClyVqsxs
zVF&q(k*OSrnFU!`6%E;h90S=C3x$=88aYIqCNA7~kW<+>=!0ld(M2vX6_bamA3<IN
z`;0h`HId~rxW^Fwy2Zf5%m|D;W<dsfhMSAJG#FN-?(9=;K3&BX-C47uQ@-MZw((kq
znBV1pjsIr3?&<h?>RPP`<2nvyg(p%`=eEr_t`Jlg{41=NK_t)>j05&2rE%ZjS{tTs
z`20gP&($ghjYVAy+F{DOMC=xATJ3bn>0?6w?xPG5Aj^Q5sr6Ov6!Y(`VQaZ}Y(KiA
zG%nk&flFgi1J|Xkz8m-~ZLSqD#5%s5mmQNVQ?h`mO9O&e+>L&#<|40O_%eLOD?<l~
zFTu|oWzH;KU~-B<>+aSQflqfn-neQ?0NYW~nX*SFe#x`tjct0ECUH!nYysyApnEhY
rZ96fuJwWqo)F-EnZ{?3Vh<NIFs;gXrdO~E?(P)JSU0xc@|8D{Sv;swo

diff --git a/src/Presentation/SmartStore.Web/Extensions/MappingExtensions.cs b/src/Presentation/SmartStore.Web/Extensions/MappingExtensions.cs
index 328539186e..a08cce463b 100644
--- a/src/Presentation/SmartStore.Web/Extensions/MappingExtensions.cs
+++ b/src/Presentation/SmartStore.Web/Extensions/MappingExtensions.cs
@@ -97,11 +97,6 @@ public static CustomerAvatarModel ToAvatarModel(
             {
                 model.AvatarLetter = 'G';
                 model.AvatarColor = "light";
-
-                if (customerSettings.DefaultAvatarEnabled)
-                {
-                    model.PictureUrl = pictureService.GetFallbackUrl(mediaSettings.AvatarPictureSize, FallbackPictureType.Avatar);
-                }
             }
             else
             {
@@ -143,14 +138,7 @@ public static CustomerAvatarModel ToAvatarModel(
 
                 if (model.PictureUrl.IsEmpty())
                 {
-                    if (customerSettings.DefaultAvatarEnabled)
-                    {
-                        model.PictureUrl = pictureService.GetFallbackUrl(mediaSettings.AvatarPictureSize, FallbackPictureType.Avatar);
-                    }
-                    else
-                    {
-                        model.AvatarColor = customer.GetAvatarColor(genericAttributeService);
-                    }
+                    model.AvatarColor = customer.GetAvatarColor(genericAttributeService);
                 }
             }
 
diff --git a/src/Presentation/SmartStore.Web/SmartStore.Web.csproj b/src/Presentation/SmartStore.Web/SmartStore.Web.csproj
index b1ab3ddc0d..5f87fa935b 100644
--- a/src/Presentation/SmartStore.Web/SmartStore.Web.csproj
+++ b/src/Presentation/SmartStore.Web/SmartStore.Web.csproj
@@ -851,7 +851,6 @@
     <Content Include="Content\editors\summernote\summernote-bs4.min.js" />
     <Content Include="Content\fontastic\fontastic.css" />
     <Content Include="Content\fontastic\fonts\fontastic.svg" />
-    <Content Include="Content\Images\default-avatar.jpg" />
     <Content Include="Content\placeholder.txt" />
     <Content Include="Content\print-rtl.css" />
     <Content Include="Content\vendors\drift\Drift.js" />

From 4445e932f3f3265b9858c911db9f53efa9e0fad1 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Thu, 27 Sep 2018 12:28:35 +0200
Subject: [PATCH 18/71] Integrate published property of forum topics and posts
 in forum search

---
 .../Search/Forum/ForumSearchQuery.cs          | 41 ++++++++++++-------
 .../Search/Forum/LinqForumSearchService.cs    | 32 ++++++++++++++-
 .../Modelling/ForumSearchQueryFactory.cs      |  2 +-
 .../Views/Boards/Partials/SearchHits.cshtml   |  2 +-
 4 files changed, 58 insertions(+), 19 deletions(-)

diff --git a/src/Libraries/SmartStore.Services/Search/Forum/ForumSearchQuery.cs b/src/Libraries/SmartStore.Services/Search/Forum/ForumSearchQuery.cs
index 1e964bad84..9fd25c0d3a 100644
--- a/src/Libraries/SmartStore.Services/Search/Forum/ForumSearchQuery.cs
+++ b/src/Libraries/SmartStore.Services/Search/Forum/ForumSearchQuery.cs
@@ -3,6 +3,7 @@
 using SmartStore.Core.Domain.Customers;
 using SmartStore.Core.Domain.Forums;
 using SmartStore.Core.Search;
+using SmartStore.Services.Customers;
 
 namespace SmartStore.Services.Search
 {
@@ -66,33 +67,43 @@ public ForumSearchQuery SortBy(ForumTopicSorting sort)
             }
         }
 
-        public ForumSearchQuery VisibleOnly(Customer customer)
+        public ForumSearchQuery VisibleOnly(Customer customer, bool includeCustomerRoles)
         {
             if (customer != null)
             {
-                var allowedCustomerRoleIds = customer.CustomerRoles.Where(x => x.Active).Select(x => x.Id).ToArray();
-
-                return VisibleOnly(allowedCustomerRoleIds);
-            }
+                if (!customer.IsForumModerator())
+                {
+                    // See also LinqForumSearchService.
+                    var publishedCombined = SearchFilter.Combined(
+                        SearchFilter.ByField("published", true).ExactMatch().NotAnalyzed(),
+                        SearchFilter.ByField("customerid", customer.Id).ExactMatch().NotAnalyzed());
 
-            return VisibleOnly(new int[0]);
-        }
+                    WithFilter(publishedCombined);
+                }
 
-        public ForumSearchQuery VisibleOnly(params int[] allowedCustomerRoleIds)
-        {
-            if (allowedCustomerRoleIds != null && allowedCustomerRoleIds.Length > 0)
-            {
-                var roleIds = allowedCustomerRoleIds.Where(x => x != 0).Distinct().ToList();
-                if (roleIds.Any())
+                if (includeCustomerRoles)
                 {
-                    roleIds.Insert(0, 0);
-                    WithFilter(SearchFilter.Combined(roleIds.Select(x => SearchFilter.ByField("roleid", x).ExactMatch().NotAnalyzed()).ToArray()));
+                    var allowedRoleIds = customer.CustomerRoles.Where(x => x.Active).Select(x => x.Id).ToArray();
+                    if (allowedRoleIds != null && allowedRoleIds.Length > 0)
+                    {
+                        var roleIds = allowedRoleIds.Where(x => x != 0).Distinct().ToList();
+                        if (roleIds.Any())
+                        {
+                            roleIds.Insert(0, 0);
+                            WithFilter(SearchFilter.Combined(roleIds.Select(x => SearchFilter.ByField("roleid", x).ExactMatch().NotAnalyzed()).ToArray()));
+                        }
+                    }
                 }
             }
 
             return this;
         }
 
+        public ForumSearchQuery PublishedOnly(bool value)
+        {
+            return WithFilter(SearchFilter.ByField("published", value).Mandatory().ExactMatch().NotAnalyzed());
+        }
+
         public override ForumSearchQuery HasStoreId(int id)
         {
             base.HasStoreId(id);
diff --git a/src/Libraries/SmartStore.Services/Search/Forum/LinqForumSearchService.cs b/src/Libraries/SmartStore.Services/Search/Forum/LinqForumSearchService.cs
index 917221d3b5..c39dec94b2 100644
--- a/src/Libraries/SmartStore.Services/Search/Forum/LinqForumSearchService.cs
+++ b/src/Libraries/SmartStore.Services/Search/Forum/LinqForumSearchService.cs
@@ -64,6 +64,7 @@ protected virtual IQueryable<ForumPost> GetPostQuery(ForumSearchQuery searchQuer
             var cnf = _customerSettings.CustomerNameFormat;
             var fields = searchQuery.Fields;
             var filters = new List<ISearchFilter>();
+            var customer = _services.WorkContext.CurrentCustomer;
             var query = baseQuery ?? _forumPostRepository.TableUntracked.Expand(x => x.ForumTopic);
 
             // Apply search term.
@@ -95,8 +96,31 @@ protected virtual IQueryable<ForumPost> GetPostQuery(ForumSearchQuery searchQuer
                 }
             }
 
-            // Filters.
-            FlattenFilters(searchQuery.Filters, filters);
+            // Flatten filters.
+            foreach (var filter in searchQuery.Filters)
+            {
+                var combinedFilter = filter as ICombinedSearchFilter;
+                if (combinedFilter != null)
+                {
+                    // Find VisibleOnly combined filter and process it separately.
+                    var cf = combinedFilter.Filters.OfType<IAttributeSearchFilter>().ToArray();
+                    if (cf.Length == 2 && cf[0].FieldName == "published" && true == (bool)cf[0].Term && cf[1].FieldName == "customerid")
+                    {
+                        if (!customer.IsForumModerator())
+                        {
+                            query = query.Where(x => x.ForumTopic.Published && (x.Published || x.CustomerId == customer.Id));
+                        }
+                    }
+                    else
+                    {
+                        FlattenFilters(combinedFilter.Filters, filters);
+                    }
+                }
+                else
+                {
+                    filters.Add(filter);
+                }
+            }
 
             if (!QuerySettings.IgnoreAcl)
             {
@@ -151,6 +175,10 @@ from a in fg_acl.DefaultIfEmpty()
                 {
                     query = query.Where(x => x.CustomerId == (int)filter.Term);
                 }
+                else if (filter.FieldName == "published")
+                {
+                    query = query.Where(x => x.Published == (bool)filter.Term);
+                }
                 else if (filter.FieldName == "createdon")
                 {
                     if (rangeFilter != null)
diff --git a/src/Libraries/SmartStore.Services/Search/Forum/Modelling/ForumSearchQueryFactory.cs b/src/Libraries/SmartStore.Services/Search/Forum/Modelling/ForumSearchQueryFactory.cs
index f5b2d7960a..05f89aa954 100644
--- a/src/Libraries/SmartStore.Services/Search/Forum/Modelling/ForumSearchQueryFactory.cs
+++ b/src/Libraries/SmartStore.Services/Search/Forum/Modelling/ForumSearchQueryFactory.cs
@@ -84,7 +84,7 @@ public ForumSearchQuery CreateFromQuery()
                 .BuildFacetMap(!isInstantSearch);
 
             // Visibility.
-            query.VisibleOnly(!QuerySettings.IgnoreAcl ? _services.WorkContext.CurrentCustomer : null);
+            query.VisibleOnly(_services.WorkContext.CurrentCustomer, !QuerySettings.IgnoreAcl);
 
             // Store.
             if (!QuerySettings.IgnoreMultiStore)
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/Partials/SearchHits.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/Partials/SearchHits.cshtml
index 4cc9c4135a..bc6375ca8b 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/Partials/SearchHits.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/Partials/SearchHits.cshtml
@@ -10,7 +10,7 @@
     data-cumulativehits="@Model.CumulativeHitCount.ToString("N0")">
     @foreach (ForumTopicRowModel topic in Model.PagedList)
     {
-        <tr class="topic" data-id="@topic.Id">
+        <tr data-id="@topic.Id" class="topic@(topic.Published ? "" : " disabled")">
             <td class="image">
                 @{ Html.RenderPartial("Customer.Avatar", topic.Avatar); }
             </td>

From 75cfe5c40edcfd8f5ab6e48f8a0af1098283e521 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Thu, 27 Sep 2018 17:07:37 +0200
Subject: [PATCH 19/71] Several performance improvements at forum service

---
 .../Forums/ForumService.cs                    | 398 +++++++++---------
 .../Forums/IForumService.cs                   |  76 ++--
 2 files changed, 239 insertions(+), 235 deletions(-)

diff --git a/src/Libraries/SmartStore.Services/Forums/ForumService.cs b/src/Libraries/SmartStore.Services/Forums/ForumService.cs
index 2e55625acf..cef6e4adb3 100644
--- a/src/Libraries/SmartStore.Services/Forums/ForumService.cs
+++ b/src/Libraries/SmartStore.Services/Forums/ForumService.cs
@@ -26,7 +26,7 @@ public partial class ForumService : IForumService
         private readonly IRepository<Customer> _customerRepository;
         private readonly IGenericAttributeService _genericAttributeService;
         private readonly ICustomerService _customerService;
-		private readonly ICommonServices _services;
+        private readonly ICommonServices _services;
 
         public ForumService(
             IRepository<ForumGroup> forumGroupRepository,
@@ -41,7 +41,7 @@ public ForumService(
             IRepository<Customer> customerRepository,
             IGenericAttributeService genericAttributeService,
             ICustomerService customerService,
-			ICommonServices services)
+            ICommonServices services)
         {
             _forumGroupRepository = forumGroupRepository;
             _forumRepository = forumRepository;
@@ -55,23 +55,22 @@ public ForumService(
             _customerRepository = customerRepository;
             _genericAttributeService = genericAttributeService;
             _customerService = customerService;
-			_services = services;
+            _services = services;
         }
 
-		public DbQuerySettings QuerySettings { get; set; }
+        public DbQuerySettings QuerySettings { get; set; }
 
-        private void UpdateForumStats(int forumId)
+        protected virtual void UpdateForumStats(Forum forum)
         {
-            var forum = GetForumById(forumId);
             if (forum == null)
             {
                 return;
             }
 
-            var queryLastValues = 
+            var queryLastValues =
                 from ft in _forumTopicRepository.TableUntracked
                 join fp in _forumPostRepository.TableUntracked on ft.Id equals fp.TopicId
-                where ft.ForumId == forumId && ft.Published && fp.Published
+                where ft.ForumId == forum.Id && ft.Published && fp.Published
                 orderby fp.CreatedOnUtc descending, ft.CreatedOnUtc descending
                 select new
                 {
@@ -86,27 +85,26 @@ join fp in _forumPostRepository.TableUntracked on ft.Id equals fp.TopicId
             forum.LastPostId = lastValues?.LastPostId ?? 0;
             forum.LastPostCustomerId = lastValues?.LastPostCustomerId ?? 0;
             forum.LastPostTime = lastValues?.LastPostTime;
-            forum.NumTopics = _forumTopicRepository.Table.Where(x => x.ForumId == forumId && x.Published).Count();
+            forum.NumTopics = _forumTopicRepository.Table.Where(x => x.ForumId == forum.Id && x.Published).Count();
             forum.NumPosts = (
                 from ft in _forumTopicRepository.Table
                 join fp in _forumPostRepository.Table on ft.Id equals fp.TopicId
-                where ft.ForumId == forumId && ft.Published && fp.Published
+                where ft.ForumId == forum.Id && ft.Published && fp.Published
                 select fp.Id).Count();
 
             UpdateForum(forum);
         }
 
-        private void UpdateForumTopicStats(int forumTopicId)
+        protected virtual void UpdateForumTopicStats(ForumTopic topic)
         {
-            var forumTopic = GetTopicById(forumTopicId);
-            if (forumTopic == null)
+            if (topic == null)
             {
                 return;
             }
 
-            var queryLastValues = 
+            var queryLastValues =
                 from fp in _forumPostRepository.TableUntracked
-                where fp.TopicId == forumTopicId && fp.Published
+                where fp.TopicId == topic.Id && fp.Published
                 orderby fp.CreatedOnUtc descending
                 select new
                 {
@@ -116,38 +114,36 @@ orderby fp.CreatedOnUtc descending
                 };
             var lastValues = queryLastValues.FirstOrDefault();
 
-            forumTopic.LastPostId = lastValues?.LastPostId ?? 0;
-            forumTopic.LastPostCustomerId = lastValues?.LastPostCustomerId ?? 0;
-            forumTopic.LastPostTime = lastValues?.LastPostTime;
-            forumTopic.NumPosts = _forumPostRepository.Table.Where(x => x.TopicId == forumTopicId && x.Published).Count();
+            topic.LastPostId = lastValues?.LastPostId ?? 0;
+            topic.LastPostCustomerId = lastValues?.LastPostCustomerId ?? 0;
+            topic.LastPostTime = lastValues?.LastPostTime;
+            topic.NumPosts = _forumPostRepository.Table.Where(x => x.TopicId == topic.Id && x.Published).Count();
 
-            UpdateTopic(forumTopic);
+            UpdateTopic(topic);
         }
 
-        private void UpdateCustomerStats(int customerId)
+        protected virtual void UpdateCustomerStats(Customer customer)
         {
-            if (customerId != 0)
+            if (customer != null)
             {
-                var customer = _customerService.GetCustomerById(customerId);
-                if (customer != null)
-                {
-                    var numPosts = _forumPostRepository.Table.Where(x => x.CustomerId == customerId && x.Published).Count();
+                var numPosts = _forumPostRepository.Table
+                    .Where(x => x.CustomerId == customer.Id && x.Published)
+                    .Count();
 
-                    _genericAttributeService.SaveAttribute(customer, SystemCustomerAttributeNames.ForumPostCount, numPosts);
-                }
+                _genericAttributeService.SaveAttribute(customer, SystemCustomerAttributeNames.ForumPostCount, numPosts);
             }
         }
 
         #region Group
 
-        public virtual ForumGroup GetForumGroupById(int forumGroupId)
+        public virtual ForumGroup GetForumGroupById(int groupId)
         {
-            if (forumGroupId == 0)
+            if (groupId == 0)
             {
                 return null;
             }
 
-            return _forumGroupRepository.GetById(forumGroupId);
+            return _forumGroupRepository.GetById(groupId);
         }
 
         public virtual IList<ForumGroup> GetAllForumGroups(int storeId = 0, bool showHidden = false)
@@ -171,7 +167,7 @@ from sm in fg_sm.DefaultIfEmpty()
             {
                 var allowedCustomerRolesIds = _services.WorkContext.CurrentCustomer.CustomerRoles.Where(x => x.Active).Select(x => x.Id).ToList();
 
-                query = 
+                query =
                     from fg in query
                     join a in _aclRepository.Table on new { a1 = fg.Id, a2 = "ForumGroup" } equals new { a1 = a.EntityId, a2 = a.EntityName } into fg_acl
                     from a in fg_acl.DefaultIfEmpty()
@@ -195,26 +191,26 @@ orderby fgGroup.Key
             return query.ToListCached();
         }
 
-        public virtual void InsertForumGroup(ForumGroup forumGroup)
+        public virtual void InsertForumGroup(ForumGroup group)
         {
-            Guard.NotNull(forumGroup, nameof(forumGroup));
+            Guard.NotNull(group, nameof(group));
 
-            _forumGroupRepository.Insert(forumGroup);
+            _forumGroupRepository.Insert(group);
         }
 
-        public virtual void UpdateForumGroup(ForumGroup forumGroup)
+        public virtual void UpdateForumGroup(ForumGroup group)
         {
-            Guard.NotNull(forumGroup, nameof(forumGroup));
+            Guard.NotNull(group, nameof(group));
 
-            _forumGroupRepository.Update(forumGroup);
+            _forumGroupRepository.Update(group);
         }
 
-        public virtual void DeleteForumGroup(ForumGroup forumGroup)
+        public virtual void DeleteForumGroup(ForumGroup group)
         {
-            if (forumGroup != null)
+            if (group != null)
             {
-                _forumGroupRepository.Delete(forumGroup);
-            }            
+                _forumGroupRepository.Delete(group);
+            }
         }
 
         #endregion
@@ -285,9 +281,9 @@ where queryTopicIds.Contains(fs.TopicId)
 
         #region Topic
 
-        public virtual ForumTopic GetTopicById(int forumTopicId)
+        public virtual ForumTopic GetTopicById(int topicId)
         {
-            if (forumTopicId == 0)
+            if (topicId == 0)
             {
                 return null;
             }
@@ -295,7 +291,7 @@ public virtual ForumTopic GetTopicById(int forumTopicId)
             var entity = _forumTopicRepository.Table
                 .Expand(x => x.Forum)
                 .Expand(x => x.Forum.ForumGroup)
-                .FirstOrDefault(x => x.Id == forumTopicId);
+                .FirstOrDefault(x => x.Id == topicId);
 
             return entity;
         }
@@ -343,30 +339,30 @@ public virtual IList<ForumTopic> GetActiveTopics(int forumId, int count, bool sh
             var customer = _services.WorkContext.CurrentCustomer;
 
             var query =
-				from ft in _forumTopicRepository.Table
-				where (forumId == 0 || ft.ForumId == forumId) && ft.LastPostTime.HasValue
-				select ft;
+                from ft in _forumTopicRepository.Table
+                where (forumId == 0 || ft.ForumId == forumId) && ft.LastPostTime.HasValue
+                select ft;
 
             if (!showHidden && !customer.IsForumModerator())
             {
                 query = query.Where(x => x.Published || x.CustomerId == customer.Id);
             }
 
-			if (!QuerySettings.IgnoreMultiStore)
-			{
-				var currentStoreId = _services.StoreContext.CurrentStore.Id;
+            if (!QuerySettings.IgnoreMultiStore)
+            {
+                var currentStoreId = _services.StoreContext.CurrentStore.Id;
 
-				query =
-					from ft in query
-					join ff in _forumRepository.Table on ft.ForumId equals ff.Id
-					join fg in _forumGroupRepository.Table on ff.ForumGroupId equals fg.Id
-					join sm in _storeMappingRepository.Table on new { c1 = fg.Id, c2 = "ForumGroup" } equals new { c1 = sm.EntityId, c2 = sm.EntityName } into fg_sm
-					from sm in fg_sm.DefaultIfEmpty()
-					where !fg.LimitedToStores || currentStoreId == sm.StoreId
-					select ft;
+                query =
+                    from ft in query
+                    join ff in _forumRepository.Table on ft.ForumId equals ff.Id
+                    join fg in _forumGroupRepository.Table on ff.ForumGroupId equals fg.Id
+                    join sm in _storeMappingRepository.Table on new { c1 = fg.Id, c2 = "ForumGroup" } equals new { c1 = sm.EntityId, c2 = sm.EntityName } into fg_sm
+                    from sm in fg_sm.DefaultIfEmpty()
+                    where !fg.LimitedToStores || currentStoreId == sm.StoreId
+                    select ft;
 
                 joinApplied = true;
-			}
+            }
 
             if (!showHidden && !QuerySettings.IgnoreAcl)
             {
@@ -399,119 +395,155 @@ orderby ftGroup.Key
             return forumTopics;
         }
 
-        public virtual void InsertTopic(ForumTopic forumTopic, bool sendNotifications)
+        public virtual void InsertTopic(ForumTopic topic, bool sendNotifications)
         {
-            Guard.NotNull(forumTopic, nameof(forumTopic));
+            Guard.NotNull(topic, nameof(topic));
+
+            _forumTopicRepository.Insert(topic);
 
-            _forumTopicRepository.Insert(forumTopic);
+            var forum = topic.Forum ?? GetForumById(topic.ForumId);
 
-            UpdateForumStats(forumTopic.ForumId);
+            UpdateForumStats(forum);
 
             if (sendNotifications)
             {
-                var forum = forumTopic.Forum;
                 var subscriptions = GetAllSubscriptions(0, forum.Id, 0, 0, int.MaxValue);
                 var languageId = _services.WorkContext.WorkingLanguage.Id;
 
                 foreach (var subscription in subscriptions)
                 {
-                    if (subscription.CustomerId == forumTopic.CustomerId)
+                    if (subscription.CustomerId == topic.CustomerId)
                     {
                         continue;
                     }
 
                     if (subscription.Customer.Email.HasValue())
                     {
-                        _services.MessageFactory.SendNewForumTopicMessage(subscription.Customer, forumTopic, languageId);	
+                        _services.MessageFactory.SendNewForumTopicMessage(subscription.Customer, topic, languageId);
                     }
                 }
             }
         }
 
-        public virtual void UpdateTopic(ForumTopic forumTopic)
+        public virtual void UpdateTopic(ForumTopic topic)
         {
-            Guard.NotNull(forumTopic, nameof(forumTopic));
+            Guard.NotNull(topic, nameof(topic));
 
-            _forumTopicRepository.Update(forumTopic);
+            _forumTopicRepository.Update(topic);
         }
 
-        public virtual void DeleteTopic(ForumTopic forumTopic)
+        public virtual void DeleteTopic(ForumTopic topic)
         {
-            if (forumTopic == null)
+            if (topic == null)
             {
                 return;
             }
 
-            int customerId = forumTopic.CustomerId;
-            int forumId = forumTopic.ForumId;
+            var forum = topic.Forum ?? GetForumById(topic.ForumId);
+            var customer = topic.Customer ?? _customerService.GetCustomerById(topic.CustomerId);
 
-            _forumTopicRepository.Delete(forumTopic);
+            _forumTopicRepository.Delete(topic);
 
             // Delete forum subscriptions.
-            var queryFs = from ft in _forumSubscriptionRepository.Table
-                          where ft.TopicId == forumTopic.Id
-                          select ft;
-            var forumSubscriptions = queryFs.ToList();
-            foreach (var fs in forumSubscriptions)
+            var subscriptions = _forumSubscriptionRepository.Table.Where(x => x.TopicId == topic.Id).ToList();
+            foreach (var subscription in subscriptions)
             {
-                _forumSubscriptionRepository.Delete(fs);
+                _forumSubscriptionRepository.Delete(subscription);
             }
 
-            UpdateForumStats(forumId);
-            UpdateCustomerStats(customerId);
+            UpdateForumStats(forum);
+            UpdateCustomerStats(customer);
         }
 
-        public virtual ForumTopic MoveTopic(int forumTopicId, int newForumId)
+        public virtual ForumTopic MoveTopic(int topicId, int newForumId)
         {
-            var forumTopic = GetTopicById(forumTopicId);
-            if (forumTopic == null)
+            var topic = GetTopicById(topicId);
+            if (topic == null)
             {
-                return forumTopic;
+                return topic;
             }
 
-            if (IsCustomerAllowedToMoveTopic(_services.WorkContext.CurrentCustomer, forumTopic))
+            if (IsCustomerAllowedToMoveTopic(_services.WorkContext.CurrentCustomer, topic))
             {
-                var previousForumId = forumTopic.ForumId;
+                var previousForumId = topic.ForumId;
                 var newForum = GetForumById(newForumId);
                 if (newForum != null && previousForumId != newForumId)
                 {
-                    forumTopic.ForumId = newForum.Id;
-                    UpdateTopic(forumTopic);
+                    topic.ForumId = newForum.Id;
+                    UpdateTopic(topic);
 
-                    UpdateForumStats(previousForumId);
-                    UpdateForumStats(newForumId);
+                    var previousForum = topic.Forum ?? GetForumById(topic.ForumId);
+                    UpdateForumStats(previousForum);
+                    UpdateForumStats(newForum);
                 }
             }
 
-            return forumTopic;
+            return topic;
         }
 
-        public virtual int CalculateTopicPageIndex(int forumTopicId, int pageSize, int postId)
+        public virtual int CalculateTopicPageIndex(int topicId, int pageSize, int postId)
         {
-            var pageIndex = 0;
-            var forumPosts = GetAllPosts(forumTopicId, 0, true, 0, int.MaxValue);
+            if (pageSize <= 0 || postId == 0)
+            {
+                return 0;
+            }
+
+            var query = GetPostQuery(topicId, 0, true, true);
+            var postIds = query.Select(x => x.Id).ToList();
 
-            for (var i = 0; i < forumPosts.TotalCount; i++)
+            for (var i = 0; i < postIds.Count; ++i)
             {
-                if (forumPosts[i].Id == postId)
+                if (postIds[i] == postId)
                 {
-                    if (pageSize > 0)
-                    {
-                        pageIndex = i / pageSize;
-                    }
+                    return i / pageSize;
                 }
             }
 
-            return pageIndex;
+            return 0;
         }
 
         #endregion
 
         #region Post
 
-        public virtual ForumPost GetPostById(int forumPostId)
+        protected virtual IQueryable<ForumPost> GetPostQuery(
+            int topicId,
+            int customerId,
+            bool ascSort,
+            bool showHidden = false,
+            bool untracked = false)
         {
-            if (forumPostId == 0)
+            var customer = _services.WorkContext.CurrentCustomer;
+            var query = untracked ? _forumPostRepository.TableUntracked : _forumPostRepository.Table;
+
+            if (topicId > 0)
+            {
+                query = query.Where(x => topicId == x.TopicId);
+            }
+            if (customerId > 0)
+            {
+                query = query.Where(x => customerId == x.CustomerId);
+            }
+            if (!showHidden && !customer.IsForumModerator())
+            {
+                query = query.Where(x => x.Published || x.CustomerId == customer.Id);
+            }
+
+            if (ascSort)
+            {
+                query = query.OrderBy(x => x.CreatedOnUtc).ThenBy(x => x.Id);
+            }
+            else
+            {
+                query = query.OrderByDescending(x => x.CreatedOnUtc).ThenBy(x => x.Id);
+            }
+
+            return query;
+        }
+
+        public virtual ForumPost GetPostById(int postId)
+        {
+            if (postId == 0)
             {
                 return null;
             }
@@ -520,7 +552,7 @@ public virtual ForumPost GetPostById(int forumPostId)
                 .Expand(x => x.ForumTopic)
                 .Expand(x => x.ForumTopic.Forum)
                 .Expand(x => x.ForumTopic.Forum.ForumGroup)
-                .FirstOrDefault(x => x.Id == forumPostId);
+                .FirstOrDefault(x => x.Id == postId);
 
             return forumPost;
         }
@@ -539,135 +571,107 @@ public virtual IList<ForumPost> GetPostsByIds(int[] postIds)
         }
 
         public virtual IPagedList<ForumPost> GetAllPosts(
-            int forumTopicId,
+            int topicId,
             int customerId,
             bool ascSort,
             int pageIndex,
             int pageSize,
             bool showHidden = false)
         {
-            var customer = _services.WorkContext.CurrentCustomer;
-            var query = _forumPostRepository.Table;
-
-            if (forumTopicId > 0)
-            {
-                query = query.Where(fp => forumTopicId == fp.TopicId);
-            }
-            if (customerId > 0)
-            {
-                query = query.Where(fp => customerId == fp.CustomerId);
-            }
-            if (!showHidden && !customer.IsForumModerator())
-            {
-                query = query.Where(fp => fp.Published || fp.CustomerId == customer.Id);
-            }
-
-            if (ascSort)
-            {
-                query = query.OrderBy(fp => fp.CreatedOnUtc).ThenBy(fp => fp.Id);
-            }
-            else
-            {
-                query = query.OrderByDescending(fp => fp.CreatedOnUtc).ThenBy(fp => fp.Id);
-            }
-
+            var query = GetPostQuery(topicId, customerId, ascSort, showHidden);
             var forumPosts = new PagedList<ForumPost>(query, pageIndex, pageSize);
             return forumPosts;
         }
 
-        public virtual void InsertPost(ForumPost forumPost, bool sendNotifications)
+        public virtual void InsertPost(ForumPost post, bool sendNotifications)
         {
-            Guard.NotNull(forumPost, nameof(forumPost));
+            Guard.NotNull(post, nameof(post));
 
-            _forumPostRepository.Insert(forumPost);
+            _forumPostRepository.Insert(post);
 
-            var forumTopic = GetTopicById(forumPost.TopicId);
+            var topic = post.ForumTopic ?? GetTopicById(post.TopicId);
+            var forum = topic.Forum ?? GetForumById(topic.ForumId);
+            var customer = post.Customer ?? _customerService.GetCustomerById(post.CustomerId);
 
-            UpdateForumTopicStats(forumPost.TopicId);
-            UpdateForumStats(forumTopic.ForumId);
-            UpdateCustomerStats(forumPost.CustomerId);
+            UpdateForumTopicStats(topic);
+            UpdateForumStats(forum);
+            UpdateCustomerStats(customer);
 
             if (sendNotifications)
             {
-                var forum = forumTopic.Forum;
                 var languageId = _services.WorkContext.WorkingLanguage.Id;
-                var subscriptions = GetAllSubscriptions(0, 0, forumTopic.Id, 0, int.MaxValue);
+                var subscriptions = GetAllSubscriptions(0, 0, topic.Id, 0, int.MaxValue);
                 var friendlyTopicPageIndex = CalculateTopicPageIndex(
-                    forumPost.TopicId,
+                    post.TopicId,
                     _forumSettings.PostsPageSize > 0 ? _forumSettings.PostsPageSize : 20,
-                    forumPost.Id) + 1;
+                    post.Id) + 1;
 
                 foreach (var subscription in subscriptions)
                 {
-                    if (subscription.CustomerId == forumPost.CustomerId)
+                    if (subscription.CustomerId == post.CustomerId)
                     {
                         continue;
                     }
 
                     if (subscription.Customer.Email.HasValue())
                     {
-                        _services.MessageFactory.SendNewForumPostMessage(subscription.Customer, forumPost, friendlyTopicPageIndex, languageId);
+                        _services.MessageFactory.SendNewForumPostMessage(subscription.Customer, post, friendlyTopicPageIndex, languageId);
                     }
                 }
             }
         }
 
-        public virtual void UpdatePost(ForumPost forumPost)
+        public virtual void UpdatePost(ForumPost post)
         {
-            Guard.NotNull(forumPost, nameof(forumPost));
+            Guard.NotNull(post, nameof(post));
 
-            _forumPostRepository.Update(forumPost);
+            _forumPostRepository.Update(post);
         }
 
-        public virtual void DeletePost(ForumPost forumPost)
+        public virtual void DeletePost(ForumPost post)
         {
-            if (forumPost == null)
+            if (post == null)
             {
                 return;
             }
 
-            var forumTopicId = forumPost.TopicId;
-            var customerId = forumPost.CustomerId;
-            var forumTopic = GetTopicById(forumTopicId);
-            var forumId = forumTopic.ForumId;
+            var topic = post.ForumTopic ?? GetTopicById(post.TopicId);
+            var forum = topic.Forum ?? GetForumById(topic.ForumId);
+            var customer = post.Customer ?? _customerService.GetCustomerById(post.CustomerId);
 
             // Delete topic if it was the first post.
-            var deleteTopic = false;
-            var firstPost = forumTopic.GetFirstPost(this);
-            if (firstPost != null && firstPost.Id == forumPost.Id)
-            {
-                deleteTopic = true;
-            }
+            var firstPost = topic.GetFirstPost(this);
+            var deleteTopic = firstPost != null && firstPost.Id == post.Id;
 
             // Delete forum post.
-            _forumPostRepository.Delete(forumPost);
+            _forumPostRepository.Delete(post);
 
             // Delete topic.
             if (deleteTopic)
             {
-                DeleteTopic(forumTopic);
+                DeleteTopic(topic);
             }
-
-            if (!deleteTopic)
+            else
             {
-                UpdateForumTopicStats(forumTopicId);
+                UpdateForumTopicStats(topic);
             }
-            UpdateForumStats(forumId);
-            UpdateCustomerStats(customerId);
+
+            UpdateForumStats(forum);
+            UpdateCustomerStats(customer);
         }
 
         #endregion
 
         #region Private message
 
-        public virtual PrivateMessage GetPrivateMessageById(int privateMessageId)
+        public virtual PrivateMessage GetPrivateMessageById(int messageId)
         {
-            if (privateMessageId == 0)
+            if (messageId == 0)
             {
                 return null;
             }
 
-            var privateMessage = _forumPrivateMessageRepository.Table.FirstOrDefault(x => x.Id == privateMessageId);
+            var privateMessage = _forumPrivateMessageRepository.Table.FirstOrDefault(x => x.Id == messageId);
             return privateMessage;
         }
 
@@ -714,45 +718,45 @@ public virtual IPagedList<PrivateMessage> GetAllPrivateMessages(
             return privateMessages;
         }
 
-        public virtual void InsertPrivateMessage(PrivateMessage privateMessage)
+        public virtual void InsertPrivateMessage(PrivateMessage message)
         {
-            Guard.NotNull(privateMessage, nameof(privateMessage));
+            Guard.NotNull(message, nameof(message));
 
-            _forumPrivateMessageRepository.Insert(privateMessage);
+            _forumPrivateMessageRepository.Insert(message);
 
-            var customerTo = _customerService.GetCustomerById(privateMessage.ToCustomerId);
+            var customerTo = _customerService.GetCustomerById(message.ToCustomerId);
             if (customerTo == null)
             {
                 throw new SmartException("Recipient could not be loaded");
             }
 
-			_genericAttributeService.SaveAttribute(customerTo, SystemCustomerAttributeNames.NotifiedAboutNewPrivateMessages, false, privateMessage.StoreId);
+			_genericAttributeService.SaveAttribute(customerTo, SystemCustomerAttributeNames.NotifiedAboutNewPrivateMessages, false, message.StoreId);
 
             if (_forumSettings.NotifyAboutPrivateMessages)
             {
-				_services.MessageFactory.SendPrivateMessageNotification(customerTo, privateMessage, _services.WorkContext.WorkingLanguage.Id);                
+				_services.MessageFactory.SendPrivateMessageNotification(customerTo, message, _services.WorkContext.WorkingLanguage.Id);                
             }
         }
 
-        public virtual void UpdatePrivateMessage(PrivateMessage privateMessage)
+        public virtual void UpdatePrivateMessage(PrivateMessage message)
         {
-            Guard.NotNull(privateMessage, nameof(privateMessage));
+            Guard.NotNull(message, nameof(message));
 
-            if (privateMessage.IsDeletedByAuthor && privateMessage.IsDeletedByRecipient)
+            if (message.IsDeletedByAuthor && message.IsDeletedByRecipient)
             {
-                _forumPrivateMessageRepository.Delete(privateMessage);
+                _forumPrivateMessageRepository.Delete(message);
             }
             else
             {
-                _forumPrivateMessageRepository.Update(privateMessage);
+                _forumPrivateMessageRepository.Update(message);
             }
         }
 
-        public virtual void DeletePrivateMessage(PrivateMessage privateMessage)
+        public virtual void DeletePrivateMessage(PrivateMessage message)
         {
-            if (privateMessage != null)
+            if (message != null)
             {
-                _forumPrivateMessageRepository.Delete(privateMessage);
+                _forumPrivateMessageRepository.Delete(message);
             }            
         }
 
@@ -760,14 +764,14 @@ public virtual void DeletePrivateMessage(PrivateMessage privateMessage)
 
         #region Subscription
 
-        public virtual ForumSubscription GetSubscriptionById(int forumSubscriptionId)
+        public virtual ForumSubscription GetSubscriptionById(int subscriptionId)
         {
-            if (forumSubscriptionId == 0)
+            if (subscriptionId == 0)
             {
                 return null;
             }
 
-            var forumSubscription = _forumSubscriptionRepository.Table.FirstOrDefault(x => x.Id == forumSubscriptionId);
+            var forumSubscription = _forumSubscriptionRepository.Table.FirstOrDefault(x => x.Id == subscriptionId);
             return forumSubscription;
         }
 
@@ -793,25 +797,25 @@ where fsQuery.Contains(fs.SubscriptionGuid)
             return forumSubscriptions;
         }
 
-        public virtual void InsertSubscription(ForumSubscription forumSubscription)
+        public virtual void InsertSubscription(ForumSubscription subscription)
         {
-            Guard.NotNull(forumSubscription, nameof(forumSubscription));
+            Guard.NotNull(subscription, nameof(subscription));
 
-            _forumSubscriptionRepository.Insert(forumSubscription);
+            _forumSubscriptionRepository.Insert(subscription);
         }
 
-        public virtual void UpdateSubscription(ForumSubscription forumSubscription)
+        public virtual void UpdateSubscription(ForumSubscription subscription)
         {
-            Guard.NotNull(forumSubscription, nameof(forumSubscription));
+            Guard.NotNull(subscription, nameof(subscription));
 
-            _forumSubscriptionRepository.Update(forumSubscription);
+            _forumSubscriptionRepository.Update(subscription);
         }
 
-        public virtual void DeleteSubscription(ForumSubscription forumSubscription)
+        public virtual void DeleteSubscription(ForumSubscription subscription)
         {
-            if (forumSubscription != null)
+            if (subscription != null)
             {
-                _forumSubscriptionRepository.Delete(forumSubscription);
+                _forumSubscriptionRepository.Delete(subscription);
             }
         }
 
diff --git a/src/Libraries/SmartStore.Services/Forums/IForumService.cs b/src/Libraries/SmartStore.Services/Forums/IForumService.cs
index 361e1720fb..9f26ab3e6c 100644
--- a/src/Libraries/SmartStore.Services/Forums/IForumService.cs
+++ b/src/Libraries/SmartStore.Services/Forums/IForumService.cs
@@ -15,9 +15,9 @@ public partial interface IForumService
         /// <summary>
         /// Gets a forum group
         /// </summary>
-        /// <param name="forumGroupId">The forum group identifier</param>
+        /// <param name="groupId">The forum group identifier</param>
         /// <returns>Forum group</returns>
-        ForumGroup GetForumGroupById(int forumGroupId);
+        ForumGroup GetForumGroupById(int groupId);
 
         /// <summary>
         /// Gets all forum groups
@@ -30,20 +30,20 @@ public partial interface IForumService
         /// <summary>
         /// Deletes a forum group
         /// </summary>
-        /// <param name="forumGroup">Forum group</param>
-        void DeleteForumGroup(ForumGroup forumGroup);
+        /// <param name="group">Forum group</param>
+        void DeleteForumGroup(ForumGroup group);
 
         /// <summary>
         /// Inserts a forum group
         /// </summary>
-        /// <param name="forumGroup">Forum group</param>
-        void InsertForumGroup(ForumGroup forumGroup);
+        /// <param name="group">Forum group</param>
+        void InsertForumGroup(ForumGroup group);
 
         /// <summary>
         /// Updates the forum group
         /// </summary>
-        /// <param name="forumGroup">Forum group</param>
-        void UpdateForumGroup(ForumGroup forumGroup);
+        /// <param name="group">Forum group</param>
+        void UpdateForumGroup(ForumGroup group);
 
         #endregion
 
@@ -81,9 +81,9 @@ public partial interface IForumService
         /// <summary>
         /// Gets a forum topic
         /// </summary>
-        /// <param name="forumTopicId">The forum topic identifier</param>
+        /// <param name="topicId">The forum topic identifier</param>
         /// <returns>Forum Topic</returns>
-        ForumTopic GetTopicById(int forumTopicId);
+        ForumTopic GetTopicById(int topicId);
 
         /// <summary>
         /// Gets forum topics by identifiers
@@ -114,38 +114,38 @@ public partial interface IForumService
         /// <summary>
         /// Deletes a forum topic
         /// </summary>
-        /// <param name="forumTopic">Forum topic</param>
-        void DeleteTopic(ForumTopic forumTopic);
+        /// <param name="topic">Forum topic</param>
+        void DeleteTopic(ForumTopic topic);
 
         /// <summary>
         /// Inserts a forum topic
         /// </summary>
-        /// <param name="forumTopic">Forum topic</param>
+        /// <param name="topic">Forum topic</param>
         /// <param name="sendNotifications">A value indicating whether to send notifications to subscribed customers</param>
-        void InsertTopic(ForumTopic forumTopic, bool sendNotifications);
+        void InsertTopic(ForumTopic topic, bool sendNotifications);
 
         /// <summary>
         /// Updates the forum topic
         /// </summary>
-        /// <param name="forumTopic">Forum topic</param>
-        void UpdateTopic(ForumTopic forumTopic);
+        /// <param name="topic">Forum topic</param>
+        void UpdateTopic(ForumTopic topic);
 
         /// <summary>
         /// Moves the forum topic
         /// </summary>
-        /// <param name="forumTopicId">The forum topic identifier</param>
+        /// <param name="topicId">The forum topic identifier</param>
         /// <param name="newForumId">New forum identifier</param>
         /// <returns>Moved forum topic</returns>
-        ForumTopic MoveTopic(int forumTopicId, int newForumId);
+        ForumTopic MoveTopic(int topicId, int newForumId);
 
         /// <summary>
         /// Calculates topic page index by post identifier
         /// </summary>
-        /// <param name="forumTopicId">Topic identifier</param>
+        /// <param name="topicId">Topic identifier</param>
         /// <param name="pageSize">Page size</param>
         /// <param name="postId">Post identifier</param>
         /// <returns>Page index</returns>
-        int CalculateTopicPageIndex(int forumTopicId, int pageSize, int postId);
+        int CalculateTopicPageIndex(int topicId, int pageSize, int postId);
 
         #endregion
 
@@ -154,9 +154,9 @@ public partial interface IForumService
         /// <summary>
         /// Gets a forum post
         /// </summary>
-        /// <param name="forumPostId">The forum post identifier</param>
+        /// <param name="postId">The forum post identifier</param>
         /// <returns>Forum Post</returns>
-        ForumPost GetPostById(int forumPostId);
+        ForumPost GetPostById(int postId);
 
         /// <summary>
         /// Gets forum posts by identifiers.
@@ -168,33 +168,33 @@ public partial interface IForumService
         /// <summary>
         /// Gets all forum posts
         /// </summary>
-        /// <param name="forumTopicId">The forum topic identifier</param>
+        /// <param name="topicId">The forum topic identifier</param>
         /// <param name="customerId">The customer identifier</param>
         /// <param name="ascSort">Sort order</param>
         /// <param name="pageIndex">Page index</param>
         /// <param name="pageSize">Page size</param>
         /// <param name="showHidden">Whether to load hidden records</param>
         /// <returns>Forum Posts</returns>
-        IPagedList<ForumPost> GetAllPosts(int forumTopicId, int customerId, bool ascSort, int pageIndex, int pageSize, bool showHidden = false);
+        IPagedList<ForumPost> GetAllPosts(int topicId, int customerId, bool ascSort, int pageIndex, int pageSize, bool showHidden = false);
 
         /// <summary>
         /// Deletes a forum post
         /// </summary>
-        /// <param name="forumPost">Forum post</param>
-        void DeletePost(ForumPost forumPost);
+        /// <param name="post">Forum post</param>
+        void DeletePost(ForumPost post);
 
         /// <summary>
         /// Inserts a forum post
         /// </summary>
-        /// <param name="forumPost">The forum post</param>
+        /// <param name="post">The forum post</param>
         /// <param name="sendNotifications">A value indicating whether to send notifications to subscribed customers</param>
-        void InsertPost(ForumPost forumPost, bool sendNotifications);
+        void InsertPost(ForumPost post, bool sendNotifications);
 
         /// <summary>
         /// Updates the forum post
         /// </summary>
-        /// <param name="forumPost">Forum post</param>
-        void UpdatePost(ForumPost forumPost);
+        /// <param name="post">Forum post</param>
+        void UpdatePost(ForumPost post);
 
         #endregion
 
@@ -203,9 +203,9 @@ public partial interface IForumService
         /// <summary>
         /// Gets a private message
         /// </summary>
-        /// <param name="privateMessageId">The private message identifier</param>
+        /// <param name="messageId">The private message identifier</param>
         /// <returns>Private message</returns>
-        PrivateMessage GetPrivateMessageById(int privateMessageId);
+        PrivateMessage GetPrivateMessageById(int messageId);
 
         /// <summary>
         /// Gets private messages
@@ -232,20 +232,20 @@ IPagedList<PrivateMessage> GetAllPrivateMessages(
         /// <summary>
         /// Deletes a private message
         /// </summary>
-        /// <param name="privateMessage">Private message</param>
-        void DeletePrivateMessage(PrivateMessage privateMessage);
+        /// <param name="message">Private message</param>
+        void DeletePrivateMessage(PrivateMessage message);
 
         /// <summary>
         /// Inserts a private message
         /// </summary>
-        /// <param name="privateMessage">Private message</param>
-        void InsertPrivateMessage(PrivateMessage privateMessage);
+        /// <param name="message">Private message</param>
+        void InsertPrivateMessage(PrivateMessage message);
 
         /// <summary>
         /// Updates the private message
         /// </summary>
-        /// <param name="privateMessage">Private message</param>
-        void UpdatePrivateMessage(PrivateMessage privateMessage);
+        /// <param name="message">Private message</param>
+        void UpdatePrivateMessage(PrivateMessage message);
 
         #endregion
 

From 00a35732cd48e5024d927fe36719915c161b0863 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Thu, 27 Sep 2018 20:59:05 +0200
Subject: [PATCH 20/71] Published property and updating forum counter

---
 .../Domain/Forums/ForumTopic.cs               |   8 +-
 .../Forums/ForumService.cs                    | 121 +++++++++++-------
 .../Forums/IForumService.cs                   |   6 +-
 .../Controllers/BoardsController.cs           |  20 +--
 .../SmartStore.Web/Views/Boards/Forum.cshtml  |   1 -
 5 files changed, 95 insertions(+), 61 deletions(-)

diff --git a/src/Libraries/SmartStore.Core/Domain/Forums/ForumTopic.cs b/src/Libraries/SmartStore.Core/Domain/Forums/ForumTopic.cs
index c31e029a50..63d6134530 100644
--- a/src/Libraries/SmartStore.Core/Domain/Forums/ForumTopic.cs
+++ b/src/Libraries/SmartStore.Core/Domain/Forums/ForumTopic.cs
@@ -114,10 +114,12 @@ public int NumReplies
         {
             get
             {
-                int result = 0;
                 if (NumPosts > 0)
-                    result = NumPosts - 1;
-                return result;
+                {
+                    return NumPosts - 1;
+                }
+
+                return 0;
             }
         }
     }
diff --git a/src/Libraries/SmartStore.Services/Forums/ForumService.cs b/src/Libraries/SmartStore.Services/Forums/ForumService.cs
index cef6e4adb3..4c0b56e800 100644
--- a/src/Libraries/SmartStore.Services/Forums/ForumService.cs
+++ b/src/Libraries/SmartStore.Services/Forums/ForumService.cs
@@ -60,7 +60,7 @@ public ForumService(
 
         public DbQuerySettings QuerySettings { get; set; }
 
-        protected virtual void UpdateForumStats(Forum forum)
+        protected virtual void UpdateForumStatistics(Forum forum)
         {
             if (forum == null)
             {
@@ -85,7 +85,11 @@ join fp in _forumPostRepository.TableUntracked on ft.Id equals fp.TopicId
             forum.LastPostId = lastValues?.LastPostId ?? 0;
             forum.LastPostCustomerId = lastValues?.LastPostCustomerId ?? 0;
             forum.LastPostTime = lastValues?.LastPostTime;
-            forum.NumTopics = _forumTopicRepository.Table.Where(x => x.ForumId == forum.Id && x.Published).Count();
+
+            forum.NumTopics = _forumTopicRepository
+                .Table.Where(x => x.ForumId == forum.Id && x.Published)
+                .Count();
+
             forum.NumPosts = (
                 from ft in _forumTopicRepository.Table
                 join fp in _forumPostRepository.Table on ft.Id equals fp.TopicId
@@ -95,7 +99,7 @@ join fp in _forumPostRepository.Table on ft.Id equals fp.TopicId
             UpdateForum(forum);
         }
 
-        protected virtual void UpdateForumTopicStats(ForumTopic topic)
+        protected virtual void UpdateTopicStatistics(ForumTopic topic)
         {
             if (topic == null)
             {
@@ -117,17 +121,20 @@ orderby fp.CreatedOnUtc descending
             topic.LastPostId = lastValues?.LastPostId ?? 0;
             topic.LastPostCustomerId = lastValues?.LastPostCustomerId ?? 0;
             topic.LastPostTime = lastValues?.LastPostTime;
-            topic.NumPosts = _forumPostRepository.Table.Where(x => x.TopicId == topic.Id && x.Published).Count();
 
-            UpdateTopic(topic);
+            topic.NumPosts = topic.Published
+                ? _forumPostRepository.Table.Where(x => x.TopicId == topic.Id && x.Published).Count()
+                : 0;
+
+            UpdateTopic(topic, false);
         }
 
-        protected virtual void UpdateCustomerStats(Customer customer)
+        protected virtual void UpdateCustomerStatistics(Customer customer)
         {
             if (customer != null)
             {
                 var numPosts = _forumPostRepository.Table
-                    .Where(x => x.CustomerId == customer.Id && x.Published)
+                    .Where(x => x.CustomerId == customer.Id && x.ForumTopic.Published && x.Published)
                     .Count();
 
                 _genericAttributeService.SaveAttribute(customer, SystemCustomerAttributeNames.ForumPostCount, numPosts);
@@ -253,21 +260,27 @@ public virtual void DeleteForum(Forum forum)
             }
 
             // Delete forum subscriptions (topics).
-            var queryTopicIds = from ft in _forumTopicRepository.Table
-                                where ft.ForumId == forum.Id
-                                select ft.Id;
-            var queryFs1 = from fs in _forumSubscriptionRepository.Table
-                           where queryTopicIds.Contains(fs.TopicId)
-                           select fs;
+            var queryTopicIds = 
+                from ft in _forumTopicRepository.Table
+                where ft.ForumId == forum.Id
+                select ft.Id;
+
+            var queryFs1 = 
+                from fs in _forumSubscriptionRepository.Table
+                where queryTopicIds.Contains(fs.TopicId)
+                select fs;
+
             foreach (var fs in queryFs1.ToList())
             {
                 _forumSubscriptionRepository.Delete(fs);
             }
 
             // Delete forum subscriptions (forum).
-            var queryFs2 = from fs in _forumSubscriptionRepository.Table
-                           where fs.ForumId == forum.Id
-                           select fs;
+            var queryFs2 = 
+                from fs in _forumSubscriptionRepository.Table
+                where fs.ForumId == forum.Id
+                select fs;
+
             foreach (var fs2 in queryFs2.ToList())
             {
                 _forumSubscriptionRepository.Delete(fs2);
@@ -403,7 +416,7 @@ public virtual void InsertTopic(ForumTopic topic, bool sendNotifications)
 
             var forum = topic.Forum ?? GetForumById(topic.ForumId);
 
-            UpdateForumStats(forum);
+            UpdateForumStatistics(forum);
 
             if (sendNotifications)
             {
@@ -425,11 +438,21 @@ public virtual void InsertTopic(ForumTopic topic, bool sendNotifications)
             }
         }
 
-        public virtual void UpdateTopic(ForumTopic topic)
+        public virtual void UpdateTopic(ForumTopic topic, bool updateStatistics)
         {
             Guard.NotNull(topic, nameof(topic));
 
             _forumTopicRepository.Update(topic);
+
+            if (updateStatistics)
+            {
+                var forum = topic.Forum ?? GetForumById(topic.ForumId);
+                var customer = topic.Customer ?? _customerService.GetCustomerById(topic.CustomerId);
+
+                UpdateForumStatistics(forum);
+                UpdateTopicStatistics(topic);
+                UpdateCustomerStatistics(customer);
+            }
         }
 
         public virtual void DeleteTopic(ForumTopic topic)
@@ -451,30 +474,25 @@ public virtual void DeleteTopic(ForumTopic topic)
                 _forumSubscriptionRepository.Delete(subscription);
             }
 
-            UpdateForumStats(forum);
-            UpdateCustomerStats(customer);
+            UpdateForumStatistics(forum);
+            UpdateCustomerStatistics(customer);
         }
 
         public virtual ForumTopic MoveTopic(int topicId, int newForumId)
         {
             var topic = GetTopicById(topicId);
-            if (topic == null)
-            {
-                return topic;
-            }
-
-            if (IsCustomerAllowedToMoveTopic(_services.WorkContext.CurrentCustomer, topic))
+            if (topic != null && IsCustomerAllowedToMoveTopic(_services.WorkContext.CurrentCustomer, topic))
             {
                 var previousForumId = topic.ForumId;
                 var newForum = GetForumById(newForumId);
+
                 if (newForum != null && previousForumId != newForumId)
                 {
                     topic.ForumId = newForum.Id;
-                    UpdateTopic(topic);
+                    UpdateTopic(topic, false);
 
-                    var previousForum = topic.Forum ?? GetForumById(topic.ForumId);
-                    UpdateForumStats(previousForum);
-                    UpdateForumStats(newForum);
+                    UpdateForumStatistics(GetForumById(previousForumId));
+                    UpdateForumStatistics(newForum);
                 }
             }
 
@@ -483,19 +501,17 @@ public virtual ForumTopic MoveTopic(int topicId, int newForumId)
 
         public virtual int CalculateTopicPageIndex(int topicId, int pageSize, int postId)
         {
-            if (pageSize <= 0 || postId == 0)
+            if (pageSize > 0 && postId != 0)
             {
-                return 0;
-            }
-
-            var query = GetPostQuery(topicId, 0, true, true);
-            var postIds = query.Select(x => x.Id).ToList();
+                var query = GetPostQuery(topicId, 0, true, true);
+                var postIds = query.Select(x => x.Id).ToList();
 
-            for (var i = 0; i < postIds.Count; ++i)
-            {
-                if (postIds[i] == postId)
+                for (var i = 0; i < postIds.Count; ++i)
                 {
-                    return i / pageSize;
+                    if (postIds[i] == postId)
+                    {
+                        return i / pageSize;
+                    }
                 }
             }
 
@@ -593,9 +609,9 @@ public virtual void InsertPost(ForumPost post, bool sendNotifications)
             var forum = topic.Forum ?? GetForumById(topic.ForumId);
             var customer = post.Customer ?? _customerService.GetCustomerById(post.CustomerId);
 
-            UpdateForumTopicStats(topic);
-            UpdateForumStats(forum);
-            UpdateCustomerStats(customer);
+            UpdateTopicStatistics(topic);
+            UpdateForumStatistics(forum);
+            UpdateCustomerStatistics(customer);
 
             if (sendNotifications)
             {
@@ -621,11 +637,22 @@ public virtual void InsertPost(ForumPost post, bool sendNotifications)
             }
         }
 
-        public virtual void UpdatePost(ForumPost post)
+        public virtual void UpdatePost(ForumPost post, bool updateStatistics)
         {
             Guard.NotNull(post, nameof(post));
 
             _forumPostRepository.Update(post);
+
+            if (updateStatistics)
+            {
+                var topic = post.ForumTopic ?? GetTopicById(post.TopicId);
+                var forum = topic.Forum ?? GetForumById(topic.ForumId);
+                var customer = post.Customer ?? _customerService.GetCustomerById(post.CustomerId);
+
+                UpdateForumStatistics(forum);
+                UpdateTopicStatistics(topic);
+                UpdateCustomerStatistics(customer);
+            }
         }
 
         public virtual void DeletePost(ForumPost post)
@@ -653,11 +680,11 @@ public virtual void DeletePost(ForumPost post)
             }
             else
             {
-                UpdateForumTopicStats(topic);
+                UpdateTopicStatistics(topic);
             }
 
-            UpdateForumStats(forum);
-            UpdateCustomerStats(customer);
+            UpdateForumStatistics(forum);
+            UpdateCustomerStatistics(customer);
         }
 
         #endregion
diff --git a/src/Libraries/SmartStore.Services/Forums/IForumService.cs b/src/Libraries/SmartStore.Services/Forums/IForumService.cs
index 9f26ab3e6c..22706359df 100644
--- a/src/Libraries/SmartStore.Services/Forums/IForumService.cs
+++ b/src/Libraries/SmartStore.Services/Forums/IForumService.cs
@@ -128,7 +128,8 @@ public partial interface IForumService
         /// Updates the forum topic
         /// </summary>
         /// <param name="topic">Forum topic</param>
-        void UpdateTopic(ForumTopic topic);
+        /// <param name="updateStatistics">A value indicating whether to update counter.</param>
+        void UpdateTopic(ForumTopic topic, bool updateStatistics);
 
         /// <summary>
         /// Moves the forum topic
@@ -194,7 +195,8 @@ public partial interface IForumService
         /// Updates the forum post
         /// </summary>
         /// <param name="post">Forum post</param>
-        void UpdatePost(ForumPost post);
+        /// <param name="updateStatistics">A value indicating whether to update counter.</param>
+        void UpdatePost(ForumPost post, bool updateStatistics);
 
         #endregion
 
diff --git a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
index 96003cf4f5..14faac192d 100644
--- a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
+++ b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
@@ -686,7 +686,7 @@ public ActionResult Topic(int id, int page = 1)
                 if (!customer.Deleted && customer.Active && !customer.IsSystemAccount)
                 {
                     topic.Views += 1;
-                    _forumService.UpdateTopic(topic);
+                    _forumService.UpdateTopic(topic, false);
                 }
             }
             catch (Exception ex)
@@ -956,8 +956,8 @@ public ActionResult TopicCreate(EditForumTopicModel model, bool captchaValid)
 
                     if (customer.IsForumModerator())
                     {
-                        model.Published = model.Published;
-                        model.TopicTypeId = model.TopicTypeId;
+                        topic.Published = model.Published;
+                        topic.TopicTypeId = model.TopicTypeId;
                     }
 
                     topic.Subject = _forumSettings.TopicSubjectMaxLength > 0 && model.Subject.Length > _forumSettings.TopicSubjectMaxLength
@@ -980,12 +980,12 @@ public ActionResult TopicCreate(EditForumTopicModel model, bool captchaValid)
 
                     _forumService.InsertPost(post, false);
 
-                    topic.NumPosts = 1;
+                    topic.NumPosts = topic.Published ? 1 : 0;
                     topic.LastPostId = post.Id;
                     topic.LastPostCustomerId = post.CustomerId;
                     topic.LastPostTime = post.CreatedOnUtc;
 
-                    _forumService.UpdateTopic(topic);
+                    _forumService.UpdateTopic(topic, false);
 
                     // Subscription.
                     if (_forumService.IsCustomerAllowedToSubscribe(customer))
@@ -1112,8 +1112,10 @@ public ActionResult TopicEdit(EditForumTopicModel model, bool captchaValid)
             {
                 try
                 {
+                    var updateStatistics = false;
                     if (customer.IsForumModerator())
                     {
+                        updateStatistics = topic.Published != model.Published;
                         topic.Published = model.Published;
                         topic.TopicTypeId = model.TopicTypeId;
                     }
@@ -1122,7 +1124,7 @@ public ActionResult TopicEdit(EditForumTopicModel model, bool captchaValid)
                         ? model.Subject.Substring(0, _forumSettings.TopicSubjectMaxLength)
                         : model.Subject;
 
-                    _forumService.UpdateTopic(topic);
+                    _forumService.UpdateTopic(topic, updateStatistics);
 
                     var text = _forumSettings.PostMaxLength > 0 && model.Text.Length > _forumSettings.PostMaxLength
                         ? model.Text.Substring(0, _forumSettings.PostMaxLength)
@@ -1132,7 +1134,7 @@ public ActionResult TopicEdit(EditForumTopicModel model, bool captchaValid)
                     if (firstPost != null)
                     {
                         firstPost.Text = text;
-                        _forumService.UpdatePost(firstPost);
+                        _forumService.UpdatePost(firstPost, false);
                     }
                     else
                     {
@@ -1496,8 +1498,10 @@ public ActionResult PostEdit(EditForumPostModel model, bool captchaValid)
             {
                 try
                 {
+                    var updateStatistics = false;
                     if (customer.IsForumModerator())
                     {
+                        updateStatistics = post.Published != model.Published;
                         post.Published = model.Published;
                     }
 
@@ -1505,7 +1509,7 @@ public ActionResult PostEdit(EditForumPostModel model, bool captchaValid)
                         ? model.Text.Substring(0, _forumSettings.PostMaxLength)
                         : model.Text;
 
-                    _forumService.UpdatePost(post);
+                    _forumService.UpdatePost(post, updateStatistics);
 
                     // Subscription.
                     if (_forumService.IsCustomerAllowedToSubscribe(customer))
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/Forum.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/Forum.cshtml
index ac5022ded4..6ff88f5941 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/Forum.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/Forum.cshtml
@@ -144,7 +144,6 @@
                                     .Route("TopicSlug", new { id = topic.Id, slug = topic.SeName }))
                             }
                         </div>
-
                     </td>
                     <td class="replies d-none d-md-table-cell">
                         @topic.NumReplies.ToString("N0")

From 389a7cef1b3f8ae54ca720c942ee4f348a68e58d Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Fri, 28 Sep 2018 03:16:40 +0200
Subject: [PATCH 21/71] Fix for HtmlHelper.BeginZoneContent(): capture inner
 writers also (Html.BeginForm() etc.)

---
 .../Extensions/HtmlZoneExtensions.cs          | 20 ++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/src/Presentation/SmartStore.Web.Framework/Extensions/HtmlZoneExtensions.cs b/src/Presentation/SmartStore.Web.Framework/Extensions/HtmlZoneExtensions.cs
index b74766934a..472a99d9c8 100644
--- a/src/Presentation/SmartStore.Web.Framework/Extensions/HtmlZoneExtensions.cs
+++ b/src/Presentation/SmartStore.Web.Framework/Extensions/HtmlZoneExtensions.cs
@@ -23,16 +23,23 @@ private class DocumentZone : IDisposable
 			internal const string ItemsKey = "DocumentTail.Snippets";
 			private const string UniqueKeysKey = "DocumentTail.UniqueKeys";
 
+			private readonly ViewContext _viewContext;
+			private readonly TextWriter _originalViewContextWriter;
 			private readonly WebViewPage _page;
 			private readonly string _targetZone;
 			private readonly ZoneInjectMode _injectMode;
 
-			public DocumentZone(WebViewPage page, string targetZone, ZoneInjectMode injectMode, string key)
+			public DocumentZone(HtmlHelper html, string targetZone, ZoneInjectMode injectMode, string key)
 			{
 				Guard.NotEmpty(targetZone, nameof(targetZone));
 
-				_page = page;
-				_page.OutputStack.Push(new StringWriter());
+				_viewContext = html.ViewContext;
+				_originalViewContextWriter = _viewContext.Writer;
+				_page = (WebViewPage)html.ViewDataContainer;
+
+				var writer = new StringWriter();
+				_page.OutputStack.Push(writer);
+				_viewContext.Writer = writer;
 
 				_targetZone = targetZone;
 				_injectMode = injectMode;
@@ -78,7 +85,10 @@ public void Dispose()
 				if (storage == null)
 					return;
 
-				var content = ((StringWriter)_page.OutputStack.Pop()).ToString();
+				var writer = ((StringWriter)_page.OutputStack.Pop());
+				var content = writer.ToString();
+
+				_viewContext.Writer = _originalViewContextWriter;
 
 				if (_injectMode == ZoneInjectMode.Append)
 				{
@@ -109,7 +119,7 @@ public static IDisposable BeginZoneContent(this HtmlHelper helper,
 				return ActionDisposable.Empty;
 			}
 
-			return new DocumentZone((WebViewPage)helper.ViewDataContainer, targetZone, injectMode, key);
+			return new DocumentZone(helper, targetZone, injectMode, key);
 		}
 
 		public static void RenderZone(this HtmlHelper helper, string zone)

From 124dd9bd45035c7e14274684a03bcf919c7bca5b Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Fri, 28 Sep 2018 03:17:24 +0200
Subject: [PATCH 22/71] CSS option class to skip fixing the top section header
 (backend)

---
 .../Scripts/admin.globalinit.js               | 20 ++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/src/Presentation/SmartStore.Web/Administration/Scripts/admin.globalinit.js b/src/Presentation/SmartStore.Web/Administration/Scripts/admin.globalinit.js
index 07c3abeb5f..d66b1ead3f 100644
--- a/src/Presentation/SmartStore.Web/Administration/Scripts/admin.globalinit.js
+++ b/src/Presentation/SmartStore.Web/Administration/Scripts/admin.globalinit.js
@@ -127,15 +127,17 @@
         var sectionHeader = $('.section-header');
         var sectionHeaderHasButtons = undefined;
 
-        $(window).on("scroll resize", function (e) {
-            if (sectionHeaderHasButtons === undefined) {
-                sectionHeaderHasButtons = sectionHeader.find(".options").children().length > 0;
-            }
-            if (sectionHeaderHasButtons === true) {
-                var y = $(this).scrollTop();
-                sectionHeader.toggleClass("sticky", y >= navbarHeight);
-            }
-        }).trigger('resize');
+        if (!sectionHeader.hasClass('nofix')) {
+            $(window).on("scroll resize", function (e) {
+                if (sectionHeaderHasButtons === undefined) {
+                    sectionHeaderHasButtons = sectionHeader.find(".options").children().length > 0;
+                }
+                if (sectionHeaderHasButtons === true) {
+                    var y = $(this).scrollTop();
+                    sectionHeader.toggleClass("sticky", y >= navbarHeight);
+                }
+            }).trigger('resize');
+        }
 
         $(window).on('load', function () {
         	// swap classes onload and domready

From f1a399e7b1c48496e1378ae1a5f664c6c9da14da Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Fri, 28 Sep 2018 03:17:43 +0200
Subject: [PATCH 23/71] Small variant of numeric textbox

---
 .../Administration/Content/_telerik.scss      | 31 ++++++++++++++++++-
 .../Views/Shared/EditorTemplates/Byte.cshtml  | 17 +++++++++-
 .../Shared/EditorTemplates/DateTime.cshtml    |  2 +-
 .../Shared/EditorTemplates/Decimal.cshtml     | 17 +++++++++-
 .../Shared/EditorTemplates/Double.cshtml      | 17 +++++++++-
 .../Views/Shared/EditorTemplates/Int32.cshtml | 17 +++++++++-
 .../Views/Shared/EditorTemplates/Time.cshtml  | 15 +++++++++
 7 files changed, 110 insertions(+), 6 deletions(-)

diff --git a/src/Presentation/SmartStore.Web/Administration/Content/_telerik.scss b/src/Presentation/SmartStore.Web/Administration/Content/_telerik.scss
index f1e731882f..e9b91a0fc0 100644
--- a/src/Presentation/SmartStore.Web/Administration/Content/_telerik.scss
+++ b/src/Presentation/SmartStore.Web/Administration/Content/_telerik.scss
@@ -359,7 +359,7 @@ a.t-button.t-state-disabled:hover,
 	display: block;
 	position: relative;
 
-	.numerictextbox-postfix {
+	> .numerictextbox-postfix {
 		display: block;
 		position: absolute;
 		z-index: 2;
@@ -374,6 +374,35 @@ a.t-button.t-state-disabled:hover,
 	}
 }
 
+.numerictextbox-group-sm {
+    > .t-numerictextbox {
+        &:after {
+            width: calc(#{$input-height-sm} - 1px);
+        }
+
+	    .t-input {
+            padding: $input-btn-padding-y-sm $input-btn-padding-x-sm;
+		    padding-right: $input-height-inner-sm + 1rem !important;
+	    }
+
+        .t-formatted-value {
+		    padding: $input-btn-padding-y-sm $input-btn-padding-x-sm;
+		    font-size: $font-size-sm; // Match sm inputs
+		    line-height: $input-btn-line-height-sm;
+        }
+
+        .t-input ~ .t-icon {
+            width: calc(#{$input-height-sm});
+        }
+    }
+
+	> .numerictextbox-postfix {
+		padding: $input-btn-padding-y-sm $input-btn-padding-x-sm;
+		font-size: $font-size-sm; // Match sm inputs
+		line-height: $input-btn-line-height-sm;
+	}
+}
+
 
 
 /* Grid
diff --git a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Byte.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Byte.cshtml
index 8fe3cbfdb3..e1085d1bf2 100644
--- a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Byte.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Byte.cshtml
@@ -21,9 +21,24 @@
 			return ViewData["postfix"] as string;
 		}
 	}
+
+	private string CssClass
+	{
+		get
+		{
+			var cls = "numerictextbox-group flex-grow-1";
+
+			if (ViewData.ContainsKey("size"))
+			{
+				cls += " numerictextbox-group-" + ViewData["size"].Convert<string>();
+			}
+
+			return cls;
+		}
+	}
 }
 
-<div class="numerictextbox-group flex-grow-1">
+<div class="@CssClass">
 	@(Html.Telerik().NumericTextBox<byte>()
 			.Name(ViewData.TemplateInfo.GetFullHtmlFieldName(string.Empty))
 			.EmptyMessage(T("Common.EnterValue"))
diff --git a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/DateTime.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/DateTime.cshtml
index 61a236c6db..90b7d17811 100644
--- a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/DateTime.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/DateTime.cshtml
@@ -38,7 +38,7 @@
 
 			if (ViewData.ContainsKey("size"))
 			{
-				cls += " input-group input-group-" + ViewData["size"].Convert<string>();
+				cls += " input-group-" + ViewData["size"].Convert<string>();
 			}
 
 			return cls;
diff --git a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Decimal.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Decimal.cshtml
index d2b0131c2c..4c93f01990 100644
--- a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Decimal.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Decimal.cshtml
@@ -21,9 +21,24 @@
 			return ViewData["postfix"] as string;
 		}
 	}
+
+	private string CssClass
+	{
+		get
+		{
+			var cls = "numerictextbox-group flex-grow-1";
+
+			if (ViewData.ContainsKey("size"))
+			{
+				cls += " numerictextbox-group-" + ViewData["size"].Convert<string>();
+			}
+
+			return cls;
+		}
+	}
 }
 
-<div class="numerictextbox-group flex-grow-1">
+<div class="@CssClass">
 	@(Html.Telerik().NumericTextBox<decimal>()
 			.Name(ViewData.TemplateInfo.GetFullHtmlFieldName(string.Empty))
 			.EmptyMessage(T("Common.EnterValue"))
diff --git a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Double.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Double.cshtml
index deccb78df2..8946e81ae3 100644
--- a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Double.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Double.cshtml
@@ -21,9 +21,24 @@
 			return ViewData["postfix"] as string;
 		}
 	}
+
+	private string CssClass
+	{
+		get
+		{
+			var cls = "numerictextbox-group flex-grow-1";
+
+			if (ViewData.ContainsKey("size"))
+			{
+				cls += " numerictextbox-group-" + ViewData["size"].Convert<string>();
+			}
+
+			return cls;
+		}
+	}
 }
 
-<div class="numerictextbox-group flex-grow-1">
+<div class="@CssClass">
 	@(Html.Telerik().NumericTextBox<double>()
 			.Name(ViewData.TemplateInfo.GetFullHtmlFieldName(string.Empty))
 			.EmptyMessage(T("Common.EnterValue"))
diff --git a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Int32.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Int32.cshtml
index 2eb3cf60f0..e70f0e6446 100644
--- a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Int32.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Int32.cshtml
@@ -21,9 +21,24 @@
 			return ViewData["postfix"] as string;
 		}
 	}
+
+	private string CssClass
+	{
+		get
+		{
+			var cls = "numerictextbox-group flex-grow-1";
+
+			if (ViewData.ContainsKey("size"))
+			{
+				cls += " numerictextbox-group-" + ViewData["size"].Convert<string>();
+			}
+
+			return cls;
+		}
+	}
 }
 
-<div class="numerictextbox-group flex-grow-1">
+<div class="@CssClass">
 	@(Html.Telerik().IntegerTextBox()
 			.Name(ViewData.TemplateInfo.GetFullHtmlFieldName(string.Empty))
 			.EmptyMessage(T("Common.EnterValue"))
diff --git a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Time.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Time.cshtml
index 6e6a2a1492..6bb6dfac23 100644
--- a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Time.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Time.cshtml
@@ -11,6 +11,21 @@
 			return value;
 		}
 	}
+
+	private string CssClass
+	{
+		get
+		{
+			var cls = "input-group date datetimepicker-group";
+
+			if (ViewData.ContainsKey("size"))
+			{
+				cls += " input-group-" + ViewData["size"].Convert<string>();
+			}
+
+			return cls;
+		}
+	}
 }
 
 @{

From ee5d99d9372c5f094bd8edf250ca40182bdc9476 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Fri, 28 Sep 2018 10:30:33 +0200
Subject: [PATCH 24/71] Do not allow to unpublish first post of a forum topic.
 Unpublish topic instead. Fixes wrong NumReplies counter problem too.

---
 .../Forums/ForumExtensions.cs                 | 109 +++++++++---------
 .../Controllers/BoardsController.cs           |  12 +-
 .../Models/Boards/EditForumPostModel.cs       |   1 +
 .../Boards/Partials/_CreateUpdatePost.cshtml  |   2 +-
 4 files changed, 69 insertions(+), 55 deletions(-)

diff --git a/src/Libraries/SmartStore.Services/Forums/ForumExtensions.cs b/src/Libraries/SmartStore.Services/Forums/ForumExtensions.cs
index d6d4fe8b19..41aa0c15bc 100644
--- a/src/Libraries/SmartStore.Services/Forums/ForumExtensions.cs
+++ b/src/Libraries/SmartStore.Services/Forums/ForumExtensions.cs
@@ -1,5 +1,4 @@
-using System;
-using SmartStore.Core.Domain.Customers;
+using SmartStore.Core.Domain.Customers;
 using SmartStore.Core.Domain.Forums;
 using SmartStore.Core.Html;
 using SmartStore.Core.Infrastructure;
@@ -12,14 +11,17 @@ public static class ForumExtensions
         /// <summary>
         /// Formats the forum post text
         /// </summary>
-        /// <param name="forumPost">Forum post</param>
+        /// <param name="post">Forum post</param>
         /// <returns>Formatted text</returns>
-        public static string FormatPostText(this ForumPost forumPost)
+        public static string FormatPostText(this ForumPost post)
         {
-            string text = forumPost.Text;
+            Guard.NotNull(post, nameof(post));
 
-            if (String.IsNullOrEmpty(text))
+            var text = post.Text;
+            if (text.IsEmpty())
+            {
                 return string.Empty;
+            }
 
             switch (EngineContext.Current.Resolve<ForumSettings>().ForumEditor)
             {
@@ -43,27 +45,26 @@ public static string FormatPostText(this ForumPost forumPost)
         /// <summary>
         /// Strips the topic subject
         /// </summary>
-        /// <param name="forumTopic">Forum topic</param>
+        /// <param name="topic">Forum topic</param>
         /// <returns>Formatted subject</returns>
-        public static string StripTopicSubject(this ForumTopic forumTopic)
+        public static string StripTopicSubject(this ForumTopic topic)
         {
-            string subject = forumTopic.Subject;
-            if (String.IsNullOrEmpty(subject))
+            Guard.NotNull(topic, nameof(topic));
+
+            var subject = topic.Subject;
+            if (subject.IsEmpty())
             {
                 return subject;
             }
 
-            int strippedTopicMaxLength = EngineContext.Current.Resolve<ForumSettings>().StrippedTopicMaxLength;
-            if (strippedTopicMaxLength > 0)
+            var strippedTopicMaxLength = EngineContext.Current.Resolve<ForumSettings>().StrippedTopicMaxLength;
+            if (strippedTopicMaxLength > 0 && subject.Length > strippedTopicMaxLength)
             {
-                if (subject.Length > strippedTopicMaxLength)
+                var index = subject.IndexOf(" ", strippedTopicMaxLength);
+                if (index > 0)
                 {
-                    int index = subject.IndexOf(" ", strippedTopicMaxLength);
-                    if (index > 0)
-                    {
-                        subject = subject.Substring(0, index);
-                        subject += "...";
-                    }
+                    subject = subject.Substring(0, index);
+                    subject += "…";
                 }
             }
 
@@ -77,28 +78,30 @@ public static string StripTopicSubject(this ForumTopic forumTopic)
         /// <returns>Formatted text</returns>
         public static string FormatForumSignatureText(this string text)
         {
-            if (String.IsNullOrEmpty(text))
+            if (text.IsEmpty())
+            {
                 return string.Empty;
+            }
 
-            text = SmartStore.Core.Html.HtmlUtils.FormatText(text, false, true, false, false, false, false);
-            return text;
+            return HtmlUtils.FormatText(text, false, true, false, false, false, false);
         }
 
         /// <summary>
         /// Formats the private message text
         /// </summary>
-        /// <param name="pm">Private message</param>
+        /// <param name="message">Private message</param>
         /// <returns>Formatted text</returns>
-        public static string FormatPrivateMessageText(this PrivateMessage pm)
+        public static string FormatPrivateMessageText(this PrivateMessage message)
         {
-            string text = pm.Text;
+            Guard.NotNull(message, nameof(message));
 
-            if (String.IsNullOrEmpty(text))
+            var text = message.Text;
+            if (text.IsEmpty())
+            {
                 return string.Empty;
+            }
 
-            text = SmartStore.Core.Html.HtmlUtils.FormatText(text, false, true, false, true, false, false);
-
-            return text;
+            return HtmlUtils.FormatText(text, false, true, false, true, false, false);
         }
         
         /// <summary>
@@ -109,8 +112,8 @@ public static string FormatPrivateMessageText(this PrivateMessage pm)
         /// <returns>Forum topic</returns>
         public static ForumTopic GetLastTopic(this Forum forum, IForumService forumService)
         {
-            if (forum == null)
-                throw new ArgumentNullException("forum");
+            Guard.NotNull(forum, nameof(forum));
+            Guard.NotNull(forumService, nameof(forumService));
 
             return forumService.GetTopicById(forum.LastTopicId);
         }
@@ -123,8 +126,8 @@ public static ForumTopic GetLastTopic(this Forum forum, IForumService forumServi
         /// <returns>Forum topic</returns>
         public static ForumPost GetLastPost(this Forum forum, IForumService forumService)
         {
-            if (forum == null)
-                throw new ArgumentNullException("forum");
+            Guard.NotNull(forum, nameof(forum));
+            Guard.NotNull(forumService, nameof(forumService));
 
             return forumService.GetPostById(forum.LastPostId);
         }
@@ -137,8 +140,8 @@ public static ForumPost GetLastPost(this Forum forum, IForumService forumService
         /// <returns>Customer</returns>
         public static Customer GetLastPostCustomer(this Forum forum, ICustomerService customerService)
         {
-            if (forum == null)
-                throw new ArgumentNullException("forum");
+            Guard.NotNull(forum, nameof(forum));
+            Guard.NotNull(customerService, nameof(customerService));
 
             return customerService.GetCustomerById(forum.LastPostCustomerId);
         }
@@ -146,17 +149,19 @@ public static Customer GetLastPostCustomer(this Forum forum, ICustomerService cu
         /// <summary>
         /// Get first post
         /// </summary>
-        /// <param name="forumTopic">Forum topic</param>
+        /// <param name="topic">Forum topic</param>
         /// <param name="forumService">Forum service</param>
         /// <returns>Forum post</returns>
-        public static ForumPost GetFirstPost(this ForumTopic forumTopic, IForumService forumService)
+        public static ForumPost GetFirstPost(this ForumTopic topic, IForumService forumService)
         {
-            if (forumTopic == null)
-                throw new ArgumentNullException("forumTopic");
+            Guard.NotNull(topic, nameof(topic));
+            Guard.NotNull(forumService, nameof(forumService));
 
-            var forumPosts = forumService.GetAllPosts(forumTopic.Id, 0, true, 0, 1);
-            if (forumPosts.Count > 0)
-                return forumPosts[0];
+            var posts = forumService.GetAllPosts(topic.Id, 0, true, 0, 1);
+            if (posts.Count > 0)
+            {
+                return posts[0];
+            }
 
             return null;
         }
@@ -164,29 +169,29 @@ public static ForumPost GetFirstPost(this ForumTopic forumTopic, IForumService f
         /// <summary>
         /// Get last post
         /// </summary>
-        /// <param name="forumTopic">Forum topic</param>
+        /// <param name="topic">Forum topic</param>
         /// <param name="forumService">Forum service</param>
         /// <returns>Forum post</returns>
-        public static ForumPost GetLastPost(this ForumTopic forumTopic, IForumService forumService)
+        public static ForumPost GetLastPost(this ForumTopic topic, IForumService forumService)
         {
-            if (forumTopic == null)
-                throw new ArgumentNullException("forumTopic");
+            Guard.NotNull(topic, nameof(topic));
+            Guard.NotNull(forumService, nameof(forumService));
 
-            return forumService.GetPostById(forumTopic.LastPostId);
+            return forumService.GetPostById(topic.LastPostId);
         }
 
         /// <summary>
         /// Get forum last post customer
         /// </summary>
-        /// <param name="forumTopic">Forum topic</param>
+        /// <param name="topic">Forum topic</param>
         /// <param name="customerService">Customer service</param>
         /// <returns>Customer</returns>
-        public static Customer GetLastPostCustomer(this ForumTopic forumTopic, ICustomerService customerService)
+        public static Customer GetLastPostCustomer(this ForumTopic topic, ICustomerService customerService)
         {
-            if (forumTopic == null)
-                throw new ArgumentNullException("forumTopic");
+            Guard.NotNull(topic, nameof(topic));
+            Guard.NotNull(customerService, nameof(customerService));
 
-            return customerService.GetCustomerById(forumTopic.LastPostCustomerId);
+            return customerService.GetCustomerById(topic.LastPostCustomerId);
         }
     }
 }
diff --git a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
index 14faac192d..789b02dac1 100644
--- a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
+++ b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
@@ -1431,11 +1431,14 @@ public ActionResult PostEdit(int id)
                 return HttpNotFound();
             }
 
+            var firstPost = post.ForumTopic.GetFirstPost(_forumService);
+
             var model = new EditForumPostModel
             {
                 Id = post.Id,
                 IsEdit = true,
                 Published = post.Published,
+                IsFirstPost = firstPost?.Id == post.Id,
                 ForumTopicId = post.ForumTopic.Id,
                 DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnForumPage,
                 ForumEditor = _forumSettings.ForumEditor,
@@ -1501,8 +1504,13 @@ public ActionResult PostEdit(EditForumPostModel model, bool captchaValid)
                     var updateStatistics = false;
                     if (customer.IsForumModerator())
                     {
-                        updateStatistics = post.Published != model.Published;
-                        post.Published = model.Published;
+                        // Do not allow to unpublish first post. NumReplies would be wrong. Unpublish topic instead.
+                        var firstPost = post.ForumTopic.GetFirstPost(_forumService);
+                        if (firstPost?.Id != post.Id)
+                        {
+                            updateStatistics = post.Published != model.Published;
+                            post.Published = model.Published;
+                        }
                     }
 
                     post.Text = _forumSettings.PostMaxLength > 0 && model.Text.Length > _forumSettings.PostMaxLength
diff --git a/src/Presentation/SmartStore.Web/Models/Boards/EditForumPostModel.cs b/src/Presentation/SmartStore.Web/Models/Boards/EditForumPostModel.cs
index 4f8ac6cb96..18cc57c8a8 100644
--- a/src/Presentation/SmartStore.Web/Models/Boards/EditForumPostModel.cs
+++ b/src/Presentation/SmartStore.Web/Models/Boards/EditForumPostModel.cs
@@ -14,6 +14,7 @@ public partial class EditForumPostModel : EntityModelBase
         public bool IsEdit { get; set; }
         public bool Published { get; set; }
         public bool DisplayCaptcha { get; set; }
+        public bool IsFirstPost { get; set; }
 
         [AllowHtml]
         public string Text { get; set; }
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/Partials/_CreateUpdatePost.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/Partials/_CreateUpdatePost.cshtml
index e578941f00..27e14b7789 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/Partials/_CreateUpdatePost.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/Partials/_CreateUpdatePost.cshtml
@@ -44,7 +44,7 @@
             </div>
         </div>
 
-        @if (Model.IsModerator)
+        @if (Model.IsModerator && !Model.IsFirstPost)
         {
             <div class="row justify-content-end">
                 <div class="col-sm-9">

From 6adb4dbef60a4d50b4facb1113a905d6cb36a92d Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Fri, 28 Sep 2018 11:31:16 +0200
Subject: [PATCH 25/71] Resolves forum paging issue

---
 .../SmartStore.Web/SmartStore.Web.csproj      |  2 +-
 .../SmartStore.Web/Views/Boards/Forum.cshtml  |  2 ++
 .../Views/Boards/ForumGroup.cshtml            |  2 +-
 .../SmartStore.Web/Views/Boards/Index.cshtml  |  2 +-
 ...mGroupPartial.cshtml => ForumGroup.cshtml} |  0
 .../Views/Boards/Partials/SearchHits.cshtml   |  1 +
 .../Boards/Partials/_ActiveTopics.cshtml      |  1 +
 .../Views/Boards/Partials/_ForumPost.cshtml   | 19 +++++++++----------
 .../SmartStore.Web/Views/Boards/Topic.cshtml  |  7 ++++---
 9 files changed, 20 insertions(+), 16 deletions(-)
 rename src/Presentation/SmartStore.Web/Views/Boards/Partials/{_ForumGroupPartial.cshtml => ForumGroup.cshtml} (100%)

diff --git a/src/Presentation/SmartStore.Web/SmartStore.Web.csproj b/src/Presentation/SmartStore.Web/SmartStore.Web.csproj
index 5f87fa935b..2c5e2a69a4 100644
--- a/src/Presentation/SmartStore.Web/SmartStore.Web.csproj
+++ b/src/Presentation/SmartStore.Web/SmartStore.Web.csproj
@@ -1532,7 +1532,7 @@
     <Content Include="Views\Boards\Partials\_ActiveTopics.cshtml" />
     <Content Include="Views\Boards\Partials\_CreateUpdatePost.cshtml" />
     <Content Include="Views\Boards\Partials\_CreateUpdateTopic.cshtml" />
-    <Content Include="Views\Boards\Partials\_ForumGroupPartial.cshtml" />
+    <Content Include="Views\Boards\Partials\ForumGroup.cshtml" />
     <Content Include="Views\Boards\Partials\_ForumPost.cshtml" />
     <Content Include="Views\Catalog\Partials\CategoryMenu.cshtml" />
     <Content Include="Views\Catalog\CategoryTemplate.ProductsInGridOrLines.cshtml" />
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/Forum.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/Forum.cshtml
index 6ff88f5941..7027d0692c 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/Forum.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/Forum.cshtml
@@ -11,6 +11,7 @@
 
     var pager = Html.SmartStore().Pager(Model.TopicPageIndex, Model.TopicPageSize, Model.TopicTotalRecords)
         .Name("paginator")
+        .QueryParam("page")
         .ShowSummary(false)
         .Route("ForumSlug", new RouteValues { id = Model.Id, slug = Model.SeName })
         .Alignment(PagerAlignment.Right);
@@ -134,6 +135,7 @@
                             @if (topic.NumPosts > Model.PostsPageSize)
                             {
                                 @(Html.SmartStore().Pager(topic.TotalPostPages)
+                                    .QueryParam("page")
                                     .HtmlAttributes(new { @class = "topics-pager" })
                                     .WithRenderer<ForumTopicPagerRenderer>()
                                     .ShowPrevious(false)
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/ForumGroup.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/ForumGroup.cshtml
index c96972078f..77316961a7 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/ForumGroup.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/ForumGroup.cshtml
@@ -10,6 +10,6 @@
         @{ Html.RenderAction("SearchBox", "Boards"); }
     </div>
     <div class="forum-group">
-        @{ Html.RenderPartial("_ForumGroupPartial", Model); }
+        @{ Html.RenderPartial("ForumGroup", Model); }
     </div>
 </div>
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/Index.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/Index.cshtml
index d156ae5b45..465d4414f3 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/Index.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/Index.cshtml
@@ -19,7 +19,7 @@
 
     @foreach (var forumGroup in Model.ForumGroups)
     {
-        Html.RenderPartial("_ForumGroupPartial", forumGroup);
+        Html.RenderPartial("ForumGroup", forumGroup);
     }
     
     @{ Html.RenderAction("ActiveDiscussionsSmall"); }
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ForumGroupPartial.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/Partials/ForumGroup.cshtml
similarity index 100%
rename from src/Presentation/SmartStore.Web/Views/Boards/Partials/_ForumGroupPartial.cshtml
rename to src/Presentation/SmartStore.Web/Views/Boards/Partials/ForumGroup.cshtml
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/Partials/SearchHits.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/Partials/SearchHits.cshtml
index bc6375ca8b..c702fa4442 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/Partials/SearchHits.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/Partials/SearchHits.cshtml
@@ -29,6 +29,7 @@
                 @if (topic.NumPosts > Model.PostsPageSize)
                 {
                     @(Html.SmartStore().Pager(topic.TotalPostPages)
+                        .QueryParam("page")
                         .HtmlAttributes(new { @class = "topics-pager" })
                         .WithRenderer<ForumTopicPagerRenderer>()
                         .ShowPrevious(false)
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ActiveTopics.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ActiveTopics.cshtml
index f59ca9deb5..cf279dfce3 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ActiveTopics.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ActiveTopics.cshtml
@@ -91,6 +91,7 @@
                             @if (@topic.NumPosts > Model.PostsPageSize)
                             {
                                 @(Html.SmartStore().Pager(topic.TotalPostPages)
+                                    .QueryParam("page")
                                     .HtmlAttributes(new { @class = "topics-pager" })
                                     .WithRenderer<ForumTopicPagerRenderer>()
                                     .ShowPrevious(false)
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ForumPost.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ForumPost.cshtml
index e257858c2c..b271913bc1 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ForumPost.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ForumPost.cshtml
@@ -20,23 +20,22 @@
             @if (Model.IsCurrentCustomerAllowedToEditPost)
             {
                 <i class="fa fa-pencil-square-o"></i>
-                @Html.ActionLink(@T("Forum.EditPost").Text, "PostEdit", new { id = Model.Id }, new { @class = "edit-post-link-button" })
+                @Html.ActionLink(T("Forum.EditPost").Text, "PostEdit", new { id = Model.Id }, new { @class = "edit-post-link-button" })
             }
                 
             @if (Model.IsCurrentCustomerAllowedToDeletePost)
             {
                 <i class="fa fa-times"></i>
-                @Html.ActionLink(@T("Forum.DeletePost").Text, "PostDelete", new { id = Model.Id }, new { onClick = String.Format("return confirm({0});", T("Common.AreYouSure").JsText), @class = "delete-post-link-button" })
+                @Html.ActionLink(T("Forum.DeletePost").Text, "PostDelete", new { id = Model.Id }, new { onClick = "return confirm(" + T("Common.AreYouSure").JsText + ");", @class = "delete-post-link-button" })
             }
-
-            @if (@Model.CurrentTopicPage > 1)
-            {
-                @Html.RouteLink(String.Format("#{0}", Model.Id.ToString()), "TopicSlug", "http", string.Empty, Model.Id.ToString(), new { id = Model.ForumTopicId, slug = Model.ForumTopicSeName, page = Model.CurrentTopicPage }, new { @class = "post-link", title = T("Forum.PostLinkTitle") })
-            }
-            else
-            {
-                @Html.RouteLink(String.Format("#{0}", Model.Id.ToString()), "TopicSlug", "http", string.Empty, Model.Id.ToString(), new { id = Model.ForumTopicId, slug = Model.ForumTopicSeName }, new { @class = "post-link pr-0", title = T("Forum.PostLinkTitle") })
+            @{
+                var postLinkRoutValues = Model.CurrentTopicPage == 1
+                    ? (object)(new { id = Model.ForumTopicId, slug = Model.ForumTopicSeName })
+                    : (object)(new { id = Model.ForumTopicId, slug = Model.ForumTopicSeName, page = Model.CurrentTopicPage });
             }
+            <a class="post-link" title="@T("Forum.PostLinkTitle")" href="@(Url.RouteUrl("TopicSlug", postLinkRoutValues))#@(Model.Id)">
+                #@(Model.Id)
+            </a>
         </div>
     </div>
 
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/Topic.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/Topic.cshtml
index cd633b0952..ab9b4acda1 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/Topic.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/Topic.cshtml
@@ -27,21 +27,21 @@
         <div class="manage btn-group my-3">
             @if (Model.IsCustomerAllowedToEditTopic)
 			{
-				<a href='@Url.Action("TopicEdit", new { id = Model.Id })' class="btn btn-secondary" rel="nofollow">
+				<a href="@Url.Action("TopicEdit", new { id = Model.Id })" class="btn btn-secondary" rel="nofollow">
 					<i class="fa fa-pencil-square-o"></i>
                     <span>@T("Forum.EditTopic")</span>
 				</a>
 			}
             @if (Model.IsCustomerAllowedToDeleteTopic)
 			{
-				<a href='@Url.Action("TopicDelete", new { id = Model.Id })' class="btn btn-secondary" rel="nofollow" onclick='@(String.Format("return confirm({0});", T("Common.AreYouSure").JsText))'>
+				<a href="@Url.Action("TopicDelete", new { id = Model.Id })" class="btn btn-secondary" rel="nofollow" onclick='return confirm(@T("Common.AreYouSure").JsText);'>
 					<i class="fa fa-trash-o"></i>
 					<span>@T("Forum.DeleteTopic")</span>
 				</a>
 			}
             @if (Model.IsCustomerAllowedToMoveTopic)
 			{
-				<a href='@Url.Action("TopicMove", new { id = Model.Id })' class="btn btn-secondary" rel="nofollow">
+				<a href="@Url.Action("TopicMove", new { id = Model.Id })" class="btn btn-secondary" rel="nofollow">
 					<i class="fa fa-arrows"></i>
 					<span>@T("Forum.MoveTopic")</span>
 				</a>
@@ -65,6 +65,7 @@
 {
     var pager = Html.SmartStore().Pager(Model.PostsPageIndex, Model.PostsPageSize, Model.PostsTotalRecords)
         .Name("paginator")
+        .QueryParam("page")
         .Size(PagerSize.Small)
         .Alignment(PagerAlignment.Centered)
         .Route("TopicSlug", new RouteValues { id = Model.Id, slug = Model.SeName });

From 260d02ec65219eb2d315af75e2fdceeece110fb3 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Fri, 28 Sep 2018 13:56:12 +0200
Subject: [PATCH 26/71] Improved forum selection box when moving a topic

---
 changelog.md                                  |  2 +
 .../Controllers/BoardsController.cs           | 94 +++++++++----------
 .../Models/Boards/TopicMoveModel.cs           |  9 +-
 .../Views/Boards/TopicMove.cshtml             |  9 +-
 4 files changed, 51 insertions(+), 63 deletions(-)

diff --git a/changelog.md b/changelog.md
index 7da2864c7c..759bbdbfc1 100644
--- a/changelog.md
+++ b/changelog.md
@@ -18,6 +18,8 @@
 * **Forum**:
 	* Added option to display a captcha on forum pages when creating or replying to a topic.
 	* #417 Restrict forum groups to specific customer roles.
+	* Added published property to forum topic and post.
+	* Several performance improvements.
 * **MegaSearch**:
 	* Supports searching for forum posts.
 	* #1172 Option to display related search terms on search page.
diff --git a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
index 789b02dac1..51bb2e5537 100644
--- a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
+++ b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
@@ -150,17 +150,17 @@ private ForumRowModel PrepareForumRowModel(Forum forum, Dictionary<int, ForumPos
             return forumModel;
         }
 
-        private ForumGroupModel PrepareForumGroupModel(ForumGroup forumGroup)
+        private ForumGroupModel PrepareForumGroupModel(ForumGroup group)
         {
             var forumGroupModel = new ForumGroupModel
             {
-                Id = forumGroup.Id,
-                Name = forumGroup.GetLocalized(x => x.Name),
-                Description = forumGroup.GetLocalized(x => x.Description),
-				SeName = forumGroup.GetSeName()
+                Id = group.Id,
+                Name = group.GetLocalized(x => x.Name),
+                Description = group.GetLocalized(x => x.Description),
+				SeName = group.GetSeName()
             };
 
-            var lastPostIds = forumGroup.Forums
+            var lastPostIds = group.Forums
                 .Where(x => x.LastPostId != 0)
                 .Select(x => x.LastPostId)
                 .Distinct()
@@ -168,7 +168,7 @@ private ForumGroupModel PrepareForumGroupModel(ForumGroup forumGroup)
 
             var lastPosts = _forumService.GetPostsByIds(lastPostIds).ToDictionary(x => x.Id);
 
-            foreach (var forum in forumGroup.Forums)
+            foreach (var forum in group.Forums.OrderBy(x => x.DisplayOrder))
             {
                 var forumModel = PrepareForumRowModel(forum, lastPosts);
                 forumModel.LastPost.ShowTopic = true;
@@ -224,31 +224,6 @@ private IEnumerable<SelectListItem> ForumTopicTypesList()
             return list;
         }
 
-        private IEnumerable<SelectListItem> ForumGroupsForumsList()
-        {
-            var forumsList = new List<SelectListItem>();
-            var separator = "--";
-            var store = Services.StoreContext.CurrentStore;
-            var forumGroups = _forumService.GetAllForumGroups(store.Id);
-
-            foreach (var fg in forumGroups)
-            {
-                // Add the forum group with Value of 0 so it won't be used as a target forum.
-                forumsList.Add(new SelectListItem { Text = fg.GetLocalized(x => x.Name), Value = "0" });
-
-                foreach (var f in fg.Forums)
-                {
-                    forumsList.Add(new SelectListItem 
-                    {
-                        Text = separator + f.GetLocalized(x => x.Name),
-                        Value = f.Id.ToString()
-                    });
-                }
-            }
-
-            return forumsList;
-        }
-
 		private void CreateForumBreadcrumb(ForumGroup group = null, Forum forum = null, ForumTopic topic = null)
 		{
 			_breadcrumb.Track(new MenuItem
@@ -346,17 +321,17 @@ public ActionResult Index()
             }
 
             var store = Services.StoreContext.CurrentStore;
-            var forumGroups = _forumService.GetAllForumGroups(store.Id);
+            var groups = _forumService.GetAllForumGroups(store.Id);
 
             var model = new BoardsIndexModel
             {
                 CurrentTime = _dateTimeHelper.ConvertToUserTime(DateTime.UtcNow)
             };
 
-            foreach (var forumGroup in forumGroups)
+            foreach (var group in groups)
             {
-                var forumGroupModel = PrepareForumGroupModel(forumGroup);
-                model.ForumGroups.Add(forumGroupModel);
+                var groupModel = PrepareForumGroupModel(group);
+                model.ForumGroups.Add(groupModel);
             }
 
             return View(model);
@@ -369,14 +344,14 @@ public ActionResult ForumGroup(int id)
 				return HttpNotFound();
             }
 
-            var forumGroup = _forumService.GetForumGroupById(id);
-            if (forumGroup == null || !_storeMappingService.Authorize(forumGroup) || !_aclService.Authorize(forumGroup))
+            var group = _forumService.GetForumGroupById(id);
+            if (group == null || !_storeMappingService.Authorize(group) || !_aclService.Authorize(group))
             {
                 return HttpNotFound();
             }
 
-            var model = PrepareForumGroupModel(forumGroup);
-			CreateForumBreadcrumb(group: forumGroup);
+            var model = PrepareForumGroupModel(group);
+			CreateForumBreadcrumb(group: group);
 
 			return View(model);
         }
@@ -514,10 +489,10 @@ public ActionResult ForumWatch(int id)
                 return Json(new { Subscribed = subscribed, Text = returnText, Error = true });
             }
 
-            var forumSubscription = _forumService.GetAllSubscriptions(customer.Id, forum.Id, 0, 0, 1).FirstOrDefault();
-            if (forumSubscription == null)
+            var subscription = _forumService.GetAllSubscriptions(customer.Id, forum.Id, 0, 0, 1).FirstOrDefault();
+            if (subscription == null)
             {
-                forumSubscription = new ForumSubscription
+                subscription = new ForumSubscription
                 {
                     SubscriptionGuid = Guid.NewGuid(),
                     CustomerId = customer.Id,
@@ -525,13 +500,13 @@ public ActionResult ForumWatch(int id)
                     CreatedOnUtc = DateTime.UtcNow
                 };
 
-                _forumService.InsertSubscription(forumSubscription);
+                _forumService.InsertSubscription(subscription);
                 subscribed = true;
                 returnText = T("Forum.UnwatchForum");
             }
             else
             {
-                _forumService.DeleteSubscription(forumSubscription);
+                _forumService.DeleteSubscription(subscription);
                 subscribed = false;
             }
 
@@ -836,7 +811,22 @@ public ActionResult TopicMove(int id)
                 return new HttpUnauthorizedResult();
             }
 
-            model.ForumList = ForumGroupsForumsList();
+            // Forums select box.
+            model.Forums = new List<SelectListItem>();
+            var groups = _forumService.GetAllForumGroups(Services.StoreContext.CurrentStore.Id);
+            foreach (var group in groups)
+            {
+                var optGroup = new SelectListGroup { Name = group.GetLocalized(x => x.Name) };
+                foreach (var forum in group.Forums.OrderBy(x => x.DisplayOrder))
+                {
+                    model.Forums.Add(new SelectListItem
+                    {
+                        Text = forum.GetLocalized(x => x.Name),
+                        Value = forum.Id.ToString(),
+                        Group = optGroup
+                    });
+                }
+            }
 
             CreateForumBreadcrumb(topic: topic);
 
@@ -1597,21 +1587,21 @@ public ActionResult PostDelete(int id)
                 return new HttpUnauthorizedResult();
             }
 
-            var forumTopic = post.ForumTopic;
-            var forumId = forumTopic.Forum.Id;
-            var forumSlug = forumTopic.Forum.GetSeName();
+            var topic = post.ForumTopic;
+            var forumId = topic.Forum.Id;
+            var forumSlug = topic.Forum.GetSeName();
 
             _forumService.DeletePost(post);
 
             // Get topic one more time because it can be deleted (first or only post deleted).
-            forumTopic = _forumService.GetTopicById(post.TopicId);
-            if (forumTopic == null)
+            topic = _forumService.GetTopicById(post.TopicId);
+            if (topic == null)
             {
                 return RedirectToRoute("ForumSlug", new { id = forumId, slug = forumSlug });
             }
             else
             {
-                return RedirectToRoute("TopicSlug", new { id = forumTopic.Id, slug = forumTopic.GetSeName() });
+                return RedirectToRoute("TopicSlug", new { id = topic.Id, slug = topic.GetSeName() });
             }
         }
 
diff --git a/src/Presentation/SmartStore.Web/Models/Boards/TopicMoveModel.cs b/src/Presentation/SmartStore.Web/Models/Boards/TopicMoveModel.cs
index b784c10cbd..6a5dccb4cc 100644
--- a/src/Presentation/SmartStore.Web/Models/Boards/TopicMoveModel.cs
+++ b/src/Presentation/SmartStore.Web/Models/Boards/TopicMoveModel.cs
@@ -6,16 +6,11 @@ namespace SmartStore.Web.Models.Boards
 {
     public partial class TopicMoveModel : EntityModelBase
     {
-        public TopicMoveModel()
-        {
-            ForumList = new List<SelectListItem>();
-        }
-
-        public int ForumSelected { get; set; }
         public string TopicSeName { get; set; }
         public bool IsCustomerAllowedToEdit { get; set; }
         public int CustomerId { get; set; }
 
-        public IEnumerable<SelectListItem> ForumList { get; set; }
+        public int ForumSelected { get; set; }
+        public IList<SelectListItem> Forums { get; set; }
     }
 }
\ No newline at end of file
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/TopicMove.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/TopicMove.cshtml
index 15e314e63c..0562526ec4 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/TopicMove.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/TopicMove.cshtml
@@ -12,16 +12,17 @@
             <h2>@T("Forum.MoveTopic")</h2>
         </div>
         <div class="page-body">
-            <h4 class="my-3">@T("Forum.SelectTheForumToMoveTopic")</h4>
-            <div>
-                @Html.DropDownList("ForumSelected", new SelectList(Model.ForumList, "Value", "Text"), new { @class = "form-control" })
+            <div class="form-group">
+                <label for="@Html.IdFor(x => x.ForumSelected)">@T("Forum.SelectTheForumToMoveTopic")</label>
+                @Html.DropDownListFor(x => x.ForumSelected, Model.Forums, new { @class = "form-control" })
             </div>
-
             <div class="options my-3">
                 <button type="submit" class="btn btn-primary">
+                    <i class="fa fa-reply"></i>
 					<span>@T("Forum.Submit")</span>
 				</button>
                 <a class="btn btn-secondary" href="@Url.RouteUrl("TopicSlug", new { id = Model.Id, slug = Model.TopicSeName })">
+                    <i class="fa fa-times"></i>
                     <span>@T("Forum.Cancel")</span>
                 </a>
             </div>

From 904f60cbf145032c0a3f341a5299c874f1253269 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Fri, 28 Sep 2018 16:09:02 +0200
Subject: [PATCH 27/71] Improved asynchronous loading of forum search hits

---
 .../Views/Boards/Partials/SearchHits.cshtml   | 17 +++--
 .../SmartStore.Web/Views/Boards/Search.cshtml | 67 +++++++++++++------
 2 files changed, 55 insertions(+), 29 deletions(-)

diff --git a/src/Presentation/SmartStore.Web/Views/Boards/Partials/SearchHits.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/Partials/SearchHits.cshtml
index c702fa4442..5a5ec93ad6 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/Partials/SearchHits.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/Partials/SearchHits.cshtml
@@ -76,13 +76,16 @@
 </tbody>
 @if (Model.PagedList.TotalCount == 0 || !Model.PagedList.HasNextPage)
 {
-    <tfoot class="border-0">
-        <tr>
-            <td colspan="5">
-                <span class="text-muted">@T("Search.NoMoreHitsFound")</span>
-            </td>
-        </tr>
-    </tfoot>
+    if (Model.PagedList.TotalPages > 1)
+    {
+        <tfoot class="border-0">
+            <tr>
+                <td colspan="5">
+                    <span class="text-muted">@T("Search.NoMoreHitsFound")</span>
+                </td>
+            </tr>
+        </tfoot>
+    }
 }
 else if (Model.Error.HasValue())
 {
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/Search.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/Search.cshtml
index 7e6cf51acc..6425113e07 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/Search.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/Search.cshtml
@@ -139,26 +139,28 @@
 
 <script type="text/javascript">
     $(document).ready(function () {
-        var result = $('#ForumSearchResult');
+        var result = $('#ForumSearchResult'),
+            loading = false;
 
         // Sorting changed.
         $('.fsearch-actions').on('change', '.artlist-action-select', function (e) {
-		    var select = $(this),
-			    qname = select.data('qname'),
-			    url = select.data('url'),
-			    val = select.val();
+            var select = $(this),
+                qname = select.data('qname'),
+                url = select.data('url'),
+                val = select.val();
 
-		    var url = window.modifyUrl(url, qname, val);
-		    window.setLocation(url);
-	    });
+            url = window.modifyUrl(url, qname, val);
+            window.setLocation(url);
+        });
 
         // Auto load more search hits.
         $(document).scroll( function() {           
             var container = result.find('.load-more:not(.loading)');
 
-            if (container.visible(true, false, 'vertical')) {
+            if (container.visible(true, false, 'vertical') && !loading) {
                 var newPage = container.data('page'),
-                    url = window.modifyUrl(window.location.href, 'i', newPage);
+                    url = window.modifyUrl(window.location.href, 'i', newPage),
+                    html, processImmediately = false;
 
                 // IDs of already rendered topics, to avoid rendering them again when the list is extended.
                 var renderedTopicIds = result.find('tr.topic').map(function() {
@@ -167,6 +169,12 @@
 
                 //console.log(page + '. ' + url + '. ' + renderedTopicIds.toString());
 
+                setTimeout(function () {
+                    processImmediately = true;
+                    processSearchResult(html, container, newPage);
+                    html = null;
+                }, 100);
+
                 $.ajax({
                     cache: false,
                     type: 'POST',
@@ -174,31 +182,46 @@
                     url: url,
                     data: { renderedTopicIds: renderedTopicIds },
                     beforeSend: function () {
+                        loading = true;
                         container.addClass('loading').append(createCircularSpinner(20, true));
                     },
                     success: function (response) {
-                        // Replace empty tbody at table end by page representing tbody.
-                        container.replaceWith(response);
-
-                        // Update cumulative hit counter.
-                        $counter = $('#SearchHitsCount');
-                        $pageBody = result.find('tbody[data-page=' + newPage + ']');
-                        $counter.find('.cumulative-count').text($pageBody.data('cumulativehits'));
-                        if (!$pageBody.data('hasnextpage')) {
-                            $counter.find('.more-hits-sign').hide();
+                        if (processImmediately) {
+                            processSearchResult(response, container, newPage);
+                        }
+                        else {
+                            html = response;
                         }
                     },
+                    complete: function () {
+                        loading = false;
+                    },
                     error: function (objXml) {
                         result.find('.load-more:not(.loading)').removeClass('loading');
 
-                        if (objXml != null && objXml.responseText != null && objXml.responseText !== '') {
+                        if (objXml && objXml.responseText.length > 0) {
                             displayNotification(objXml.responseText, 'error');
-			            }
+                        }
                     }
-		        });
+                });
 
             }
         });
 
+        function processSearchResult(html, container, newPage) {
+            if (html && html.length > 0) {
+                // Replace empty tbody at table end by page representing tbody.
+                container.replaceWith(html);
+
+                // Update cumulative hit counter.
+                $counter = $('#SearchHitsCount');
+                $pageBody = result.find('tbody[data-page=' + newPage + ']');
+                $counter.find('.cumulative-count').text($pageBody.data('cumulativehits'));
+                if (!$pageBody.data('hasnextpage')) {
+                    $counter.find('.more-hits-sign').hide();
+                }
+            }
+        }
+
     });
 </script>
\ No newline at end of file

From 0b33722bd581eee640345b640ab32aad38953d50 Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Sat, 29 Sep 2018 04:06:21 +0200
Subject: [PATCH 28/71] Minor code fix

---
 .../SmartStore.Core/Search/Facets/FacetValue.cs     |  4 ++--
 .../Hooks/UpdateCustomerFullNameHook.cs             |  9 ++++-----
 .../Templating/Liquid/LiquidTemplateEngine.cs       | 13 +++++--------
 3 files changed, 11 insertions(+), 15 deletions(-)

diff --git a/src/Libraries/SmartStore.Core/Search/Facets/FacetValue.cs b/src/Libraries/SmartStore.Core/Search/Facets/FacetValue.cs
index e3e451cab7..80e54b44af 100644
--- a/src/Libraries/SmartStore.Core/Search/Facets/FacetValue.cs
+++ b/src/Libraries/SmartStore.Core/Search/Facets/FacetValue.cs
@@ -100,8 +100,8 @@ public override int GetHashCode()
 			{
 				var combiner = HashCodeCombiner
 					.Start()
-					.Add(Value.GetHashCode())
-					.Add(UpperValue.GetHashCode());
+					.Add(Value)
+					.Add(UpperValue);
 
 				return combiner.CombinedHash;
 			}
diff --git a/src/Libraries/SmartStore.Services/Hooks/UpdateCustomerFullNameHook.cs b/src/Libraries/SmartStore.Services/Hooks/UpdateCustomerFullNameHook.cs
index 662659d2dd..ba90b19cc8 100644
--- a/src/Libraries/SmartStore.Services/Hooks/UpdateCustomerFullNameHook.cs
+++ b/src/Libraries/SmartStore.Services/Hooks/UpdateCustomerFullNameHook.cs
@@ -5,7 +5,6 @@
 using SmartStore.Core.Data;
 using SmartStore.Core.Data.Hooks;
 using SmartStore.Core.Domain.Customers;
-using SmartStore.Utilities;
 
 namespace SmartStore.Services.Hooks
 {
@@ -14,10 +13,10 @@ public class UpdateCustomerFullNameHook : DbSaveHook<Customer>
 	{
 		private static readonly HashSet<string> _candidateProps = new HashSet<string>(new string[] 
 		{
-			TypeHelper.NameOf<Customer>(x => x.Title),
-			TypeHelper.NameOf<Customer>(x => x.Salutation),
-			TypeHelper.NameOf<Customer>(x => x.FirstName),
-			TypeHelper.NameOf<Customer>(x => x.LastName)
+			nameof(Customer.Title),
+			nameof(Customer.Salutation),
+			nameof(Customer.FirstName),
+			nameof(Customer.LastName)
 		});
 
 		private readonly IComponentContext _ctx;
diff --git a/src/Presentation/SmartStore.Web.Framework/Templating/Liquid/LiquidTemplateEngine.cs b/src/Presentation/SmartStore.Web.Framework/Templating/Liquid/LiquidTemplateEngine.cs
index 9f3b03baca..a229d69208 100644
--- a/src/Presentation/SmartStore.Web.Framework/Templating/Liquid/LiquidTemplateEngine.cs
+++ b/src/Presentation/SmartStore.Web.Framework/Templating/Liquid/LiquidTemplateEngine.cs
@@ -1,18 +1,15 @@
 using System;
 using System.IO;
 using System.Web;
-using System.Web.Hosting;
 using DotLiquid;
 using DotLiquid.FileSystems;
 using DotLiquid.NamingConventions;
 using SmartStore.Core;
-using SmartStore.Core.Events;
 using SmartStore.Core.Infrastructure.DependencyManagement;
 using SmartStore.Core.IO;
 using SmartStore.Core.Localization;
 using SmartStore.Core.Themes;
 using SmartStore.Services;
-using SmartStore.Utilities;
 
 namespace SmartStore.Templating.Liquid
 {
@@ -37,11 +34,11 @@ public LiquidTemplateEngine(
 			// Register Value type transformers
 			var allowedMoneyProps = new[] 
 			{
-				TypeHelper.NameOf<Money>(x => x.Amount),
-				TypeHelper.NameOf<Money>(x => x.RoundedAmount),
-				TypeHelper.NameOf<Money>(x => x.TruncatedAmount),
-				TypeHelper.NameOf<Money>(x => x.Formatted),
-				TypeHelper.NameOf<Money>(x => x.DecimalDigits)
+				nameof(Money.Amount),
+				nameof(Money.RoundedAmount),
+				nameof(Money.TruncatedAmount),
+				nameof(Money.Formatted),
+				nameof(Money.DecimalDigits)
 			};
 			Template.RegisterSafeType(typeof(Money), allowedMoneyProps, x => x);
 			

From efe8fe2b25c5bb91a2a808d52744ec6253eb0514 Mon Sep 17 00:00:00 2001
From: Michael Herzog <herzog@smartstore.com>
Date: Mon, 1 Oct 2018 10:54:55 +0200
Subject: [PATCH 29/71] Import: Validate picture parameter modifies file size
 thus subsequent search for equal images fails

---
 .../Catalog/Importer/CategoryImporter.cs              |  9 ++++-----
 .../Catalog/Importer/ProductImporter.cs               | 11 ++++-------
 .../Customers/Importer/CustomerImporter.cs            |  9 ++++-----
 3 files changed, 12 insertions(+), 17 deletions(-)

diff --git a/src/Libraries/SmartStore.Services/Catalog/Importer/CategoryImporter.cs b/src/Libraries/SmartStore.Services/Catalog/Importer/CategoryImporter.cs
index 504c4d91a2..57d484a6b6 100644
--- a/src/Libraries/SmartStore.Services/Catalog/Importer/CategoryImporter.cs
+++ b/src/Libraries/SmartStore.Services/Catalog/Importer/CategoryImporter.cs
@@ -221,15 +221,14 @@ protected virtual int ProcessPictures(
 											currentPictures.Add(picture);
 										}
 									}
-
-									var size = Size.Empty;
-									pictureBinary = _pictureService.ValidatePicture(pictureBinary, image.MimeType, out size);
+                                    
 									pictureBinary = _pictureService.FindEqualPicture(pictureBinary, currentPictures, out equalPictureId);
 
 									if (pictureBinary != null && pictureBinary.Length > 0)
 									{
-										var picture = _pictureService.InsertPicture(pictureBinary, image.MimeType, seoName, true, size.Width, size.Height, false);
-										if (picture != null)
+										//var picture = _pictureService.InsertPicture(pictureBinary, image.MimeType, seoName, true, size.Width, size.Height, false);
+                                        var picture = _pictureService.InsertPicture(pictureBinary, image.MimeType, seoName, true, false, false); ;
+                                        if (picture != null)
 										{
 											category.PictureId = picture.Id;
 											_categoryRepository.Update(category);
diff --git a/src/Libraries/SmartStore.Services/Catalog/Importer/ProductImporter.cs b/src/Libraries/SmartStore.Services/Catalog/Importer/ProductImporter.cs
index d15e4ed20d..b12d3c2d44 100644
--- a/src/Libraries/SmartStore.Services/Catalog/Importer/ProductImporter.cs
+++ b/src/Libraries/SmartStore.Services/Catalog/Importer/ProductImporter.cs
@@ -547,7 +547,6 @@ protected virtual void ProcessProductPictures(ImportExecuteContext context, IEnu
 							if (pictureBinary != null && pictureBinary.Length > 0)
 							{
 								var currentProductPictures = _productPictureRepository.TableUntracked
-									.Expand(x => x.Picture)
 									.Expand(x => x.Picture.MediaStorage)
 									.Where(x => x.ProductId == row.Entity.Id)
 									.ToList();
@@ -560,16 +559,14 @@ protected virtual void ProcessProductPictures(ImportExecuteContext context, IEnu
 								{
 									displayOrder = (currentProductPictures.Any() ? currentProductPictures.Select(x => x.DisplayOrder).Max() : 0);
 								}
-
-								var size = Size.Empty;
-								pictureBinary = _pictureService.ValidatePicture(pictureBinary, image.MimeType, out size);
+                                
 								pictureBinary = _pictureService.FindEqualPicture(pictureBinary, currentPictures, out equalPictureId);
 
 								if (pictureBinary != null && pictureBinary.Length > 0)
 								{
-									// no equal picture found in sequence
-									var newPicture = _pictureService.InsertPicture(pictureBinary, image.MimeType, seoName, true, size.Width, size.Height, false);
-									if (newPicture != null)
+                                    var newPicture = _pictureService.InsertPicture(pictureBinary, image.MimeType, seoName, true, false, false); ;
+
+                                    if (newPicture != null)
 									{
 										var mapping = new ProductPicture
 										{
diff --git a/src/Libraries/SmartStore.Services/Customers/Importer/CustomerImporter.cs b/src/Libraries/SmartStore.Services/Customers/Importer/CustomerImporter.cs
index 15b0cdcf13..62836732ce 100644
--- a/src/Libraries/SmartStore.Services/Customers/Importer/CustomerImporter.cs
+++ b/src/Libraries/SmartStore.Services/Customers/Importer/CustomerImporter.cs
@@ -606,15 +606,14 @@ protected virtual int ProcessAvatars(
 								currentPictures.Add(picture);
 							}
 						}
-
-						var size = Size.Empty;
-						pictureBinary = _pictureService.ValidatePicture(pictureBinary, image.MimeType, out size);
+                        
 						pictureBinary = _pictureService.FindEqualPicture(pictureBinary, currentPictures, out equalPictureId);
 
 						if (pictureBinary != null && pictureBinary.Length > 0)
 						{
-							var picture = _pictureService.InsertPicture(pictureBinary, image.MimeType, seoName, true, size.Width, size.Height, false);
-							if (picture != null)
+                            var picture = _pictureService.InsertPicture(pictureBinary, image.MimeType, seoName, true, false, false);
+
+                            if (picture != null)
 							{
 								SaveAttribute(row, SystemCustomerAttributeNames.AvatarPictureId, picture.Id);
 							}

From 95499debea88deeb3afa30b17f3b330d6a08a501 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Mon, 1 Oct 2018 11:15:31 +0200
Subject: [PATCH 30/71] Avoid "No route in the route table matches the supplied
 values" (rare case of a grouped product)

---
 .../SmartStore.Web/Controllers/ProductController.cs      | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/Presentation/SmartStore.Web/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Controllers/ProductController.cs
index b48f76ff53..a69302a416 100644
--- a/src/Presentation/SmartStore.Web/Controllers/ProductController.cs
+++ b/src/Presentation/SmartStore.Web/Controllers/ProductController.cs
@@ -160,12 +160,15 @@ public ActionResult ProductDetails(int productId, string attributes, ProductVari
 			{
 				// Find parent grouped product.
 				var parentGroupedProduct = _productService.GetProductById(product.ParentGroupedProductId);
-
 				if (parentGroupedProduct == null)
 					return HttpNotFound();
 
-				var routeValues = new RouteValueDictionary();
-				routeValues.Add("SeName", parentGroupedProduct.GetSeName());
+                var seName = parentGroupedProduct.GetSeName();
+                if (seName.IsEmpty())
+                    return HttpNotFound();
+
+                var routeValues = new RouteValueDictionary();
+				routeValues.Add("SeName", seName);
 
 				// Add query string parameters.
 				Request.QueryString.AllKeys.Each(x => routeValues.Add(x, Request.QueryString[x]));

From 80d70feec9d442c2291b70a965f4e622c73a36dc Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Mon, 1 Oct 2018 13:04:53 +0200
Subject: [PATCH 31/71] Avoid exception "Failed to parse email address for
 variable..." if parsed email address is an empty string

---
 src/Libraries/SmartStore.Services/Messages/MessageFactory.cs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/Libraries/SmartStore.Services/Messages/MessageFactory.cs b/src/Libraries/SmartStore.Services/Messages/MessageFactory.cs
index 14d42ddb6d..284269020b 100644
--- a/src/Libraries/SmartStore.Services/Messages/MessageFactory.cs
+++ b/src/Libraries/SmartStore.Services/Messages/MessageFactory.cs
@@ -187,7 +187,7 @@ private EmailAddress RenderEmailAddress(string email, MessageContext ctx, bool r
 			{
 				parsed = RenderTemplate(email, ctx, required);
 
-				if (required || parsed != null)
+				if (required || parsed.HasValue())
 				{
 					return parsed.Convert<EmailAddress>();
 				}

From 141c665f3821a9c19ac7661c9844139a52e3a38a Mon Sep 17 00:00:00 2001
From: Michael Herzog <herzog@smartstore.com>
Date: Mon, 1 Oct 2018 14:37:34 +0200
Subject: [PATCH 32/71] Added CustomerLoggedInEvent

---
 .../Customers/Events/CustomerLogedInEvent.cs  | 17 +++++++++++++++++
 .../Events/CustomerRegisteredEvent.cs         |  2 +-
 .../SmartStore.Services.csproj                |  1 +
 .../Controllers/CustomerController.cs         | 19 +++++++++++--------
 4 files changed, 30 insertions(+), 9 deletions(-)
 create mode 100644 src/Libraries/SmartStore.Services/Customers/Events/CustomerLogedInEvent.cs

diff --git a/src/Libraries/SmartStore.Services/Customers/Events/CustomerLogedInEvent.cs b/src/Libraries/SmartStore.Services/Customers/Events/CustomerLogedInEvent.cs
new file mode 100644
index 0000000000..b224692e64
--- /dev/null
+++ b/src/Libraries/SmartStore.Services/Customers/Events/CustomerLogedInEvent.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using SmartStore.Core.Domain.Customers;
+
+namespace SmartStore.Services.Customers
+{
+	/// <summary>
+	/// An event message, which will be published after customer has logged in
+	/// </summary>
+    public class CustomerLogedInEvent
+	{
+        public Customer Customer
+		{ 
+			get; 
+			set; 
+		}
+	}
+}
diff --git a/src/Libraries/SmartStore.Services/Customers/Events/CustomerRegisteredEvent.cs b/src/Libraries/SmartStore.Services/Customers/Events/CustomerRegisteredEvent.cs
index 76bc89b1de..920c08fca6 100644
--- a/src/Libraries/SmartStore.Services/Customers/Events/CustomerRegisteredEvent.cs
+++ b/src/Libraries/SmartStore.Services/Customers/Events/CustomerRegisteredEvent.cs
@@ -4,7 +4,7 @@
 namespace SmartStore.Services.Customers
 {
 	/// <summary>
-	/// An event message, which gets published after customer was registered
+	/// An event message, which will be published after customer has registered
 	/// </summary>
     public class CustomerRegisteredEvent
 	{
diff --git a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj
index 54a0760a18..a26437105d 100644
--- a/src/Libraries/SmartStore.Services/SmartStore.Services.csproj
+++ b/src/Libraries/SmartStore.Services/SmartStore.Services.csproj
@@ -211,6 +211,7 @@
     <Compile Include="Customers\CustomerSearchQuery.cs" />
     <Compile Include="Customers\Events\CustomerAnonymizedEvent.cs" />
     <Compile Include="Customers\Events\CustomerExportedEvent.cs" />
+    <Compile Include="Customers\Events\CustomerLogedInEvent.cs" />
     <Compile Include="Customers\Events\CustomerRegisteredEvent.cs" />
     <Compile Include="Customers\GdprTool.cs" />
     <Compile Include="Customers\IGdprTool.cs" />
diff --git a/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs b/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs
index 81b9d388e4..21fdd3e78d 100644
--- a/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs
+++ b/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs
@@ -39,6 +39,7 @@
 using SmartStore.Web.Framework.UI;
 using SmartStore.Web.Models.Common;
 using SmartStore.Web.Models.Customer;
+using SmartStore.Core.Events;
 
 namespace SmartStore.Web.Controllers
 {
@@ -82,18 +83,18 @@ public partial class CustomerController : PublicControllerBase
         private readonly IWebHelper _webHelper;
         private readonly ICustomerActivityService _customerActivityService;
 		private readonly ProductUrlHelper _productUrlHelper;
-
-        private readonly MediaSettings _mediaSettings;
+		private readonly MediaSettings _mediaSettings;
         private readonly LocalizationSettings _localizationSettings;
         private readonly CaptchaSettings _captchaSettings;
         private readonly ExternalAuthenticationSettings _externalAuthenticationSettings;
 		private readonly PluginMediator _pluginMediator;
+		private readonly IEventPublisher _eventPublisher;
 
-        #endregion
+		#endregion
 
-        #region Ctor
+		#region Ctor
 
-        public CustomerController(
+		public CustomerController(
             ICommonServices services,
             IAuthenticationService authenticationService,
             IDateTimeHelper dateTimeHelper,
@@ -122,7 +123,7 @@ public CustomerController(
 			MediaSettings mediaSettings,
             LocalizationSettings localizationSettings,
             CaptchaSettings captchaSettings, ExternalAuthenticationSettings externalAuthenticationSettings,
-			PluginMediator pluginMediator)
+			PluginMediator pluginMediator, IEventPublisher eventPublisher)
         {
             _services = services;
             _authenticationService = authenticationService;
@@ -160,13 +161,13 @@ public CustomerController(
             _webHelper = webHelper;
             _customerActivityService = customerActivityService;
 			_productUrlHelper = productUrlHelper;
-
 			_mediaSettings = mediaSettings;
             _localizationSettings = localizationSettings;
             _captchaSettings = captchaSettings;
             _externalAuthenticationSettings = externalAuthenticationSettings;
 			_pluginMediator = pluginMediator;
-        }
+			_eventPublisher = eventPublisher;
+		}
 
         #endregion
 
@@ -485,6 +486,8 @@ public ActionResult Login(LoginModel model, string returnUrl, bool captchaValid)
 
                     _customerActivityService.InsertActivity("PublicStore.Login", _localizationService.GetResource("ActivityLog.PublicStore.Login"), customer);
 
+					_eventPublisher.Publish(new CustomerLogedInEvent { Customer = customer });
+
 					// Redirect home where redirect to referrer would be confusing.
 					if (returnUrl.IsEmpty() || returnUrl.Contains(@"/login?") || returnUrl.Contains(@"/passwordrecoveryconfirm"))
 					{

From c9fc0ea5fdeebc7f8d345ce1f1b78f7294d4fe85 Mon Sep 17 00:00:00 2001
From: Michael Herzog <herzog@smartstore.com>
Date: Mon, 1 Oct 2018 15:44:51 +0200
Subject: [PATCH 33/71] Updated changelog

---
 changelog.md | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/changelog.md b/changelog.md
index 759bbdbfc1..1975b7b336 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,8 +1,12 @@
-# Release Notes
+# Release Notes
 
 ## SmartStore.NET 3.2
 
 ### New Features
+* **EmailReminder**:
+	* Reminders for open shopping carts
+	* Reminders for product reviews
+	* Reminders to visit the shop after a long absence
 * #1144 Enable multi server search index
 * Made Topic ACL enabled
 * Implemented paging & filtering for Topic grid
@@ -25,12 +29,18 @@
 	* #1172 Option to display related search terms on search page.
 * Customer avatar: Letter with colored background if no avatar image was uploaded.
 * Viveum: Supports payment via "Virtual Account Brands" like PayPal.
+* Added options for alternating price display (in badges)
 
 ### Improvements
 * (Perf) Significantly increased query performance for products with a lot of category assignments (> 10).
 * Debitoor: Partially update customer instead of full update to avoid all fields being overwritten
 * #1479 Show in messages the delivery time at the time of purchase
 * #1184 Sort Current shopping carts & Current wishlists by ShoppingCartItem.CreatedOn.
+* #1106 BMECat: import & export support for product keywords
+* #1499 Add hint to forms indicating that fields with an asterisk (*)
+* Added filter for newsletter subscriber export by working language
+* Refactored download section  
+* Enhanced EntityPicker to pick from customers, manufacturers & categories
 
 ### Bugfixes
 * In a multi-store environment, multiple topics with the same system name cannot be resolved reliably.
@@ -61,6 +71,9 @@
 * #1504 Cart item price calculation wrong if attribute combinations with text types are involved.
 * #1485 Dropdown list for product sorting does not work with Internet Explorer 11.
 * #1468 Twitter authentication not working anymore.
+* Newsletter subscription didn't work when customer privacy setting DisplayGdprConsentOnForms was turned off
+* Fixed social media image detection
+* Fixed redirection of bots when several languages were active
 
 
 ## SmartStore.NET 3.1.5

From 680c2175db716108629d3b5c683ecff9e589ba0c Mon Sep 17 00:00:00 2001
From: Michael Herzog <herzog@smartstore.com>
Date: Mon, 1 Oct 2018 15:44:51 +0200
Subject: [PATCH 34/71] Updated changelog

---
 changelog.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/changelog.md b/changelog.md
index 1975b7b336..44d18966c1 100644
--- a/changelog.md
+++ b/changelog.md
@@ -37,7 +37,7 @@
 * #1479 Show in messages the delivery time at the time of purchase
 * #1184 Sort Current shopping carts & Current wishlists by ShoppingCartItem.CreatedOn.
 * #1106 BMECat: import & export support for product keywords
-* #1499 Add hint to forms indicating that fields with an asterisk (*)
+* #1499 Added hint to forms indicating that fields with an asterisk (*)
 * Added filter for newsletter subscriber export by working language
 * Refactored download section  
 * Enhanced EntityPicker to pick from customers, manufacturers & categories

From 9e88ffbf2f57228eda137279312f0df616c6c4c7 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Mon, 1 Oct 2018 22:00:19 +0200
Subject: [PATCH 35/71] Getting started with voting on forum posts

---
 .../Catalog/ProductReviewHelpfulness.cs       |   9 +-
 .../Domain/Forums/ForumPost.cs                |  12 ++
 .../Domain/Forums/ForumPostVote.cs            |  25 ++++
 .../Domain/Forums/ForumSettings.cs            |  13 +-
 .../SmartStore.Core/SmartStore.Core.csproj    |   1 +
 .../Mapping/Forums/ForumPostVoteMap.cs        |  18 +++
 .../201810011954195_ForumPostVote.Designer.cs |  29 ++++
 .../201810011954195_ForumPostVote.cs          |  35 +++++
 .../201810011954195_ForumPostVote.resx        | 126 ++++++++++++++++++
 .../Migrations/MigrationsConfiguration.cs     |  14 ++
 .../SmartStore.Data/SmartStore.Data.csproj    |   8 ++
 .../Controllers/BoardsController.cs           |  81 ++++++++++-
 .../Models/Boards/ForumPostModel.cs           |   3 +
 .../Views/Boards/Partials/_ForumPost.cshtml   |  13 +-
 .../SmartStore.Web/Views/Boards/Topic.cshtml  |  29 +++-
 15 files changed, 401 insertions(+), 15 deletions(-)
 create mode 100644 src/Libraries/SmartStore.Core/Domain/Forums/ForumPostVote.cs
 create mode 100644 src/Libraries/SmartStore.Data/Mapping/Forums/ForumPostVoteMap.cs
 create mode 100644 src/Libraries/SmartStore.Data/Migrations/201810011954195_ForumPostVote.Designer.cs
 create mode 100644 src/Libraries/SmartStore.Data/Migrations/201810011954195_ForumPostVote.cs
 create mode 100644 src/Libraries/SmartStore.Data/Migrations/201810011954195_ForumPostVote.resx

diff --git a/src/Libraries/SmartStore.Core/Domain/Catalog/ProductReviewHelpfulness.cs b/src/Libraries/SmartStore.Core/Domain/Catalog/ProductReviewHelpfulness.cs
index e6b612e382..7d9cd545d1 100644
--- a/src/Libraries/SmartStore.Core/Domain/Catalog/ProductReviewHelpfulness.cs
+++ b/src/Libraries/SmartStore.Core/Domain/Catalog/ProductReviewHelpfulness.cs
@@ -1,25 +1,24 @@
-
 using SmartStore.Core.Domain.Customers;
 
 namespace SmartStore.Core.Domain.Catalog
 {
     /// <summary>
-    /// Represents a product review helpfulness
+    /// Represents a product review helpfulness.
     /// </summary>
     public partial class ProductReviewHelpfulness : CustomerContent
     {
         /// <summary>
-        /// Gets or sets the product review identifier
+        /// Gets or sets the product review identifier.
         /// </summary>
         public int ProductReviewId { get; set; }
 
         /// <summary>
-        /// A value indicating whether a review a helpful
+        /// A value indicating whether a review is helpful.
         /// </summary>
         public bool WasHelpful { get; set; }
 
         /// <summary>
-        /// Gets the product
+        /// Gets the product review.
         /// </summary>
         public virtual ProductReview ProductReview { get; set; }
     }
diff --git a/src/Libraries/SmartStore.Core/Domain/Forums/ForumPost.cs b/src/Libraries/SmartStore.Core/Domain/Forums/ForumPost.cs
index 292615a8d3..e65c80573d 100644
--- a/src/Libraries/SmartStore.Core/Domain/Forums/ForumPost.cs
+++ b/src/Libraries/SmartStore.Core/Domain/Forums/ForumPost.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Generic;
 using System.ComponentModel.DataAnnotations.Schema;
 using SmartStore.Core.Domain.Customers;
 
@@ -9,6 +10,8 @@ namespace SmartStore.Core.Domain.Forums
     /// </summary>
     public partial class ForumPost : BaseEntity, IAuditable
 	{
+        private ICollection<ForumPostVote> _forumPostVotes;
+
         /// <summary>
         /// Gets or sets the forum topic identifier
         /// </summary>
@@ -55,5 +58,14 @@ public partial class ForumPost : BaseEntity, IAuditable
         /// Gets the customer
         /// </summary>
         public virtual Customer Customer { get; set; }
+
+        /// <summary>
+        /// Forum post votes.
+        /// </summary>
+        public virtual ICollection<ForumPostVote> ForumPostVotes
+        {
+            get { return _forumPostVotes ?? (_forumPostVotes = new HashSet<ForumPostVote>()); }
+            protected set { _forumPostVotes = value; }
+        }
     }
 }
diff --git a/src/Libraries/SmartStore.Core/Domain/Forums/ForumPostVote.cs b/src/Libraries/SmartStore.Core/Domain/Forums/ForumPostVote.cs
new file mode 100644
index 0000000000..1799d22dd3
--- /dev/null
+++ b/src/Libraries/SmartStore.Core/Domain/Forums/ForumPostVote.cs
@@ -0,0 +1,25 @@
+using SmartStore.Core.Domain.Customers;
+
+namespace SmartStore.Core.Domain.Forums
+{
+    /// <summary>
+    /// Represents a vote for a forum post.
+    /// </summary>
+    public partial class ForumPostVote : CustomerContent
+    {
+        /// <summary>
+        /// Forum post identifier.
+        /// </summary>
+        public int ForumPostId { get; set; }
+
+        /// <summary>
+        /// A value indicating whether the customer voted for or against a forum post.
+        /// </summary>
+        public bool Vote { get; set; }
+
+        /// <summary>
+        /// Forum post entity.
+        /// </summary>
+        public virtual ForumPost ForumPost { get; set; }
+    }
+}
diff --git a/src/Libraries/SmartStore.Core/Domain/Forums/ForumSettings.cs b/src/Libraries/SmartStore.Core/Domain/Forums/ForumSettings.cs
index ed484dbb4f..86a2b5e423 100644
--- a/src/Libraries/SmartStore.Core/Domain/Forums/ForumSettings.cs
+++ b/src/Libraries/SmartStore.Core/Domain/Forums/ForumSettings.cs
@@ -27,7 +27,8 @@ public ForumSettings()
 			HomePageActiveDiscussionsTopicCount = 5;
 			ActiveDiscussionsPageTopicCount = 50;
 			ActiveDiscussionsFeedCount = 25;
-		}
+            AllowCustomersToVoteOnPosts = true;
+        }
 		
 		/// <summary>
         /// Gets or sets a value indicating whether forums are enabled
@@ -64,6 +65,16 @@ public ForumSettings()
         /// </summary>
         public bool AllowCustomersToDeletePosts { get; set; }
 
+        /// <summary>
+        /// Gets or sets a value indicating whether customer can vote on posts
+        /// </summary>
+        public bool AllowCustomersToVoteOnPosts { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether guests are allowed to vote on posts
+        /// </summary>
+        public bool AllowGuestsToVoteOnPosts { get; set; }
+
         /// <summary>
         /// Gets or sets maximum length of topic subject
         /// </summary>
diff --git a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj
index 2a4eafc78f..ddb7fbe127 100644
--- a/src/Libraries/SmartStore.Core/SmartStore.Core.csproj
+++ b/src/Libraries/SmartStore.Core/SmartStore.Core.csproj
@@ -235,6 +235,7 @@
     <Compile Include="Domain\DataExchange\ExportFilter.cs" />
     <Compile Include="Domain\DataExchange\ExportProfile.cs" />
     <Compile Include="Domain\Forums\ForumDateFilter.cs" />
+    <Compile Include="Domain\Forums\ForumPostVote.cs" />
     <Compile Include="Domain\Forums\ForumTopicSorting.cs" />
     <Compile Include="Domain\Media\MediaStorage.cs" />
     <Compile Include="Domain\Media\IHasMedia.cs" />
diff --git a/src/Libraries/SmartStore.Data/Mapping/Forums/ForumPostVoteMap.cs b/src/Libraries/SmartStore.Data/Mapping/Forums/ForumPostVoteMap.cs
new file mode 100644
index 0000000000..40d9e9d8bb
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Mapping/Forums/ForumPostVoteMap.cs
@@ -0,0 +1,18 @@
+using System.Data.Entity.ModelConfiguration;
+using SmartStore.Core.Domain.Forums;
+
+namespace SmartStore.Data.Mapping.Forums
+{
+    public partial class ForumPostVoteMap : EntityTypeConfiguration<ForumPostVote>
+    {
+        public ForumPostVoteMap()
+        {
+            ToTable("ForumPostVote");
+
+            HasRequired(fpl => fpl.ForumPost)
+                .WithMany(fp => fp.ForumPostVotes)
+                .HasForeignKey(fpl => fpl.ForumPostId)
+                .WillCascadeOnDelete(true);
+        }
+    }
+}
diff --git a/src/Libraries/SmartStore.Data/Migrations/201810011954195_ForumPostVote.Designer.cs b/src/Libraries/SmartStore.Data/Migrations/201810011954195_ForumPostVote.Designer.cs
new file mode 100644
index 0000000000..df1f55332e
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201810011954195_ForumPostVote.Designer.cs
@@ -0,0 +1,29 @@
+// <auto-generated />
+namespace SmartStore.Data.Migrations
+{
+    using System.CodeDom.Compiler;
+    using System.Data.Entity.Migrations;
+    using System.Data.Entity.Migrations.Infrastructure;
+    using System.Resources;
+    
+    [GeneratedCode("EntityFramework.Migrations", "6.2.0-61023")]
+    public sealed partial class ForumPostVote : IMigrationMetadata
+    {
+        private readonly ResourceManager Resources = new ResourceManager(typeof(ForumPostVote));
+        
+        string IMigrationMetadata.Id
+        {
+            get { return "201810011954195_ForumPostVote"; }
+        }
+        
+        string IMigrationMetadata.Source
+        {
+            get { return null; }
+        }
+        
+        string IMigrationMetadata.Target
+        {
+            get { return Resources.GetString("Target"); }
+        }
+    }
+}
diff --git a/src/Libraries/SmartStore.Data/Migrations/201810011954195_ForumPostVote.cs b/src/Libraries/SmartStore.Data/Migrations/201810011954195_ForumPostVote.cs
new file mode 100644
index 0000000000..843ad1b291
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201810011954195_ForumPostVote.cs
@@ -0,0 +1,35 @@
+namespace SmartStore.Data.Migrations
+{
+    using System;
+    using System.Data.Entity.Migrations;
+    
+    public partial class ForumPostVote : DbMigration
+    {
+        public override void Up()
+        {
+            CreateTable(
+                "dbo.ForumPostVote",
+                c => new
+                    {
+                        Id = c.Int(nullable: false),
+                        ForumPostId = c.Int(nullable: false),
+                        Vote = c.Boolean(nullable: false),
+                    })
+                .PrimaryKey(t => t.Id)
+                .ForeignKey("dbo.CustomerContent", t => t.Id)
+                .ForeignKey("dbo.Forums_Post", t => t.ForumPostId, cascadeDelete: true)
+                .Index(t => t.Id)
+                .Index(t => t.ForumPostId);
+            
+        }
+        
+        public override void Down()
+        {
+            DropForeignKey("dbo.ForumPostVote", "ForumPostId", "dbo.Forums_Post");
+            DropForeignKey("dbo.ForumPostVote", "Id", "dbo.CustomerContent");
+            DropIndex("dbo.ForumPostVote", new[] { "ForumPostId" });
+            DropIndex("dbo.ForumPostVote", new[] { "Id" });
+            DropTable("dbo.ForumPostVote");
+        }
+    }
+}
diff --git a/src/Libraries/SmartStore.Data/Migrations/201810011954195_ForumPostVote.resx b/src/Libraries/SmartStore.Data/Migrations/201810011954195_ForumPostVote.resx
new file mode 100644
index 0000000000..1363d329af
--- /dev/null
+++ b/src/Libraries/SmartStore.Data/Migrations/201810011954195_ForumPostVote.resx
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="Target" xml:space="preserve">
+    <value>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</value>
+  </data>
+  <data name="DefaultSchema" xml:space="preserve">
+    <value>dbo</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs b/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
index b656f275f9..b949a4779a 100644
--- a/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
+++ b/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
@@ -527,6 +527,20 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder)
                 "* Input elements with asterisk are required and have to be filled out.",
                 "* Eingabefelder mit Sternchen sind Pflichfelder und müssen ausgefüllt werden.");
 
+            builder.AddOrUpdate("Forum.Post.Vote.OnlyRegistered",
+                "Only registered users can vote for posts.",
+                "Nur registrierte Benutzer können Beiträge bewerten.");
+
+            builder.AddOrUpdate("Forum.Post.Vote.OwnPostNotAllowed",
+                "You cannot vote for your own post.",
+                "Sie können nicht Ihren eigenen Beitrag bewerten.");
+
+            builder.AddOrUpdate("Forum.Post.Vote.SuccessfullyVoted",
+                "Thank you for your vote.",
+                "Danke für Ihre Bewertung.");
+
+            builder.AddOrUpdate("Common.LikeIt", "I like it", "Gefällt mir");
+            builder.AddOrUpdate("Common.DoNotLikeIt", "I do not like it anymore", "Gefällt mir nicht mehr");
         }
     }
 }
diff --git a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj
index cc9da1dd58..b0d59e0d11 100644
--- a/src/Libraries/SmartStore.Data/SmartStore.Data.csproj
+++ b/src/Libraries/SmartStore.Data/SmartStore.Data.csproj
@@ -147,6 +147,7 @@
     <Compile Include="Mapping\DataExchange\ExportDeploymentMap.cs" />
     <Compile Include="Mapping\Directory\QuantityUnitMap.cs" />
     <Compile Include="Mapping\DataExchange\ExportProfileMap.cs" />
+    <Compile Include="Mapping\Forums\ForumPostVoteMap.cs" />
     <Compile Include="Mapping\Media\MediaStorageMap.cs" />
     <Compile Include="Mapping\Messages\QueuedEmailAttachmentMap.cs" />
     <Compile Include="Mapping\Payments\PaymentMethodMap.cs" />
@@ -627,6 +628,10 @@
     <Compile Include="Migrations\201809261026134_ForumGroupAcl.Designer.cs">
       <DependentUpon>201809261026134_ForumGroupAcl.cs</DependentUpon>
     </Compile>
+    <Compile Include="Migrations\201810011954195_ForumPostVote.cs" />
+    <Compile Include="Migrations\201810011954195_ForumPostVote.Designer.cs">
+      <DependentUpon>201810011954195_ForumPostVote.cs</DependentUpon>
+    </Compile>
     <Compile Include="ObjectContextBase.SaveChanges.cs" />
     <Compile Include="Setup\Builder\ActivityLogTypeMigrator.cs" />
     <Compile Include="Setup\Builder\PermissionMigrator.cs" />
@@ -1127,6 +1132,9 @@
     <EmbeddedResource Include="Migrations\201809261026134_ForumGroupAcl.resx">
       <DependentUpon>201809261026134_ForumGroupAcl.cs</DependentUpon>
     </EmbeddedResource>
+    <EmbeddedResource Include="Migrations\201810011954195_ForumPostVote.resx">
+      <DependentUpon>201810011954195_ForumPostVote.cs</DependentUpon>
+    </EmbeddedResource>
     <EmbeddedResource Include="Sql\Indexes.sql" />
     <EmbeddedResource Include="Sql\StoredProcedures.sql" />
   </ItemGroup>
diff --git a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
index 51bb2e5537..7eac114bea 100644
--- a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
+++ b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
@@ -45,6 +45,7 @@ public partial class BoardsController : PublicControllerBase
         private readonly IGenericAttributeService _genericAttributeService;
         private readonly IStoreMappingService _storeMappingService;
         private readonly IAclService _aclService;
+        private readonly ICustomerContentService _customerContentService;
         private readonly ForumSettings _forumSettings;
         private readonly ForumSearchSettings _searchSettings;
         private readonly CustomerSettings _customerSettings;
@@ -63,6 +64,7 @@ public BoardsController(
             IGenericAttributeService genericAttributeService,
             IStoreMappingService storeMappingService,
             IAclService aclService,
+            ICustomerContentService customerContentService,
             ForumSettings forumSettings,
             ForumSearchSettings searchSettings,
             CustomerSettings customerSettings,
@@ -80,6 +82,7 @@ public BoardsController(
             _genericAttributeService = genericAttributeService;
             _storeMappingService = storeMappingService;
             _aclService = aclService;
+            _customerContentService = customerContentService;
             _forumSettings = forumSettings;
             _searchSettings = searchSettings;
             _customerSettings = customerSettings;
@@ -696,7 +699,7 @@ public ActionResult Topic(int id, int page = 1)
                 
             foreach (var post in posts)
             {
-                var forumPostModel = new ForumPostModel
+                var postModel = new ForumPostModel
                 {
                     Id = post.Id,
                     Published = post.Published,
@@ -717,26 +720,32 @@ public ActionResult Topic(int id, int page = 1)
                     AllowPrivateMessages = _forumSettings.AllowPrivateMessages,
                     SignaturesEnabled = _forumSettings.SignaturesEnabled,
                     FormattedSignature = post.Customer.GetAttribute<string>(SystemCustomerAttributeNames.Signature).FormatForumSignatureText(),
+                    AllowVoting = _forumSettings.AllowCustomersToVoteOnPosts && post.CustomerId != customer.Id
                 };
 
-                forumPostModel.PostCreatedOnStr = _forumSettings.RelativeDateTimeFormattingEnabled
+                if (postModel.AllowVoting)
+                {
+                    postModel.Vote = post.ForumPostVotes.FirstOrDefault(x => x.CustomerId == customer.Id)?.Vote ?? false;
+                }
+
+                postModel.PostCreatedOnStr = _forumSettings.RelativeDateTimeFormattingEnabled
                     ? post.CreatedOnUtc.RelativeFormat(true, "f")
                     : _dateTimeHelper.ConvertToUserTime(post.CreatedOnUtc, DateTimeKind.Utc).ToString("f");
 
-                forumPostModel.Avatar = post.Customer.ToAvatarModel(_genericAttributeService, _pictureService, _customerSettings, _mediaSettings, Url, forumPostModel.CustomerName, true);
+                postModel.Avatar = post.Customer.ToAvatarModel(_genericAttributeService, _pictureService, _customerSettings, _mediaSettings, Url, postModel.CustomerName, true);
 
                 // Location.
-                forumPostModel.ShowCustomersLocation = _customerSettings.ShowCustomersLocation;
+                postModel.ShowCustomersLocation = _customerSettings.ShowCustomersLocation;
                 if (_customerSettings.ShowCustomersLocation)
                 {
                     var countryId = post.Customer.GetAttribute<int>(SystemCustomerAttributeNames.CountryId);
                     var country = _countryService.GetCountryById(countryId);
-                    forumPostModel.CustomerLocation = country != null ? country.GetLocalized(x => x.Name) : string.Empty;
+                    postModel.CustomerLocation = country != null ? country.GetLocalized(x => x.Name) : string.Empty;
                 }
 
                 // Page number is needed for creating post link in _ForumPost partial view.
-                forumPostModel.CurrentTopicPage = page;
-                model.ForumPostModels.Add(forumPostModel);
+                postModel.CurrentTopicPage = page;
+                model.ForumPostModels.Add(postModel);
             }
 
 			CreateForumBreadcrumb(topic: topic);
@@ -1605,6 +1614,64 @@ public ActionResult PostDelete(int id)
             }
         }
 
+        [HttpPost]
+        public ActionResult PostVote(int id, bool vote)
+        {
+            if (!_forumSettings.ForumsEnabled || !_forumSettings.AllowCustomersToVoteOnPosts)
+            {
+                return HttpNotFound();
+            }
+
+            var customer = Services.WorkContext.CurrentCustomer;
+            var post = _forumService.GetPostById(id);
+
+            if (post == null || !_storeMappingService.Authorize(post.ForumTopic.Forum.ForumGroup) || !_aclService.Authorize(post.ForumTopic.Forum.ForumGroup))
+            {
+                return HttpNotFound();
+            }
+
+            if (!_forumSettings.AllowGuestsToVoteOnPosts && customer.IsGuest())
+            {
+                return Json(new { success = false, message = T("Forum.Post.Vote.OnlyRegistered").Text });
+            }
+
+            // Do not allow to vote for own posts.
+            if (post.CustomerId == customer.Id)
+            {
+                return Json(new { success = false, message = T("Forum.Post.Vote.OwnPostNotAllowed").Text });
+            }
+
+            var voteEntity = post.ForumPostVotes.FirstOrDefault(x => x.CustomerId == customer.Id);
+            if (vote)
+            {
+                if (voteEntity == null)
+                {
+                    voteEntity = new ForumPostVote
+                    {
+                        ForumPostId = post.Id,
+                        Vote = true,
+                        CustomerId = customer.Id,
+                        IpAddress = Services.WebHelper.GetCurrentIpAddress()
+                    };
+                    _customerContentService.InsertCustomerContent(voteEntity);
+                }
+                else
+                {
+                    voteEntity.Vote = true;
+                    _customerContentService.UpdateCustomerContent(voteEntity);
+                }
+            }
+            else
+            {
+                if (voteEntity != null)
+                {
+                    _customerContentService.DeleteCustomerContent(voteEntity);
+                }
+            }
+
+            return Json(new { success = true, message = T("Forum.Post.Vote.SuccessfullyVoted").Text });
+        }
+
         #endregion
 
         #region Search
diff --git a/src/Presentation/SmartStore.Web/Models/Boards/ForumPostModel.cs b/src/Presentation/SmartStore.Web/Models/Boards/ForumPostModel.cs
index b7c7806ab8..57ba6d5db5 100644
--- a/src/Presentation/SmartStore.Web/Models/Boards/ForumPostModel.cs
+++ b/src/Presentation/SmartStore.Web/Models/Boards/ForumPostModel.cs
@@ -39,6 +39,9 @@ public partial class ForumPostModel : EntityModelBase
 
         public int CurrentTopicPage { get; set; }
 
+        public bool AllowVoting { get; set; }
+        public bool Vote { get; set; }
+
         public CustomerAvatarModel Avatar { get; set; }
     }
 }
\ No newline at end of file
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ForumPost.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ForumPost.cshtml
index b271913bc1..411d957ad8 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ForumPost.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ForumPost.cshtml
@@ -2,7 +2,7 @@
 @model ForumPostModel
 @Html.Raw("<a name=\"{0}\"></a>".FormatInvariant(Model.Id))
 
-<div class="block block-bordered forum-post card" id="post@(Model.Id)">
+<div class="block block-bordered forum-post card" id="post@(Model.Id)" data-id="@Model.Id">
     <div class="block-title card-header">
         @if (Model.CustomerId > 0)
         {
@@ -114,6 +114,17 @@
                 <i class="fa fa-quote-left"></i>
                 <span>@T("Forum.QuotePost")</span>
             </a>
+            @if (Model.AllowVoting)
+            {
+                <button type="button" class="btn btn-outline-success btn-flat btn-sm post-vote-button post-vote-up@(Model.Vote ? " hide" : "")" value="true">
+                    <i class="fa fa-thumbs-up"></i>
+                    <span>@T("Common.LikeIt")</span>
+                </button>
+                <button type="button" class="btn btn-outline-danger btn-flat btn-sm post-vote-button post-vote-down@(Model.Vote ? "" : " hide")" value="false">
+                    <i class="fa fa-thumbs-down"></i>
+                    <span>@T("Common.DoNotLikeIt")</span>
+                </button>
+            }
         </div>
     </div>
 </div>
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/Topic.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/Topic.cshtml
index ab9b4acda1..a670fe2f87 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/Topic.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/Topic.cshtml
@@ -92,4 +92,31 @@
 
         @pager
     </div>
-}
\ No newline at end of file
+}
+
+<script type="text/javascript">
+	jQuery(document).ready(function () {
+
+		// Post voting.
+		$('button.post-vote-button').on('click', function () {
+            var self = $(this),
+                postId = self.closest('.forum-post').data('id');
+
+            $.ajax({
+                type: 'POST',
+                url: '@Url.Action("PostVote", "Boards")',
+                data: { "id": postId, "vote": self.attr('value') },
+                cache: false,
+                success: function (resp) {
+                    if (resp.success) {
+                        self.closest('div').find(self.hasClass('post-vote-up') ? '.post-vote-down' : '.post-vote-up').show();
+                        self.hide();
+                    }
+
+                    displayNotification(resp.message, resp.success ? 'success' : 'error');
+                }
+            });
+        });
+
+	});
+</script>

From 7c836ab2659f1740635d5a24794355f378bb4579 Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Tue, 2 Oct 2018 02:51:21 +0200
Subject: [PATCH 36/71] Added object-fit css util classes

---
 src/Presentation/SmartStore.Web/Content/shared/_utils.scss | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/Presentation/SmartStore.Web/Content/shared/_utils.scss b/src/Presentation/SmartStore.Web/Content/shared/_utils.scss
index dc11f76300..fe8e282617 100644
--- a/src/Presentation/SmartStore.Web/Content/shared/_utils.scss
+++ b/src/Presentation/SmartStore.Web/Content/shared/_utils.scss
@@ -183,6 +183,11 @@
 	height: auto !important;
 }
 
+.fit-fill       { object-fit: fill; }
+.fit-contain    { object-fit: contain; }
+.fit-cover      { object-fit: cover; }
+.fit-scale-down { object-fit: scale-down; }
+.fit-none       { object-fit: none; }
 
 //
 // Bootstrap overrides and tweaks

From b9307cafa3ea114be85f9fd178e8701e88d01504 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Tue, 2 Oct 2018 10:45:49 +0200
Subject: [PATCH 37/71] Fixes region cannot be selected in checkout when
 entering a billing or shipping address

---
 .../Shared/Partials/_CreateOrUpdateAddress.cshtml | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/src/Presentation/SmartStore.Web/Views/Shared/Partials/_CreateOrUpdateAddress.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/Partials/_CreateOrUpdateAddress.cshtml
index f5ac141f36..ec96afef12 100644
--- a/src/Presentation/SmartStore.Web/Views/Shared/Partials/_CreateOrUpdateAddress.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Shared/Partials/_CreateOrUpdateAddress.cshtml
@@ -81,17 +81,18 @@
 
     @if (Model.CountryEnabled)
     {
+		var fieldPrefix = ViewData.TemplateInfo.HtmlFieldPrefix.NullEmpty() ?? "Address";
         <div class="form-group row">
             @Html.LabelFor(model => model.CountryId, new { @class = "col-{0}-3 col-form-label{1}".FormatInvariant(breakpoint, Model.CountryRequired ? " required" : "") })
             <div class="col-@breakpoint-9">
                 @Html.DropDownList("CountryId", Model.AvailableCountries,
-                new
-                {
-                    @class = "form-control country-input country-selector",
-                    data_region_control_selector = "#Address_StateProvinceId",
-                    data_states_ajax_url = Url.Action("GetStatesByCountryId", "Country"),
-                    data_addEmptyStateIfRequired = "true"
-                })
+				new
+				{
+					@class = "form-control country-input country-selector",
+					data_region_control_selector = "#{0}_StateProvinceId".FormatInvariant(fieldPrefix),
+					data_states_ajax_url = Url.Action("GetStatesByCountryId", "Country"),
+					data_addEmptyStateIfRequired = "true"
+				})
                 @Html.ValidationMessageFor(model => model.CountryId)
             </div>
         </div>

From 4743fd650b22ccd28381c93c0b1eded74c44a2f4 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Tue, 2 Oct 2018 10:54:10 +0200
Subject: [PATCH 38/71] Updated change log

---
 changelog.md | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/changelog.md b/changelog.md
index 44d18966c1..d79f588e5b 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,4 +1,4 @@
-# Release Notes
+# Release Notes
 
 ## SmartStore.NET 3.2
 
@@ -74,6 +74,7 @@
 * Newsletter subscription didn't work when customer privacy setting DisplayGdprConsentOnForms was turned off
 * Fixed social media image detection
 * Fixed redirection of bots when several languages were active
+* Region cannot be selected in checkout when entering a billing or shipping address
 
 
 ## SmartStore.NET 3.1.5

From 249008882e604d24b6685e92a2d5bd2d7739621c Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Tue, 2 Oct 2018 12:41:28 +0200
Subject: [PATCH 39/71] More on forum post voting

---
 .../Migrations/MigrationsConfiguration.cs     | 13 +++++++++++
 .../Models/Settings/ForumSettingsModel.cs     | 10 +++++++--
 .../Administration/Views/Setting/Forum.cshtml | 18 +++++++++++++++
 .../Controllers/BoardsController.cs           | 22 +++++++++++++++++--
 .../Models/Boards/ForumPostModel.cs           |  1 +
 .../Themes/Flex/Content/_forum.scss           | 12 +---------
 .../Views/Boards/Partials/_ForumPost.cshtml   | 13 ++++++++---
 .../SmartStore.Web/Views/Boards/Topic.cshtml  | 12 ++++++++--
 8 files changed, 81 insertions(+), 20 deletions(-)

diff --git a/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs b/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
index b949a4779a..980c0bb4fa 100644
--- a/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
+++ b/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
@@ -539,8 +539,21 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder)
                 "Thank you for your vote.",
                 "Danke für Ihre Bewertung.");
 
+            builder.AddOrUpdate("Common.Liked", "Liked", "Gefällt");
             builder.AddOrUpdate("Common.LikeIt", "I like it", "Gefällt mir");
             builder.AddOrUpdate("Common.DoNotLikeIt", "I do not like it anymore", "Gefällt mir nicht mehr");
+
+            builder.AddOrUpdate("Admin.Configuration.Settings.Forums.AllowCustomersToVoteOnPosts",
+                "Allow customers to vote on posts",
+                "Benutzer können Beiträge bewerten",
+                "Specifies whether customers can vote on posts.",
+                "Legt fest, ob Benutzer Beiträge bewerten können.");
+
+            builder.AddOrUpdate("Admin.Configuration.Settings.Forums.AllowGuestsToVoteOnPosts",
+                "Allow guests to vote on posts",
+                "Gäste können Beiträge bewerten",
+                "Specifies whether guests can vote on posts.",
+                "Legt fest, ob Gäste Beiträge bewerten können.");
         }
     }
 }
diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Settings/ForumSettingsModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Settings/ForumSettingsModel.cs
index 455f58204d..cb1a9ec8ab 100644
--- a/src/Presentation/SmartStore.Web/Administration/Models/Settings/ForumSettingsModel.cs
+++ b/src/Presentation/SmartStore.Web/Administration/Models/Settings/ForumSettingsModel.cs
@@ -35,11 +35,17 @@ public class ForumSettingsModel
         [SmartResourceDisplayName("Admin.Configuration.Settings.Forums.PostsPageSize")]
         public int PostsPageSize { get; set; }
 
+        [SmartResourceDisplayName("Admin.Configuration.Settings.Forums.SearchResultsPageSize")]
+        public int SearchResultsPageSize { get; set; }
+
         [SmartResourceDisplayName("Admin.Configuration.Settings.Forums.AllowSorting")]
         public bool AllowSorting { get; set; }
 
-        [SmartResourceDisplayName("Admin.Configuration.Settings.Forums.SearchResultsPageSize")]
-        public int SearchResultsPageSize { get; set; }
+        [SmartResourceDisplayName("Admin.Configuration.Settings.Forums.AllowCustomersToVoteOnPosts")]
+        public bool AllowCustomersToVoteOnPosts { get; set; }
+
+        [SmartResourceDisplayName("Admin.Configuration.Settings.Forums.AllowGuestsToVoteOnPosts")]
+        public bool AllowGuestsToVoteOnPosts { get; set; }
 
         [SmartResourceDisplayName("Admin.Configuration.Settings.Forums.ForumEditor")]
         public EditorType ForumEditor { get; set; }
diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Setting/Forum.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Setting/Forum.cshtml
index 85efaac0ef..0d1f79d40b 100644
--- a/src/Presentation/SmartStore.Web/Administration/Views/Setting/Forum.cshtml
+++ b/src/Presentation/SmartStore.Web/Administration/Views/Setting/Forum.cshtml
@@ -106,6 +106,24 @@
                 @Html.ValidationMessageFor(model => model.AllowCustomersToManageSubscriptions)
             </td>
         </tr>
+        <tr>
+            <td class="adminTitle">
+                @Html.SmartLabelFor(model => model.AllowCustomersToVoteOnPosts)
+            </td>
+            <td class="adminData">
+                @Html.SettingEditorFor(model => model.AllowCustomersToVoteOnPosts, Html.CheckBoxFor(x => x.AllowCustomersToVoteOnPosts, new { data_toggler_for = "#pnlForumsEnabled .post-voting" }))
+                @Html.ValidationMessageFor(model => model.AllowCustomersToVoteOnPosts)
+            </td>
+        </tr>
+        <tr class="post-voting">
+            <td class="adminTitle">
+                @Html.SmartLabelFor(model => model.AllowGuestsToVoteOnPosts)
+            </td>
+            <td class="adminData">
+                @Html.SettingEditorFor(model => model.AllowGuestsToVoteOnPosts)
+                @Html.ValidationMessageFor(model => model.AllowGuestsToVoteOnPosts)
+            </td>
+        </tr>
         <tr>
             <td class="adminTitle">
                 @Html.SmartLabelFor(model => model.ForumEditor)
diff --git a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
index 7eac114bea..35707cde1d 100644
--- a/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
+++ b/src/Presentation/SmartStore.Web/Controllers/BoardsController.cs
@@ -725,7 +725,15 @@ public ActionResult Topic(int id, int page = 1)
 
                 if (postModel.AllowVoting)
                 {
-                    postModel.Vote = post.ForumPostVotes.FirstOrDefault(x => x.CustomerId == customer.Id)?.Vote ?? false;
+                    if (!_forumSettings.AllowGuestsToVoteOnPosts && customer.IsGuest())
+                    {
+                        postModel.AllowVoting = false;
+                    }
+                    else
+                    {
+                        postModel.Vote = post.ForumPostVotes.FirstOrDefault(x => x.CustomerId == customer.Id)?.Vote ?? false;
+                        postModel.VoteCount = post.ForumPostVotes.Count;
+                    }
                 }
 
                 postModel.PostCreatedOnStr = _forumSettings.RelativeDateTimeFormattingEnabled
@@ -1642,6 +1650,8 @@ public ActionResult PostVote(int id, bool vote)
             }
 
             var voteEntity = post.ForumPostVotes.FirstOrDefault(x => x.CustomerId == customer.Id);
+            var voteCount = post.ForumPostVotes.Count;
+
             if (vote)
             {
                 if (voteEntity == null)
@@ -1654,6 +1664,7 @@ public ActionResult PostVote(int id, bool vote)
                         IpAddress = Services.WebHelper.GetCurrentIpAddress()
                     };
                     _customerContentService.InsertCustomerContent(voteEntity);
+                    ++voteCount;
                 }
                 else
                 {
@@ -1666,10 +1677,17 @@ public ActionResult PostVote(int id, bool vote)
                 if (voteEntity != null)
                 {
                     _customerContentService.DeleteCustomerContent(voteEntity);
+                    --voteCount;
                 }
             }
 
-            return Json(new { success = true, message = T("Forum.Post.Vote.SuccessfullyVoted").Text });
+            return Json(new 
+            {
+                success = true,
+                message = T("Forum.Post.Vote.SuccessfullyVoted").Text,
+                voteCount,
+                voteCountString = voteCount.ToString("N0")
+            });
         }
 
         #endregion
diff --git a/src/Presentation/SmartStore.Web/Models/Boards/ForumPostModel.cs b/src/Presentation/SmartStore.Web/Models/Boards/ForumPostModel.cs
index 57ba6d5db5..5271f12c12 100644
--- a/src/Presentation/SmartStore.Web/Models/Boards/ForumPostModel.cs
+++ b/src/Presentation/SmartStore.Web/Models/Boards/ForumPostModel.cs
@@ -41,6 +41,7 @@ public partial class ForumPostModel : EntityModelBase
 
         public bool AllowVoting { get; set; }
         public bool Vote { get; set; }
+        public int VoteCount { get; set; }
 
         public CustomerAvatarModel Avatar { get; set; }
     }
diff --git a/src/Presentation/SmartStore.Web/Themes/Flex/Content/_forum.scss b/src/Presentation/SmartStore.Web/Themes/Flex/Content/_forum.scss
index 971984f6e3..348b5848eb 100644
--- a/src/Presentation/SmartStore.Web/Themes/Flex/Content/_forum.scss
+++ b/src/Presentation/SmartStore.Web/Themes/Flex/Content/_forum.scss
@@ -92,13 +92,6 @@ $forum-unobstrusive-link-color: #646464;
         }
     }
     .post-content {
-		/*
-	    .functions {
-	        right: 10px;
-	        bottom: 10px;
-	        .fa-quote-left { font-size: 10px;}
-        }
-		*/
         .signature {
 	        position: absolute;
 	        bottom: 10px;
@@ -110,7 +103,7 @@ $forum-unobstrusive-link-color: #646464;
     }
 }
 .post-info .user-info .user-stats, 
-.post-content .posttime {
+.post-content .post-stats {
     font-size: $font-size-xs;
 }
 .posttext .quotefrom {
@@ -122,9 +115,6 @@ $forum-unobstrusive-link-color: #646464;
 .posttext blockquote {
 	margin-bottom: 0;
 }
-.post-content .posttime {
-	margin-bottom: 5px;
-}
 
 /* Forum Search
 ================================================ */
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ForumPost.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ForumPost.cshtml
index 411d957ad8..c1c5cf6cb9 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ForumPost.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/Partials/_ForumPost.cshtml
@@ -85,9 +85,16 @@
             </div>
         </div>
         <div class="post-content col col-sm-10">
-            <div class="posttime text-muted">
-                <span class="pr-1">@T("Forum.Posted"):</span>
-				<span class="stat-value">@Model.PostCreatedOnStr</span>
+            <div class="post-stats text-muted mb-1">
+                <span class="posttime">
+                    <span class="pr-1">@T("Forum.Posted"):</span>
+				    <span class="stat-value">@Model.PostCreatedOnStr</span>
+                </span>
+                <span class="votes@(Model.VoteCount > 0 ? "" : " hide")" title="@T("Common.Liked")">
+                    <span class="pl-1 pr-1">&middot;</span>
+                    <span><i class="fa fa-thumbs-up"></i></span>
+				    <span class="vote-count stat-value">@Model.VoteCount.ToString("N0")</span>
+                </span>
             </div>
             <div class="post-body">
                 <div class="posttext" dir="auto">
diff --git a/src/Presentation/SmartStore.Web/Views/Boards/Topic.cshtml b/src/Presentation/SmartStore.Web/Views/Boards/Topic.cshtml
index a670fe2f87..6596777acb 100644
--- a/src/Presentation/SmartStore.Web/Views/Boards/Topic.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Boards/Topic.cshtml
@@ -100,17 +100,25 @@
 		// Post voting.
 		$('button.post-vote-button').on('click', function () {
             var self = $(this),
-                postId = self.closest('.forum-post').data('id');
+                post = self.closest('.forum-post');
 
             $.ajax({
                 type: 'POST',
                 url: '@Url.Action("PostVote", "Boards")',
-                data: { "id": postId, "vote": self.attr('value') },
+                data: { "id": post.data('id'), "vote": self.attr('value') },
                 cache: false,
                 success: function (resp) {
                     if (resp.success) {
                         self.closest('div').find(self.hasClass('post-vote-up') ? '.post-vote-down' : '.post-vote-up').show();
                         self.hide();
+
+                        // Update counter.
+                        if (resp.voteCount > 0) {
+                            post.find('.votes').show().find('.vote-count').text(resp.voteCountString);
+                        }
+                        else {
+                            post.find('.votes').text(resp.voteCountString).hide();
+                        }
                     }
 
                     displayNotification(resp.message, resp.success ? 'success' : 'error');

From 73d14c2224238b741873b78286d06d7be1f38223 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Tue, 2 Oct 2018 12:49:42 +0200
Subject: [PATCH 40/71] Fixed typos

---
 .../Migrations/MigrationsConfiguration.cs           | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs b/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
index 980c0bb4fa..4449fab2e9 100644
--- a/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
+++ b/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
@@ -554,6 +554,19 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder)
                 "Gäste können Beiträge bewerten",
                 "Specifies whether guests can vote on posts.",
                 "Legt fest, ob Gäste Beiträge bewerten können.");
+
+            // Typos.
+            builder.AddOrUpdate("Admin.Promotions.Discounts.Requirements")
+                .Value("de", "Voraussetzungen");
+            builder.AddOrUpdate("Admin.Promotions.Discounts.Requirements.DiscountRequirementType")
+                .Value("de", "Typ der Voraussetzung");
+            builder.AddOrUpdate("Admin.Promotions.Discounts.Requirements.DiscountRequirementType.Hint")
+                .Value("de", "Voraussetzungen für den Rabatt");
+            builder.AddOrUpdate("Admin.Promotions.Discounts.Requirements.Remove")
+                .Value("de", "Voraussetzung für den Rabatt entfernen");
+            builder.AddOrUpdate("Admin.Promotions.Discounts.Requirements.SaveBeforeEdit")
+                .Value("de", "Sie müssen den Rabatt zunächst speichern, bevor Sie Voraussetzungen für seine Anwendung festlegen können");
+
         }
     }
 }

From 9f26066ca0217779ee6c40a0a8108ad0d41c8c79 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Tue, 2 Oct 2018 14:29:51 +0200
Subject: [PATCH 41/71] Fixed non-localized strings

---
 .../Administration/Controllers/ProductController.cs    | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs
index 8466df6cd5..41dacdba20 100644
--- a/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs
+++ b/src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs
@@ -3946,13 +3946,15 @@ public ActionResult CombinationExistenceNote(int productId, ProductVariantQuery
 
         public ActionResult DeleteDownloadVersion(int downloadId, int productId)
         {
-            if (downloadId == 0)
-                NotifySuccess("Der Download wurde nicht gefunden.");
-
             var download = _downloadService.GetDownloadById(downloadId);
+            if (download == null)
+            {
+                return HttpNotFound();
+            }
+
             _downloadService.DeleteDownload(download);
 
-            NotifySuccess("Der Download wurde erfolgreich gelöscht.");
+            NotifySuccess(T("Admin.Common.TaskSuccessfullyProcessed"));
 
             return RedirectToAction("Edit", new { id = productId });
         }

From d487e6f9483e3e1ae7c4fda2396612430d1e2a01 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Tue, 2 Oct 2018 15:06:36 +0200
Subject: [PATCH 42/71] Votes of forum posts are customer content thus subject
 to GDPR

---
 .../SmartStore.Services/Customers/GdprTool.cs | 13 ++++++++--
 .../Messages/MessageModelProvider.cs          | 25 ++++++++++++++++++-
 2 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/src/Libraries/SmartStore.Services/Customers/GdprTool.cs b/src/Libraries/SmartStore.Services/Customers/GdprTool.cs
index b8a52c9666..1c2cc5d174 100644
--- a/src/Libraries/SmartStore.Services/Customers/GdprTool.cs
+++ b/src/Libraries/SmartStore.Services/Customers/GdprTool.cs
@@ -25,6 +25,7 @@
 using System.Net;
 using System.Net.Sockets;
 using SmartStore.Core.Logging;
+using SmartStore.Core.Domain.Forums;
 
 namespace SmartStore.Services.Customers
 {
@@ -151,8 +152,16 @@ public virtual IDictionary<string, object> ExportCustomer(Customer customer)
 					model["ForumPosts"] = forumPosts.Select(x => _messageModelProvider.CreateModelPart(x, true)).ToList();
 				}
 
-				// Product reviews
-				var productReviews = customer.CustomerContent.OfType<ProductReview>();
+                // Forum post votes
+                var forumPostVotes = customer.CustomerContent.OfType<ForumPostVote>();
+                if (forumPostVotes.Any())
+                {
+                    ignoreMemberNames = new string[] { "CustomerId", "UpdatedOn" };
+                    model["ForumPostVotes"] = forumPostVotes.Select(x => _messageModelProvider.CreateModelPart(x, true, ignoreMemberNames)).ToList();
+                }
+
+                // Product reviews
+                var productReviews = customer.CustomerContent.OfType<ProductReview>();
 				if (productReviews.Any())
 				{
 					model["ProductReviews"] = productReviews.Select(x => _messageModelProvider.CreateModelPart(x, true)).ToList();
diff --git a/src/Libraries/SmartStore.Services/Messages/MessageModelProvider.cs b/src/Libraries/SmartStore.Services/Messages/MessageModelProvider.cs
index ad818b0636..3485c46262 100644
--- a/src/Libraries/SmartStore.Services/Messages/MessageModelProvider.cs
+++ b/src/Libraries/SmartStore.Services/Messages/MessageModelProvider.cs
@@ -258,6 +258,9 @@ public virtual void AddModelPart(object part, MessageContext messageContext, str
 				case ForumPost x:
 					modelPart = CreateModelPart(x, messageContext);
 					break;
+                case ForumPostVote x:
+                    modelPart = CreateModelPart(x, messageContext);
+                    break;
 				case Forum x:
 					modelPart = CreateModelPart(x, messageContext);
 					break;
@@ -887,7 +890,27 @@ protected virtual object CreateModelPart(ForumPost part, MessageContext messageC
 			return m;
 		}
 
-		protected virtual object CreateModelPart(Forum part, MessageContext messageContext)
+        protected virtual object CreateModelPart(ForumPostVote part, MessageContext messageContext)
+        {
+            Guard.NotNull(messageContext, nameof(messageContext));
+            Guard.NotNull(part, nameof(part));
+
+            var m = new Dictionary<string, object>
+            {
+                { "ForumPostId", part.ForumPostId },
+                { "Vote", part.Vote },
+                { "TopicId", part.ForumPost.TopicId },
+                { "TopicSubject", part.ForumPost.ForumTopic.Subject.NullEmpty() },
+            };
+
+            ApplyCustomerContentPart(m, part, messageContext);
+
+            PublishModelPartCreatedEvent(part, m);
+
+            return m;
+        }
+
+        protected virtual object CreateModelPart(Forum part, MessageContext messageContext)
 		{
 			Guard.NotNull(messageContext, nameof(messageContext));
 			Guard.NotNull(part, nameof(part));

From 233fbcffaa535f66721a255193650ae9dce93803 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Tue, 2 Oct 2018 20:38:21 +0200
Subject: [PATCH 43/71] Resolves #1517 Creating a manufacturer throws an
 exception

---
 changelog.md                                                    | 1 +
 .../Administration/Models/Catalog/ManufacturerModel.cs          | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/changelog.md b/changelog.md
index d79f588e5b..4a7e2926b1 100644
--- a/changelog.md
+++ b/changelog.md
@@ -23,6 +23,7 @@
 	* Added option to display a captcha on forum pages when creating or replying to a topic.
 	* #417 Restrict forum groups to specific customer roles.
 	* Added published property to forum topic and post.
+	* Added voting for forum posts.
 	* Several performance improvements.
 * **MegaSearch**:
 	* Supports searching for forum posts.
diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Catalog/ManufacturerModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Catalog/ManufacturerModel.cs
index 9642a98edb..727ac92048 100644
--- a/src/Presentation/SmartStore.Web/Administration/Models/Catalog/ManufacturerModel.cs
+++ b/src/Presentation/SmartStore.Web/Administration/Models/Catalog/ManufacturerModel.cs
@@ -53,7 +53,7 @@ public ManufacturerModel()
 
         [UIHint("Picture")]
         [SmartResourceDisplayName("Admin.Catalog.Manufacturers.Fields.Picture")]
-        public int PictureId { get; set; }
+        public int? PictureId { get; set; }
 
         [SmartResourceDisplayName("Admin.Catalog.Manufacturers.Fields.PageSize")]
         public int? PageSize { get; set; }

From 94cf628a31bb9bd2399a99a37e5d3458eac42bf6 Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Tue, 2 Oct 2018 19:37:51 +0200
Subject: [PATCH 44/71] Code convention

---
 .../SmartStore.Core/Domain/Catalog/Product.cs | 39 +++++++------------
 1 file changed, 14 insertions(+), 25 deletions(-)

diff --git a/src/Libraries/SmartStore.Core/Domain/Catalog/Product.cs b/src/Libraries/SmartStore.Core/Domain/Catalog/Product.cs
index a4bc4c5251..41a35ad433 100644
--- a/src/Libraries/SmartStore.Core/Domain/Catalog/Product.cs
+++ b/src/Libraries/SmartStore.Core/Domain/Catalog/Product.cs
@@ -22,32 +22,21 @@ public partial class Product : BaseEntity, IAuditable, ISoftDeletable, ILocalize
 	{
 		#region static
 
-		private static readonly HashSet<string> _visibilityAffectingProductProps = new HashSet<string>();
-
-		static Product()
-		{
-			AddPropsToSet(_visibilityAffectingProductProps,
-				x => x.AvailableEndDateTimeUtc,
-				x => x.AvailableStartDateTimeUtc,
-				x => x.Deleted,
-				x => x.LowStockActivityId,
-				x => x.LimitedToStores,
-				x => x.ManageInventoryMethodId,
-				x => x.MinStockQuantity,
-				x => x.Published,
-				x => x.SubjectToAcl,
-				x => x.VisibleIndividually);
-		}
-
-		static void AddPropsToSet(HashSet<string> props, params Expression<Func<Product, object>>[] lambdas)
+		private static readonly HashSet<string> _visibilityAffectingProductProps = new HashSet<string>
 		{
-			foreach (var lambda in lambdas)
-			{
-				props.Add(lambda.ExtractPropertyInfo().Name);
-			}
-		}
-
-		public static HashSet<string> GetVisibilityAffectingPropertyNames()
+			nameof(Product.AvailableEndDateTimeUtc),
+			nameof(Product.AvailableStartDateTimeUtc),
+			nameof(Product.Deleted),
+			nameof(Product.LowStockActivityId),
+			nameof(Product.LimitedToStores),
+			nameof(Product.ManageInventoryMethodId),
+			nameof(Product.MinStockQuantity),
+			nameof(Product.Published),
+			nameof(Product.SubjectToAcl),
+			nameof(Product.VisibleIndividually)
+		};
+
+		public static IReadOnlyCollection<string> GetVisibilityAffectingPropertyNames()
 		{
 			return _visibilityAffectingProductProps;
 		}

From 4c278344f65451f2bb662396031535cbb0bd0ec9 Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Wed, 3 Oct 2018 03:31:58 +0200
Subject: [PATCH 45/71] Minor refactoring

---
 .../Domain/Catalog/SpecificationAttributeOption.cs       | 2 +-
 .../UI/Blocks/BlockHandlerBase.cs                        | 2 +-
 .../SmartStore.Web.Framework/UI/Blocks/IBlockHandler.cs  | 9 ++++++++-
 3 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/src/Libraries/SmartStore.Core/Domain/Catalog/SpecificationAttributeOption.cs b/src/Libraries/SmartStore.Core/Domain/Catalog/SpecificationAttributeOption.cs
index 64827d8ce4..47b5a55cef 100644
--- a/src/Libraries/SmartStore.Core/Domain/Catalog/SpecificationAttributeOption.cs
+++ b/src/Libraries/SmartStore.Core/Domain/Catalog/SpecificationAttributeOption.cs
@@ -50,7 +50,7 @@ public partial class SpecificationAttributeOption : BaseEntity, ILocalizedEntity
 		public virtual SpecificationAttribute SpecificationAttribute { get; set; }
 
         /// <summary>
-        /// Gets or sets the product specification attribute
+        /// Gets or sets the product specification attributes
         /// </summary>
 		[DataMember]
 		public virtual ICollection<ProductSpecificationAttribute> ProductSpecificationAttributes
diff --git a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockHandlerBase.cs b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockHandlerBase.cs
index 0d395920de..b94ab59af3 100644
--- a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockHandlerBase.cs
+++ b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockHandlerBase.cs
@@ -25,7 +25,7 @@ public virtual T Create(IBlockEntity entity)
 			return Activator.CreateInstance<T>();
 		}
 
-		public virtual T Load(IBlockEntity entity, bool editMode)
+		public virtual T Load(IBlockEntity entity, StoryViewMode viewMode)
 		{
 			Guard.NotNull(entity, nameof(entity));
 
diff --git a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockHandler.cs b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockHandler.cs
index 5032cb037e..370a4e1b42 100644
--- a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockHandler.cs
+++ b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockHandler.cs
@@ -4,6 +4,13 @@
 
 namespace SmartStore.Web.Framework.UI.Blocks
 {
+	public enum StoryViewMode
+	{
+		Public,
+		Preview,
+		Edit
+	}
+
 	public interface IBlockHandler
 	{
 		void Render(IBlockContainer element, string[] templates, HtmlHelper htmlHeper);
@@ -13,7 +20,7 @@ public interface IBlockHandler
 	public interface IBlockHandler<T> : IBlockHandler where T : IBlock
 	{
 		T Create(IBlockEntity entity);
-		T Load(IBlockEntity entity, bool editMode);
+		T Load(IBlockEntity entity, StoryViewMode viewMode);
 		void Save(T block, IBlockEntity entity);
 	}
 }

From 512fd4c993bbab113dff3b525882c78a97813b79 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Wed, 3 Oct 2018 11:16:17 +0200
Subject: [PATCH 46/71] SQL CE: Fixes SqlCeException in
 CatalogSearchQueryAliasMapper. Resolves #1516.

---
 .../Search/Catalog/Modelling/CatalogSearchQueryAliasMapper.cs   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/Libraries/SmartStore.Services/Search/Catalog/Modelling/CatalogSearchQueryAliasMapper.cs b/src/Libraries/SmartStore.Services/Search/Catalog/Modelling/CatalogSearchQueryAliasMapper.cs
index 67c3ad8337..6fbc08bc10 100644
--- a/src/Libraries/SmartStore.Services/Search/Catalog/Modelling/CatalogSearchQueryAliasMapper.cs
+++ b/src/Libraries/SmartStore.Services/Search/Catalog/Modelling/CatalogSearchQueryAliasMapper.cs
@@ -70,7 +70,7 @@ protected string CreateOptionKey(string prefix, int languageId, int optionId)
 		protected void CachedLocalizedAlias(string localeKeyGroup, Action<LocalizedProperty> caching)
 		{
 			_localizedPropertyRepository.TableUntracked
-				.Where(x => x.LocaleKeyGroup == localeKeyGroup && x.LocaleKey == "Alias" && x.LocaleValue != null && x.LocaleValue != string.Empty)
+				.Where(x => x.LocaleKeyGroup == localeKeyGroup && x.LocaleKey == "Alias" && x.LocaleValue != null)
 				.ToList()
 				.ForEach(caching);
 		}

From daf9a9cf9ae71fee77a34a0ff56f0f67a6dbb0f7 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Wed, 3 Oct 2018 11:20:51 +0200
Subject: [PATCH 47/71] SQL CE: DropIndex fails during installation

---
 .../SmartStore.Data/Migrations/201609201852449_log4net.cs      | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/Libraries/SmartStore.Data/Migrations/201609201852449_log4net.cs b/src/Libraries/SmartStore.Data/Migrations/201609201852449_log4net.cs
index 640f6fca9e..5eda541bc0 100644
--- a/src/Libraries/SmartStore.Data/Migrations/201609201852449_log4net.cs
+++ b/src/Libraries/SmartStore.Data/Migrations/201609201852449_log4net.cs
@@ -22,7 +22,8 @@ public override void Up()
                 else
                 {
                     Sql(@"SET LOCK_TIMEOUT 20000;");
-                    DropIndex("Log", "IX_Log_ContentHash");
+                    // SQL CE: DropIndex fails during installation, IF EXISTS not supported.
+                    //DropIndex("Log", "IX_Log_ContentHash");
                     Sql(@"DELETE FROM Log;");
                 }
             }

From b72df747c3870c85c0b486da4b1074a616185a90 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Thu, 4 Oct 2018 09:30:15 +0200
Subject: [PATCH 48/71] More on SqlCeException in CatalogSearchQueryAliasMapper
 fix

---
 .../Modelling/CatalogSearchQueryAliasMapper.cs      | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/src/Libraries/SmartStore.Services/Search/Catalog/Modelling/CatalogSearchQueryAliasMapper.cs b/src/Libraries/SmartStore.Services/Search/Catalog/Modelling/CatalogSearchQueryAliasMapper.cs
index 6fbc08bc10..be969584e7 100644
--- a/src/Libraries/SmartStore.Services/Search/Catalog/Modelling/CatalogSearchQueryAliasMapper.cs
+++ b/src/Libraries/SmartStore.Services/Search/Catalog/Modelling/CatalogSearchQueryAliasMapper.cs
@@ -69,10 +69,15 @@ protected string CreateOptionKey(string prefix, int languageId, int optionId)
 
 		protected void CachedLocalizedAlias(string localeKeyGroup, Action<LocalizedProperty> caching)
 		{
-			_localizedPropertyRepository.TableUntracked
-				.Where(x => x.LocaleKeyGroup == localeKeyGroup && x.LocaleKey == "Alias" && x.LocaleValue != null)
-				.ToList()
-				.ForEach(caching);
+            var properties = _localizedPropertyRepository.TableUntracked
+                .Where(x => x.LocaleKeyGroup == localeKeyGroup && x.LocaleKey == "Alias")
+                .ToList();
+
+            // SQL CE: leads to an error when checked in the query.
+            properties
+                .Where(x => !string.IsNullOrWhiteSpace(x.LocaleValue))
+                .ToList()
+                .ForEach(caching);
 		}
 
 		#region Specification Attributes

From 80d528eeae0bc1d0c24038d8809148308f4b387f Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Thu, 4 Oct 2018 12:15:11 +0200
Subject: [PATCH 49/71] Resolves #1515 Poll: Add result tab with a list of
 answers and customers for a poll

---
 changelog.md                                  |   3 +-
 .../Migrations/MigrationsConfiguration.cs     |   2 +
 .../SmartStore.Services/Polls/IPollService.cs |   9 ++
 .../SmartStore.Services/Polls/PollService.cs  |  23 ++++
 .../Controllers/PollController.cs             | 106 ++++++++++++------
 .../Administration/Models/Polls/PollModel.cs  |   3 +
 .../Models/Polls/PollVotingRecordModel.cs     |  28 +++++
 .../Administration/SmartStore.Admin.csproj    |   1 +
 .../Views/Poll/_CreateOrUpdate.cshtml         |  54 ++++++---
 9 files changed, 183 insertions(+), 46 deletions(-)
 create mode 100644 src/Presentation/SmartStore.Web/Administration/Models/Polls/PollVotingRecordModel.cs

diff --git a/changelog.md b/changelog.md
index 4a7e2926b1..58e3aa514c 100644
--- a/changelog.md
+++ b/changelog.md
@@ -30,7 +30,8 @@
 	* #1172 Option to display related search terms on search page.
 * Customer avatar: Letter with colored background if no avatar image was uploaded.
 * Viveum: Supports payment via "Virtual Account Brands" like PayPal.
-* Added options for alternating price display (in badges)
+* Added options for alternating price display (in badges).
+* #1515 Poll: Add result tab with a list of answers and customers for a poll
 
 ### Improvements
 * (Perf) Significantly increased query performance for products with a lot of category assignments (> 10).
diff --git a/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs b/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
index 4449fab2e9..c3970d15b8 100644
--- a/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
+++ b/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
@@ -567,6 +567,8 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder)
             builder.AddOrUpdate("Admin.Promotions.Discounts.Requirements.SaveBeforeEdit")
                 .Value("de", "Sie müssen den Rabatt zunächst speichern, bevor Sie Voraussetzungen für seine Anwendung festlegen können");
 
+            builder.AddOrUpdate("Common.Voting", "Voting", "Abstimmung");
+            builder.AddOrUpdate("Common.Answer", "Answer", "Antwort");
         }
     }
 }
diff --git a/src/Libraries/SmartStore.Services/Polls/IPollService.cs b/src/Libraries/SmartStore.Services/Polls/IPollService.cs
index fb5929cf51..bdf19bab73 100644
--- a/src/Libraries/SmartStore.Services/Polls/IPollService.cs
+++ b/src/Libraries/SmartStore.Services/Polls/IPollService.cs
@@ -72,5 +72,14 @@ public partial interface IPollService
         /// <param name="customerId">Customer identifier</param>
         /// <returns>Result</returns>
         bool AlreadyVoted(int pollId, int customerId);
+
+        /// <summary>
+        /// Get voting records for a poll.
+        /// </summary>
+        /// <param name="pollId">Poll identifier.</param>
+        /// <param name="pageIndex">Page index.</param>
+        /// <param name="pageSize">Page size.</param>
+        /// <returns>List of voting records.</returns>
+        IPagedList<PollVotingRecord> GetVotingRecords(int pollId, int pageIndex, int pageSize);
     }
 }
diff --git a/src/Libraries/SmartStore.Services/Polls/PollService.cs b/src/Libraries/SmartStore.Services/Polls/PollService.cs
index 327d3f3075..e12cb2f6af 100644
--- a/src/Libraries/SmartStore.Services/Polls/PollService.cs
+++ b/src/Libraries/SmartStore.Services/Polls/PollService.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Generic;
 using System.Linq;
 using SmartStore.Core;
 using SmartStore.Core.Caching;
@@ -164,5 +165,27 @@ join pvr in _pollVotingRecords.Table on pa.Id equals pvr.PollAnswerId
                           select pvr).Count() > 0;
             return result;
         }
+
+        public virtual IPagedList<PollVotingRecord> GetVotingRecords(int pollId, int pageIndex, int pageSize)
+        {
+            if (pollId == 0)
+            {
+                return new PagedList<PollVotingRecord>(new List<PollVotingRecord>(), pageIndex, pageSize);
+            }
+
+            var query =
+                from pa in _pollAnswerRepository.TableUntracked
+                join pvr in _pollVotingRecords.TableUntracked on pa.Id equals pvr.PollAnswerId
+                where pa.PollId == pollId
+                orderby pa.DisplayOrder, pvr.CreatedOnUtc descending
+                select pvr;
+
+            query = query
+                .Expand(x => x.Customer)
+                .Expand(x => x.PollAnswer);
+
+            var votings = new PagedList<PollVotingRecord>(query, pageIndex, pageSize);
+            return votings;
+        }
     }
 }
diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/PollController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/PollController.cs
index a01316b5fd..3825a02d75 100644
--- a/src/Presentation/SmartStore.Web/Administration/Controllers/PollController.cs
+++ b/src/Presentation/SmartStore.Web/Administration/Controllers/PollController.cs
@@ -3,56 +3,54 @@
 using System.Web.Mvc;
 using SmartStore.Admin.Models.Polls;
 using SmartStore.Core.Domain.Common;
+using SmartStore.Core.Domain.Customers;
 using SmartStore.Core.Domain.Polls;
+using SmartStore.Services.Customers;
 using SmartStore.Services.Helpers;
 using SmartStore.Services.Localization;
 using SmartStore.Services.Polls;
 using SmartStore.Services.Security;
 using SmartStore.Services.Stores;
+using SmartStore.Web.Framework;
 using SmartStore.Web.Framework.Controllers;
 using SmartStore.Web.Framework.Filters;
 using SmartStore.Web.Framework.Security;
 using Telerik.Web.Mvc;
-using SmartStore.Web.Framework;
 
 namespace SmartStore.Admin.Controllers
 {
-	[AdminAuthorize]
+    [AdminAuthorize]
     public class PollController : AdminControllerBase
 	{
-		#region Fields
-
         private readonly IPollService _pollService;
         private readonly ILanguageService _languageService;
         private readonly IDateTimeHelper _dateTimeHelper;
-        private readonly ILocalizationService _localizationService;
         private readonly IPermissionService _permissionService;
         private readonly AdminAreaSettings _adminAreaSettings;
 		private readonly IStoreService _storeService;
 		private readonly IStoreMappingService _storeMappingService;
-
-		#endregion
-
-		#region Constructors
-
-        public PollController(IPollService pollService, ILanguageService languageService,
-            IDateTimeHelper dateTimeHelper, ILocalizationService localizationService,
-            IPermissionService permissionService, AdminAreaSettings adminAreaSettings,
+        private readonly CustomerSettings _customerSettings;
+
+        public PollController(
+            IPollService pollService,
+            ILanguageService languageService,
+            IDateTimeHelper dateTimeHelper,
+            IPermissionService permissionService,
+            AdminAreaSettings adminAreaSettings,
 			IStoreService storeService,
-			IStoreMappingService storeMappingService)
+			IStoreMappingService storeMappingService,
+            CustomerSettings customerSettings)
         {
-            this._pollService = pollService;
-            this._languageService = languageService;
-            this._dateTimeHelper = dateTimeHelper;
-            this._localizationService = localizationService;
-            this._permissionService = permissionService;
-            this._adminAreaSettings = adminAreaSettings;
-			this._storeService = storeService;
-			this._storeMappingService = storeMappingService;
+            _pollService = pollService;
+            _languageService = languageService;
+            _dateTimeHelper = dateTimeHelper;
+            _permissionService = permissionService;
+            _adminAreaSettings = adminAreaSettings;
+			_storeService = storeService;
+			_storeMappingService = storeMappingService;
+            _customerSettings = customerSettings;
 		}
 
-		#endregion 
-
 		#region Utilities
 
 		private void PreparePollModel(PollModel model, Poll poll, bool excludeProperties)
@@ -65,6 +63,8 @@ private void PreparePollModel(PollModel model, Poll poll, bool excludeProperties
 			}
 
 			model.AvailableStores = _storeService.GetAllStores().ToSelectListItems(model.SelectedStoreIds);
+            model.UsernamesEnabled = _customerSettings.UsernamesEnabled;
+            model.GridPageSize = _adminAreaSettings.GridPageSize;
 		}
 
 		#endregion Utilities
@@ -170,11 +170,11 @@ public ActionResult Create(PollModel model, bool continueEditing)
 
 				SaveStoreMappings(poll, model);
 
-                NotifySuccess(_localizationService.GetResource("Admin.ContentManagement.Polls.Added"));
+                NotifySuccess(T("Admin.ContentManagement.Polls.Added"));
                 return continueEditing ? RedirectToAction("Edit", new { id = poll.Id }) : RedirectToAction("List");
             }
 
-            //If we got this far, something failed, redisplay form
+            // If we got this far, something failed, redisplay form.
             ViewBag.AllLanguages = _languageService.GetAllLanguages(true);
 			
 			PreparePollModel(model, null, true);
@@ -221,11 +221,11 @@ public ActionResult Edit(PollModel model, bool continueEditing)
 
 				SaveStoreMappings(poll, model);
 
-                NotifySuccess(_localizationService.GetResource("Admin.ContentManagement.Polls.Updated"));
+                NotifySuccess(T("Admin.ContentManagement.Polls.Updated"));
                 return continueEditing ? RedirectToAction("Edit", new { id = poll.Id }) : RedirectToAction("List");
             }
 
-            //If we got this far, something failed, redisplay form
+            // If we got this far, something failed, redisplay form.
             ViewBag.AllLanguages = _languageService.GetAllLanguages(true);
 
 			PreparePollModel(model, poll, true);
@@ -245,7 +245,7 @@ public ActionResult DeleteConfirmed(int id)
             
             _pollService.DeletePoll(poll);
 
-            NotifySuccess(_localizationService.GetResource("Admin.ContentManagement.Polls.Deleted"));
+            NotifySuccess(T("Admin.ContentManagement.Polls.Deleted"));
             return RedirectToAction("List");
         }
 
@@ -291,7 +291,6 @@ public ActionResult PollAnswers(int pollId, GridCommand command)
             };
         }
 
-
         [GridAction(EnableCustomBinding = true)]
         public ActionResult PollAnswerUpdate(PollAnswerModel model, GridCommand command)
         {
@@ -301,7 +300,7 @@ public ActionResult PollAnswerUpdate(PollAnswerModel model, GridCommand command)
 			{
 				if (!ModelState.IsValid)
 				{
-					var modelStateErrors = this.ModelState.Values.SelectMany(x => x.Errors).Select(x => x.ErrorMessage);
+					var modelStateErrors = ModelState.Values.SelectMany(x => x.Errors).Select(x => x.ErrorMessage);
 					return Content(modelStateErrors.FirstOrDefault());
 				}
 
@@ -339,7 +338,6 @@ public ActionResult PollAnswerAdd(int pollId, PollAnswerModel model, GridCommand
             return PollAnswers(pollId, command);
         }
 
-
         [GridAction(EnableCustomBinding = true)]
         public ActionResult PollAnswerDelete(int id, GridCommand command)
         {
@@ -355,5 +353,49 @@ public ActionResult PollAnswerDelete(int id, GridCommand command)
         }
 
         #endregion
+
+        #region Voting records
+
+        [HttpPost, GridAction(EnableCustomBinding = true)]
+        public ActionResult VotingRecords(int pollId, GridCommand command)
+        {
+            var model = new GridModel<PollVotingRecordModel>();
+
+            if (_permissionService.Authorize(StandardPermissionProvider.ManagePolls))
+            {
+                var guestString = T("Admin.Customers.Guest").Text;
+                var votings = _pollService.GetVotingRecords(pollId, command.Page - 1, command.PageSize);
+
+                model.Data = votings.Select(x =>
+                {
+                    var votingModel = new PollVotingRecordModel
+                    {
+                        Id = x.Id,
+                        CustomerId = x.CustomerId,
+                        IsGuest = x.Customer.IsGuest(),
+                        CreatedOn = _dateTimeHelper.ConvertToUserTime(x.CreatedOnUtc, DateTimeKind.Utc),
+                        AnswerName = x.PollAnswer.Name,
+                        Username = x.Customer.Username,
+                        FullName = x.Customer.GetFullName()
+                    };
+
+                    votingModel.Email = x.Customer.Email.HasValue() ? x.Customer.Email : (votingModel.IsGuest ? guestString : "".NaIfEmpty());
+
+                    return votingModel;
+                });
+
+                model.Total = votings.TotalCount;
+            }
+            else
+            {
+                model.Data = Enumerable.Empty<PollVotingRecordModel>();
+
+                NotifyAccessDenied();
+            }
+
+            return new JsonResult { Data = model };
+        }
+
+        #endregion
     }
 }
diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Polls/PollModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Polls/PollModel.cs
index ca5a995cde..7638748736 100644
--- a/src/Presentation/SmartStore.Web/Administration/Models/Polls/PollModel.cs
+++ b/src/Presentation/SmartStore.Web/Administration/Models/Polls/PollModel.cs
@@ -12,6 +12,9 @@ namespace SmartStore.Admin.Models.Polls
     [Validator(typeof(PollValidator))]
     public class PollModel : EntityModelBase, IStoreSelector
     {
+        public bool UsernamesEnabled { get; set; }
+        public int GridPageSize { get; set; }
+
         [SmartResourceDisplayName("Admin.ContentManagement.Polls.Fields.Language")]
         public int LanguageId { get; set; }
 
diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Polls/PollVotingRecordModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Polls/PollVotingRecordModel.cs
new file mode 100644
index 0000000000..b504fbe55a
--- /dev/null
+++ b/src/Presentation/SmartStore.Web/Administration/Models/Polls/PollVotingRecordModel.cs
@@ -0,0 +1,28 @@
+using System;
+using SmartStore.Web.Framework;
+using SmartStore.Web.Framework.Modelling;
+
+namespace SmartStore.Admin.Models.Polls
+{
+    public class PollVotingRecordModel : EntityModelBase
+    {
+        public int CustomerId { get; set; }
+        public bool IsGuest { get; set; }
+
+        [SmartResourceDisplayName("Common.CreatedOn")]
+        public DateTime CreatedOn { get; set; }
+
+        [SmartResourceDisplayName("Common.Answer")]
+        public string AnswerName { get; set; }
+
+        [SmartResourceDisplayName("Admin.Customers.Customers.Fields.Email")]
+        public string Email { get; set; }
+
+        [SmartResourceDisplayName("Admin.Customers.Customers.Fields.Username")]
+        public string Username { get; set; }
+
+        [SmartResourceDisplayName("Admin.Customers.Customers.Fields.FullName")]
+        public string FullName { get; set; }
+
+    }
+}
\ No newline at end of file
diff --git a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj
index d12a93a5f4..1b53de7ab0 100644
--- a/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj
+++ b/src/Presentation/SmartStore.Web/Administration/SmartStore.Admin.csproj
@@ -296,6 +296,7 @@
     <Compile Include="Models\Plugins\LicensePluginModel.cs" />
     <Compile Include="Models\Plugins\LocalPluginsModel.cs" />
     <Compile Include="Models\Plugins\ProviderModelList.cs" />
+    <Compile Include="Models\Polls\PollVotingRecordModel.cs" />
     <Compile Include="Models\Settings\ForumSearchSettingsModel.cs" />
     <Compile Include="Models\Settings\PaymentSettingsModel.cs" />
     <Compile Include="Models\Settings\SearchSettingsModel.cs" />
diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Poll/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Poll/_CreateOrUpdate.cshtml
index 3dd7be83a7..b0688dcb15 100644
--- a/src/Presentation/SmartStore.Web/Administration/Views/Poll/_CreateOrUpdate.cshtml
+++ b/src/Presentation/SmartStore.Web/Administration/Views/Poll/_CreateOrUpdate.cshtml
@@ -1,14 +1,15 @@
-@model PollModel
-@using Telerik.Web.Mvc.UI;
+@using Telerik.Web.Mvc.UI;
+@model PollModel
+
 @Html.ValidationSummary(true)
 @Html.HiddenFor(model => model.Id)
 @Html.SmartStore().TabStrip().Name("poll-edit").Style(TabsStyle.Material).Items(x =>
 {
     x.Add().Text(T("Admin.ContentManagement.Polls.Info").Text).Content(TabInfo()).Selected(true);
     x.Add().Text(T("Admin.ContentManagement.Polls.Answers").Text).Content(TabAnswers());
+    x.Add().Text(T("Common.Voting").Text).Content(TabVoting());
 	x.Add().Text(T("Admin.Common.Stores").Text).Content(TabStores());
     
-    //generate an event
     EngineContext.Current.Resolve<IEventPublisher>().Publish(new TabStripCreated(x, "poll-edit", this.Html, this.Model));
 })
 
@@ -116,9 +117,11 @@
 							.Width("60%");
 						columns.Bound(x => x.NumberOfVotes)
 							.ReadOnly()
-							.Width("10%");
+							.Width("10%")
+                            .Centered();
 						columns.Bound(x => x.DisplayOrder1)
-							.Width("10%");
+							.Width("10%")
+                            .Centered();
 						columns.Command(commands =>
 						{
 							commands.Edit().Localize(T);
@@ -139,15 +142,7 @@
 							.Delete("PollAnswerDelete", "Poll")
 							.Insert("PollAnswerAdd", "Poll", new { pollId = Model.Id });
 					})
-					.ClientEvents(x => x.OnError("grid_onError"))
 					.EnableCustomBinding(true))
-
-			<script type="text/javascript">
-				function grid_onError(e) {
-					alert(e.XMLHttpRequest.responseText);
-					e.preventDefault();
-				}
-			</script>
 		</div>
     }
     else
@@ -156,6 +151,39 @@
     }
 }
 
+@helper TabVoting()
+{
+    if (Model.Id > 0)
+    {
+        <div>
+            @(Html.Telerik().Grid<PollVotingRecordModel>()
+                .Name("voting-records-grid")
+                .DataKeys(x =>
+                {
+                    x.Add(y => y.Id).RouteKey("Id");
+                })
+                .Columns(columns =>
+                {
+			        columns.Bound(x => x.Email)
+				        .Template(x => Html.ActionLink(x.Email, "Edit", "Customer", new { id = x.CustomerId }, new { }))
+				        .ClientTemplate("<a href=\"" + Url.Content("~/Admin/Customer/Edit/") + "<#= CustomerId #>\"><#= Email #></a>");
+			        columns.Bound(x => x.Username)
+				        .Visible(Model.UsernamesEnabled);
+			        columns.Bound(x => x.FullName);
+                    columns.Bound(x => x.AnswerName);
+                    columns.Bound(x => x.CreatedOn);
+                })
+                .Pageable(settings => settings.PageSize(Model.GridPageSize).Position(GridPagerPosition.Both))
+                .DataBinding(dataBinding => dataBinding.Ajax().Select("VotingRecords", "Poll", new { pollId = Model.Id }))
+                .EnableCustomBinding(true))
+        </div>
+    }
+    else
+    {
+		@T("Admin.ContentManagement.Polls.Answers.SaveBeforeEdit")
+    }
+}
+
 @helper TabStores()
 {
 	@Html.Partial("StoreSelector", Model)

From 32e1e2836d8012b23bb4d335f6216dcce768f85e Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Thu, 4 Oct 2018 16:09:10 +0200
Subject: [PATCH 50/71] Minor improvements

---
 .../Setup/SeedData/InvariantSeedData.cs       | 34 +++++++------------
 .../Controllers/PollController.cs             | 25 ++++++--------
 .../Infrastructure/AutoMapperAdminProfile.cs  |  4 ++-
 .../Administration/Models/Polls/PollModel.cs  |  1 +
 .../Views/Poll/_CreateOrUpdate.cshtml         |  2 +-
 5 files changed, 28 insertions(+), 38 deletions(-)

diff --git a/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs b/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs
index e61e2c513b..a7947fd324 100644
--- a/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs
+++ b/src/Libraries/SmartStore.Data/Setup/SeedData/InvariantSeedData.cs
@@ -13306,83 +13306,73 @@ public IList<PollAnswer> PollAnswers()
 		public IList<Poll> Polls()
 		{
 			var defaultLanguage = _ctx.Set<Language>().FirstOrDefault();
-			var poll1 = new Poll()
+			var poll1 = new Poll
 			{
 				Language = defaultLanguage,
 				Name = "How do you like the shop?",
-				SystemKeyword = "RightColumnPoll",
+				SystemKeyword = "Blog",
 				Published = true,
 				DisplayOrder = 1,
 			};
 
-			poll1.PollAnswers.Add(new PollAnswer()
+			poll1.PollAnswers.Add(new PollAnswer
 			{
 				Name = "Excellent",
 				DisplayOrder = 1,
 			});
 
-			poll1.PollAnswers.Add(new PollAnswer()
+			poll1.PollAnswers.Add(new PollAnswer
 			{
 				Name = "Good",
 				DisplayOrder = 2,
 			});
 
-			poll1.PollAnswers.Add(new PollAnswer()
+			poll1.PollAnswers.Add(new PollAnswer
 			{
 				Name = "Poor",
 				DisplayOrder = 3,
 			});
 
-			poll1.PollAnswers.Add(new PollAnswer()
+			poll1.PollAnswers.Add(new PollAnswer
 			{
 				Name = "Very bad",
 				DisplayOrder = 4,
 			});
 
 
-			//_pollAnswerRepository.Table.Where(x => x.DisplayOrder < 5).Each(y =>
-			//    {
-			//        poll1.PollAnswers.Add(y);
-			//    });
-
-			var poll2 = new Poll()
+			var poll2 = new Poll
 			{
 				Language = defaultLanguage,
 				Name = "How often do you buy online?",
-				SystemKeyword = "RightColumnPoll",
+				SystemKeyword = "Blog",
 				Published = true,
 				DisplayOrder = 2,
 			};
 
-			poll2.PollAnswers.Add(new PollAnswer()
+			poll2.PollAnswers.Add(new PollAnswer
 			{
 				Name = "Daily",
 				DisplayOrder = 1,
 			});
 
-			poll2.PollAnswers.Add(new PollAnswer()
+			poll2.PollAnswers.Add(new PollAnswer
 			{
 				Name = "Once a week",
 				DisplayOrder = 2,
 			});
 
-			poll2.PollAnswers.Add(new PollAnswer()
+			poll2.PollAnswers.Add(new PollAnswer
 			{
 				Name = "Every two weeks",
 				DisplayOrder = 3,
 			});
 
-			poll2.PollAnswers.Add(new PollAnswer()
+			poll2.PollAnswers.Add(new PollAnswer
 			{
 				Name = "Once a month",
 				DisplayOrder = 4,
 			});
 
-			//_pollAnswerRepository.Table.Where(x => x.DisplayOrder > 4).Each(y =>
-			//{
-			//    poll2.PollAnswers.Add(y);
-			//});
-
 
 			var entities = new List<Poll>
 			{
diff --git a/src/Presentation/SmartStore.Web/Administration/Controllers/PollController.cs b/src/Presentation/SmartStore.Web/Administration/Controllers/PollController.cs
index 3825a02d75..53b4748fb5 100644
--- a/src/Presentation/SmartStore.Web/Administration/Controllers/PollController.cs
+++ b/src/Presentation/SmartStore.Web/Administration/Controllers/PollController.cs
@@ -65,7 +65,11 @@ private void PreparePollModel(PollModel model, Poll poll, bool excludeProperties
 			model.AvailableStores = _storeService.GetAllStores().ToSelectListItems(model.SelectedStoreIds);
             model.UsernamesEnabled = _customerSettings.UsernamesEnabled;
             model.GridPageSize = _adminAreaSettings.GridPageSize;
-		}
+
+            model.AvailableLanguages = _languageService.GetAllLanguages(true)
+                .Select(x => new SelectListItem { Text = x.Name, Value = x.Id.ToString() })
+                .ToList();
+        }
 
 		#endregion Utilities
 
@@ -143,11 +147,11 @@ public ActionResult Create()
             if (!_permissionService.Authorize(StandardPermissionProvider.ManagePolls))
                 return AccessDeniedView();
 
-            ViewBag.AllLanguages = _languageService.GetAllLanguages(true);
-
-            var model = new PollModel();
-            model.Published = true;
-            model.ShowOnHomePage = true;
+            var model = new PollModel
+            {
+                Published = true,
+                ShowOnHomePage = true
+            };
 
 			PreparePollModel(model, null, false);
 
@@ -174,11 +178,8 @@ public ActionResult Create(PollModel model, bool continueEditing)
                 return continueEditing ? RedirectToAction("Edit", new { id = poll.Id }) : RedirectToAction("List");
             }
 
-            // If we got this far, something failed, redisplay form.
-            ViewBag.AllLanguages = _languageService.GetAllLanguages(true);
-			
+            // If we got this far, something failed, redisplay form.		
 			PreparePollModel(model, null, true);
-
             return View(model);
         }
 
@@ -191,7 +192,6 @@ public ActionResult Edit(int id)
             if (poll == null)
                 return RedirectToAction("List");
 
-            ViewBag.AllLanguages = _languageService.GetAllLanguages(true);
             var model = poll.ToModel();
             model.StartDate = poll.StartDateUtc;
             model.EndDate = poll.EndDateUtc;
@@ -226,10 +226,7 @@ public ActionResult Edit(PollModel model, bool continueEditing)
             }
 
             // If we got this far, something failed, redisplay form.
-            ViewBag.AllLanguages = _languageService.GetAllLanguages(true);
-
 			PreparePollModel(model, poll, true);
-
             return View(model);
         }
 
diff --git a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperAdminProfile.cs b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperAdminProfile.cs
index 7906ddcbea..068081f3dd 100644
--- a/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperAdminProfile.cs
+++ b/src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperAdminProfile.cs
@@ -498,7 +498,9 @@ public AutoMapperAdminProfile()
 				.ForMember(dest => dest.StartDate, mo => mo.Ignore())
 				.ForMember(dest => dest.EndDate, mo => mo.Ignore())
 				.ForMember(dest => dest.AvailableStores, mo => mo.Ignore())
-				.ForMember(dest => dest.SelectedStoreIds, mo => mo.Ignore());
+				.ForMember(dest => dest.SelectedStoreIds, mo => mo.Ignore())
+                .ForMember(dest => dest.UsernamesEnabled, mo => mo.Ignore())
+                .ForMember(dest => dest.GridPageSize, mo => mo.Ignore());
 			CreateMap<PollModel, Poll>()
 				.ForMember(dest => dest.PollAnswers, mo => mo.Ignore())
 				.ForMember(dest => dest.Language, mo => mo.Ignore())
diff --git a/src/Presentation/SmartStore.Web/Administration/Models/Polls/PollModel.cs b/src/Presentation/SmartStore.Web/Administration/Models/Polls/PollModel.cs
index 7638748736..30fef1abf8 100644
--- a/src/Presentation/SmartStore.Web/Administration/Models/Polls/PollModel.cs
+++ b/src/Presentation/SmartStore.Web/Administration/Models/Polls/PollModel.cs
@@ -17,6 +17,7 @@ public class PollModel : EntityModelBase, IStoreSelector
 
         [SmartResourceDisplayName("Admin.ContentManagement.Polls.Fields.Language")]
         public int LanguageId { get; set; }
+        public List<SelectListItem> AvailableLanguages { get; set; }
 
         [SmartResourceDisplayName("Admin.ContentManagement.Polls.Fields.Language")]
         [AllowHtml]
diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Poll/_CreateOrUpdate.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Poll/_CreateOrUpdate.cshtml
index b0688dcb15..b6889cc50f 100644
--- a/src/Presentation/SmartStore.Web/Administration/Views/Poll/_CreateOrUpdate.cshtml
+++ b/src/Presentation/SmartStore.Web/Administration/Views/Poll/_CreateOrUpdate.cshtml
@@ -21,7 +21,7 @@
                 @Html.SmartLabelFor(model => model.LanguageId)
             </td>
             <td class="adminData">
-                @Html.DropDownListFor(model => model.LanguageId, new SelectList(ViewBag.AllLanguages, "Id", "Name"))
+                @Html.DropDownListFor(model => model.LanguageId, Model.AvailableLanguages)
             </td>
         </tr>
         <tr>

From 0b52c83f529e14f8e1139f519bf2a368c23616c2 Mon Sep 17 00:00:00 2001
From: Michael Herzog <herzog@smartstore.com>
Date: Fri, 5 Oct 2018 20:42:36 +0200
Subject: [PATCH 51/71] Added wow script to SmartStore.Web

---
 .../SmartStore.Web/Content/vendors/wow/wow.js | 511 ++++++++++++++++++
 .../SmartStore.Web/SmartStore.Web.csproj      |   1 +
 2 files changed, 512 insertions(+)
 create mode 100644 src/Presentation/SmartStore.Web/Content/vendors/wow/wow.js

diff --git a/src/Presentation/SmartStore.Web/Content/vendors/wow/wow.js b/src/Presentation/SmartStore.Web/Content/vendors/wow/wow.js
new file mode 100644
index 0000000000..eb0cbb090a
--- /dev/null
+++ b/src/Presentation/SmartStore.Web/Content/vendors/wow/wow.js
@@ -0,0 +1,511 @@
+(function() {
+  var MutationObserver, Util, WeakMap, getComputedStyle, getComputedStyleRX,
+    bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
+    indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+  Util = (function() {
+    function Util() {}
+
+    Util.prototype.extend = function(custom, defaults) {
+      var key, value;
+      for (key in defaults) {
+        value = defaults[key];
+        if (custom[key] == null) {
+          custom[key] = value;
+        }
+      }
+      return custom;
+    };
+
+    Util.prototype.isMobile = function(agent) {
+      return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(agent);
+    };
+
+    Util.prototype.createEvent = function(event, bubble, cancel, detail) {
+      var customEvent;
+      if (bubble == null) {
+        bubble = false;
+      }
+      if (cancel == null) {
+        cancel = false;
+      }
+      if (detail == null) {
+        detail = null;
+      }
+      if (document.createEvent != null) {
+        customEvent = document.createEvent('CustomEvent');
+        customEvent.initCustomEvent(event, bubble, cancel, detail);
+      } else if (document.createEventObject != null) {
+        customEvent = document.createEventObject();
+        customEvent.eventType = event;
+      } else {
+        customEvent.eventName = event;
+      }
+      return customEvent;
+    };
+
+    Util.prototype.emitEvent = function(elem, event) {
+      if (elem.dispatchEvent != null) {
+        return elem.dispatchEvent(event);
+      } else if (event in (elem != null)) {
+        return elem[event]();
+      } else if (("on" + event) in (elem != null)) {
+        return elem["on" + event]();
+      }
+    };
+
+    Util.prototype.addEvent = function(elem, event, fn) {
+      if (elem.addEventListener != null) {
+        return elem.addEventListener(event, fn, false);
+      } else if (elem.attachEvent != null) {
+        return elem.attachEvent("on" + event, fn);
+      } else {
+        return elem[event] = fn;
+      }
+    };
+
+    Util.prototype.removeEvent = function(elem, event, fn) {
+      if (elem.removeEventListener != null) {
+        return elem.removeEventListener(event, fn, false);
+      } else if (elem.detachEvent != null) {
+        return elem.detachEvent("on" + event, fn);
+      } else {
+        return delete elem[event];
+      }
+    };
+
+    Util.prototype.innerHeight = function() {
+      if ('innerHeight' in window) {
+        return window.innerHeight;
+      } else {
+        return document.documentElement.clientHeight;
+      }
+    };
+
+    return Util;
+
+  })();
+
+  WeakMap = this.WeakMap || this.MozWeakMap || (WeakMap = (function() {
+    function WeakMap() {
+      this.keys = [];
+      this.values = [];
+    }
+
+    WeakMap.prototype.get = function(key) {
+      var i, item, j, len, ref;
+      ref = this.keys;
+      for (i = j = 0, len = ref.length; j < len; i = ++j) {
+        item = ref[i];
+        if (item === key) {
+          return this.values[i];
+        }
+      }
+    };
+
+    WeakMap.prototype.set = function(key, value) {
+      var i, item, j, len, ref;
+      ref = this.keys;
+      for (i = j = 0, len = ref.length; j < len; i = ++j) {
+        item = ref[i];
+        if (item === key) {
+          this.values[i] = value;
+          return;
+        }
+      }
+      this.keys.push(key);
+      return this.values.push(value);
+    };
+
+    return WeakMap;
+
+  })());
+
+  MutationObserver = this.MutationObserver || this.WebkitMutationObserver || this.MozMutationObserver || (MutationObserver = (function() {
+    function MutationObserver() {
+      if (typeof console !== "undefined" && console !== null) {
+        console.warn('MutationObserver is not supported by your browser.');
+      }
+      if (typeof console !== "undefined" && console !== null) {
+        console.warn('WOW.js cannot detect dom mutations, please call .sync() after loading new content.');
+      }
+    }
+
+    MutationObserver.notSupported = true;
+
+    MutationObserver.prototype.observe = function() {};
+
+    return MutationObserver;
+
+  })());
+
+  getComputedStyle = this.getComputedStyle || function(el, pseudo) {
+    this.getPropertyValue = function(prop) {
+      var ref;
+      if (prop === 'float') {
+        prop = 'styleFloat';
+      }
+      if (getComputedStyleRX.test(prop)) {
+        prop.replace(getComputedStyleRX, function(_, _char) {
+          return _char.toUpperCase();
+        });
+      }
+      return ((ref = el.currentStyle) != null ? ref[prop] : void 0) || null;
+    };
+    return this;
+  };
+
+  getComputedStyleRX = /(\-([a-z]){1})/g;
+
+  this.WOW = (function() {
+    WOW.prototype.defaults = {
+      boxClass: 'wow',
+      animateClass: 'animated',
+      offset: 0,
+      mobile: true,
+      live: true,
+      callback: null
+    };
+
+    function WOW(options) {
+      if (options == null) {
+        options = {};
+      }
+      this.scrollCallback = bind(this.scrollCallback, this);
+      this.scrollHandler = bind(this.scrollHandler, this);
+      this.resetAnimation = bind(this.resetAnimation, this);
+      this.start = bind(this.start, this);
+      this.scrolled = true;
+      this.config = this.util().extend(options, this.defaults);
+      this.animationNameCache = new WeakMap();
+      this.wowEvent = this.util().createEvent(this.config.boxClass);
+    }
+
+    WOW.prototype.init = function() {
+      var ref;
+      this.element = window.document.documentElement;
+      if ((ref = document.readyState) === "interactive" || ref === "complete") {
+        this.start();
+      } else {
+        this.util().addEvent(document, 'DOMContentLoaded', this.start);
+      }
+      return this.finished = [];
+    };
+
+    WOW.prototype.start = function() {
+      var box, j, len, ref;
+      this.stopped = false;
+      this.boxes = (function() {
+        var j, len, ref, results;
+        ref = this.element.querySelectorAll("." + this.config.boxClass);
+        results = [];
+        for (j = 0, len = ref.length; j < len; j++) {
+          box = ref[j];
+          results.push(box);
+        }
+        return results;
+      }).call(this);
+      this.all = (function() {
+        var j, len, ref, results;
+        ref = this.boxes;
+        results = [];
+        for (j = 0, len = ref.length; j < len; j++) {
+          box = ref[j];
+          results.push(box);
+        }
+        return results;
+      }).call(this);
+      if (this.boxes.length) {
+        if (this.disabled()) {
+          this.resetStyle();
+        } else {
+          ref = this.boxes;
+          for (j = 0, len = ref.length; j < len; j++) {
+            box = ref[j];
+            this.applyStyle(box, true);
+          }
+        }
+      }
+      if (!this.disabled()) {
+        this.util().addEvent(window, 'scroll', this.scrollHandler);
+        this.util().addEvent(window, 'resize', this.scrollHandler);
+        this.interval = setInterval(this.scrollCallback, 50);
+      }
+      if (this.config.live) {
+        return new MutationObserver((function(_this) {
+          return function(records) {
+            var k, len1, node, record, results;
+            results = [];
+            for (k = 0, len1 = records.length; k < len1; k++) {
+              record = records[k];
+              results.push((function() {
+                var l, len2, ref1, results1;
+                ref1 = record.addedNodes || [];
+                results1 = [];
+                for (l = 0, len2 = ref1.length; l < len2; l++) {
+                  node = ref1[l];
+                  results1.push(this.doSync(node));
+                }
+                return results1;
+              }).call(_this));
+            }
+            return results;
+          };
+        })(this)).observe(document.body, {
+          childList: true,
+          subtree: true
+        });
+      }
+    };
+
+    WOW.prototype.stop = function() {
+      this.stopped = true;
+      this.util().removeEvent(window, 'scroll', this.scrollHandler);
+      this.util().removeEvent(window, 'resize', this.scrollHandler);
+      if (this.interval != null) {
+        return clearInterval(this.interval);
+      }
+    };
+
+    WOW.prototype.sync = function(element) {
+      if (MutationObserver.notSupported) {
+        return this.doSync(this.element);
+      }
+    };
+
+    WOW.prototype.doSync = function(element) {
+      var box, j, len, ref, results;
+      if (element == null) {
+        element = this.element;
+      }
+      if (element.nodeType !== 1) {
+        return;
+      }
+      element = element.parentNode || element;
+      ref = element.querySelectorAll("." + this.config.boxClass);
+      results = [];
+      for (j = 0, len = ref.length; j < len; j++) {
+        box = ref[j];
+        if (indexOf.call(this.all, box) < 0) {
+          this.boxes.push(box);
+          this.all.push(box);
+          if (this.stopped || this.disabled()) {
+            this.resetStyle();
+          } else {
+            this.applyStyle(box, true);
+          }
+          results.push(this.scrolled = true);
+        } else {
+          results.push(void 0);
+        }
+      }
+      return results;
+    };
+
+    WOW.prototype.show = function(box) {
+      this.applyStyle(box);
+      box.className = box.className + " " + this.config.animateClass;
+      if (this.config.callback != null) {
+        this.config.callback(box);
+      }
+      this.util().emitEvent(box, this.wowEvent);
+      this.util().addEvent(box, 'animationend', this.resetAnimation);
+      this.util().addEvent(box, 'oanimationend', this.resetAnimation);
+      this.util().addEvent(box, 'webkitAnimationEnd', this.resetAnimation);
+      this.util().addEvent(box, 'MSAnimationEnd', this.resetAnimation);
+      return box;
+    };
+
+    WOW.prototype.applyStyle = function(box, hidden) {
+      var delay, duration, iteration;
+      duration = box.getAttribute('data-wow-duration');
+      delay = box.getAttribute('data-wow-delay');
+      iteration = box.getAttribute('data-wow-iteration');
+      return this.animate((function(_this) {
+        return function() {
+          return _this.customStyle(box, hidden, duration, delay, iteration);
+        };
+      })(this));
+    };
+
+    WOW.prototype.animate = (function() {
+      if ('requestAnimationFrame' in window) {
+        return function(callback) {
+          return window.requestAnimationFrame(callback);
+        };
+      } else {
+        return function(callback) {
+          return callback();
+        };
+      }
+    })();
+
+    WOW.prototype.resetStyle = function() {
+      var box, j, len, ref, results;
+      ref = this.boxes;
+      results = [];
+      for (j = 0, len = ref.length; j < len; j++) {
+        box = ref[j];
+        results.push(box.style.visibility = 'visible');
+      }
+      return results;
+    };
+
+    WOW.prototype.resetAnimation = function(event) {
+      var target;
+      if (event.type.toLowerCase().indexOf('animationend') >= 0) {
+        target = event.target || event.srcElement;
+        return target.className = target.className.replace(this.config.animateClass, '').trim();
+      }
+    };
+
+    WOW.prototype.customStyle = function(box, hidden, duration, delay, iteration) {
+      if (hidden) {
+        this.cacheAnimationName(box);
+      }
+      box.style.visibility = hidden ? 'hidden' : 'visible';
+      if (duration) {
+        this.vendorSet(box.style, {
+          animationDuration: duration
+        });
+      }
+      if (delay) {
+        this.vendorSet(box.style, {
+          animationDelay: delay
+        });
+      }
+      if (iteration) {
+        this.vendorSet(box.style, {
+          animationIterationCount: iteration
+        });
+      }
+      this.vendorSet(box.style, {
+        animationName: hidden ? 'none' : this.cachedAnimationName(box)
+      });
+      return box;
+    };
+
+    WOW.prototype.vendors = ["moz", "webkit"];
+
+    WOW.prototype.vendorSet = function(elem, properties) {
+      var name, results, value, vendor;
+      results = [];
+      for (name in properties) {
+        value = properties[name];
+        elem["" + name] = value;
+        results.push((function() {
+          var j, len, ref, results1;
+          ref = this.vendors;
+          results1 = [];
+          for (j = 0, len = ref.length; j < len; j++) {
+            vendor = ref[j];
+            results1.push(elem["" + vendor + (name.charAt(0).toUpperCase()) + (name.substr(1))] = value);
+          }
+          return results1;
+        }).call(this));
+      }
+      return results;
+    };
+
+    WOW.prototype.vendorCSS = function(elem, property) {
+      var j, len, ref, result, style, vendor;
+      style = getComputedStyle(elem);
+      result = style.getPropertyCSSValue(property);
+      ref = this.vendors;
+      for (j = 0, len = ref.length; j < len; j++) {
+        vendor = ref[j];
+        result = result || style.getPropertyCSSValue("-" + vendor + "-" + property);
+      }
+      return result;
+    };
+
+    WOW.prototype.animationName = function(box) {
+      var animationName;
+      try {
+        animationName = this.vendorCSS(box, 'animation-name').cssText;
+      } catch (_error) {
+        animationName = getComputedStyle(box).getPropertyValue('animation-name');
+      }
+      if (animationName === 'none') {
+        return '';
+      } else {
+        return animationName;
+      }
+    };
+
+    WOW.prototype.cacheAnimationName = function(box) {
+      return this.animationNameCache.set(box, this.animationName(box));
+    };
+
+    WOW.prototype.cachedAnimationName = function(box) {
+      return this.animationNameCache.get(box);
+    };
+
+    WOW.prototype.scrollHandler = function() {
+      return this.scrolled = true;
+    };
+
+    WOW.prototype.scrollCallback = function() {
+      var box;
+      if (this.scrolled) {
+        this.scrolled = false;
+        this.boxes = (function() {
+          var j, len, ref, results;
+          ref = this.boxes;
+          results = [];
+          for (j = 0, len = ref.length; j < len; j++) {
+            box = ref[j];
+            if (!(box)) {
+              continue;
+            }
+            if (this.isVisible(box)) {
+              this.show(box);
+              continue;
+            }
+            results.push(box);
+          }
+          return results;
+        }).call(this);
+        if (!(this.boxes.length || this.config.live)) {
+          return this.stop();
+        }
+      }
+    };
+
+    WOW.prototype.offsetTop = function(element) {
+      var top;
+      while (element.offsetTop === void 0) {
+        element = element.parentNode;
+      }
+      top = element.offsetTop;
+      while (element = element.offsetParent) {
+        top += element.offsetTop;
+      }
+      return top;
+    };
+
+    WOW.prototype.isVisible = function(box) {
+      var bottom, offset, top, viewBottom, viewTop;
+      offset = box.getAttribute('data-wow-offset') || this.config.offset;
+      viewTop = window.pageYOffset;
+      viewBottom = viewTop + Math.min(this.element.clientHeight, this.util().innerHeight()) - offset;
+      top = this.offsetTop(box);
+      bottom = top + box.clientHeight;
+      return top <= viewBottom && bottom >= viewTop;
+    };
+
+    WOW.prototype.util = function() {
+      return this._util != null ? this._util : this._util = new Util();
+    };
+
+    WOW.prototype.disabled = function() {
+      return !this.config.mobile && this.util().isMobile(navigator.userAgent);
+    };
+
+    return WOW;
+
+  })();
+
+}).call(this);
+
+//# sourceMappingURL=wow.js.map
\ No newline at end of file
diff --git a/src/Presentation/SmartStore.Web/SmartStore.Web.csproj b/src/Presentation/SmartStore.Web/SmartStore.Web.csproj
index 2c5e2a69a4..92d4ab19c7 100644
--- a/src/Presentation/SmartStore.Web/SmartStore.Web.csproj
+++ b/src/Presentation/SmartStore.Web/SmartStore.Web.csproj
@@ -1162,6 +1162,7 @@
     <Content Include="Scripts\smartstore.viewport.js" />
     <Content Include="Content\vendors\underscore\underscore.min.js" />
     <Content Include="Content\vendors\underscore\underscore.js" />
+    <Content Include="Content\vendors\wow\wow.js" />
     <Content Include="Themes\FlexBlue\preview.png" />
     <Content Include="Themes\FlexBlack\preview.png" />
     <Content Include="Scripts\smartstore.entitypicker.js" />

From dfd33f8c779323eece23e1af32daf040e790f78c Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Fri, 5 Oct 2018 21:32:32 +0200
Subject: [PATCH 52/71] Resolves #1510 Breadcrumb of an associated product
 should include the grouped product if it has no assigned categories

---
 changelog.md                                  |  1 +
 .../Controllers/ProductController.cs          | 46 +++++++++----------
 2 files changed, 22 insertions(+), 25 deletions(-)

diff --git a/changelog.md b/changelog.md
index 58e3aa514c..c24fd6d9c4 100644
--- a/changelog.md
+++ b/changelog.md
@@ -43,6 +43,7 @@
 * Added filter for newsletter subscriber export by working language
 * Refactored download section  
 * Enhanced EntityPicker to pick from customers, manufacturers & categories
+* #1510 Breadcrumb of an associated product should include the grouped product if it has no assigned categories.
 
 ### Bugfixes
 * In a multi-store environment, multiple topics with the same system name cannot be resolved reliably.
diff --git a/src/Presentation/SmartStore.Web/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Controllers/ProductController.cs
index a69302a416..e2e77bbcde 100644
--- a/src/Presentation/SmartStore.Web/Controllers/ProductController.cs
+++ b/src/Presentation/SmartStore.Web/Controllers/ProductController.cs
@@ -10,12 +10,12 @@
 using SmartStore.Core.Domain.Media;
 using SmartStore.Core.Domain.Orders;
 using SmartStore.Core.Domain.Seo;
+using SmartStore.Core.Domain.Tax;
 using SmartStore.Services;
 using SmartStore.Services.Catalog;
 using SmartStore.Services.Catalog.Modelling;
 using SmartStore.Services.Common;
 using SmartStore.Services.Customers;
-using SmartStore.Services.Directory;
 using SmartStore.Services.Localization;
 using SmartStore.Services.Media;
 using SmartStore.Services.Orders;
@@ -29,25 +29,19 @@
 using SmartStore.Web.Framework.UI;
 using SmartStore.Web.Infrastructure.Cache;
 using SmartStore.Web.Models.Catalog;
-using SmartStore.Core.Domain.Tax;
 
 namespace SmartStore.Web.Controllers
 {
-	public partial class ProductController : PublicControllerBase
+    public partial class ProductController : PublicControllerBase
 	{
 		private readonly ICommonServices _services;
 		private readonly IManufacturerService _manufacturerService;
 		private readonly IProductService _productService;
 		private readonly IProductAttributeService _productAttributeService;
-		private readonly IProductAttributeParser _productAttributeParser;
 		private readonly ITaxService _taxService;
-		private readonly ICurrencyService _currencyService;
 		private readonly IPictureService _pictureService;
-		private readonly IPriceCalculationService _priceCalculationService;
-		private readonly IPriceFormatter _priceFormatter;
 		private readonly ICustomerContentService _customerContentService;
 		private readonly ICustomerService _customerService;
-		private readonly IShoppingCartService _shoppingCartService;
 		private readonly IRecentlyViewedProductsService _recentlyViewedProductsService;
 		private readonly IProductTagService _productTagService;
 		private readonly IOrderReportService _orderReportService;
@@ -61,8 +55,6 @@ public partial class ProductController : PublicControllerBase
 		private readonly LocalizationSettings _localizationSettings;
 		private readonly CaptchaSettings _captchaSettings;
 		private readonly CatalogHelper _helper;
-        private readonly IDownloadService _downloadService;
-        private readonly ILocalizationService _localizationService;
 		private readonly IBreadcrumb _breadcrumb;
 		private readonly Lazy<PrivacySettings> _privacySettings;
 		private readonly Lazy<TaxSettings> _taxSettings;
@@ -72,15 +64,10 @@ public ProductController(
 			IManufacturerService manufacturerService,
 			IProductService productService,
 			IProductAttributeService productAttributeService,
-			IProductAttributeParser productAttributeParser,
 			ITaxService taxService,
-			ICurrencyService currencyService,
 			IPictureService pictureService,
-			IPriceCalculationService priceCalculationService, 
-			IPriceFormatter priceFormatter,
 			ICustomerContentService customerContentService, 
 			ICustomerService customerService,
-			IShoppingCartService shoppingCartService,
 			IRecentlyViewedProductsService recentlyViewedProductsService, 
 			IProductTagService productTagService,
 			IOrderReportService orderReportService,
@@ -94,8 +81,6 @@ public ProductController(
 			LocalizationSettings localizationSettings, 
 			CaptchaSettings captchaSettings,
 			CatalogHelper helper,
-            IDownloadService downloadService,
-            ILocalizationService localizationService,
 			IBreadcrumb breadcrumb,
 			Lazy<PrivacySettings> privacySettings,
             Lazy<TaxSettings> taxSettings)
@@ -104,15 +89,10 @@ public ProductController(
 			_manufacturerService = manufacturerService;
 			_productService = productService;
 			_productAttributeService = productAttributeService;
-			_productAttributeParser = productAttributeParser;
 			_taxService = taxService;
-			_currencyService = currencyService;
 			_pictureService = pictureService;
-			_priceCalculationService = priceCalculationService;
-			_priceFormatter = priceFormatter;
 			_customerContentService = customerContentService;
 			_customerService = customerService;
-			_shoppingCartService = shoppingCartService;
 			_recentlyViewedProductsService = recentlyViewedProductsService;
 			_productTagService = productTagService;
 			_orderReportService = orderReportService;
@@ -126,8 +106,6 @@ public ProductController(
 			_localizationSettings = localizationSettings;
 			_captchaSettings = captchaSettings;
 			_helper = helper;
-			_downloadService = downloadService;
-			_localizationService = localizationService;
 			_breadcrumb = breadcrumb;
 			_privacySettings = privacySettings;
 			_taxSettings = taxSettings;
@@ -193,12 +171,30 @@ public ActionResult ProductDetails(int productId, string attributes, ProductVari
 			if (_catalogSettings.CategoryBreadcrumbEnabled)
 			{
 				_helper.GetCategoryBreadCrumb(0, productId).Select(x => x.Value).Each(x => _breadcrumb.Track(x));
+
+                // Add parent product if product has no category assigned.
+                var hasTrail = _breadcrumb.Trail?.Any() ?? false;
+                if (!hasTrail)
+                {
+                    var parentGroupedProduct = _productService.GetProductById(product.ParentGroupedProductId);
+                    if (parentGroupedProduct != null)
+                    {
+                        _breadcrumb.Track(new MenuItem
+                        {
+                            Text = parentGroupedProduct.GetLocalized(x => x.Name),
+                            Rtl = model.Name.CurrentLanguage.Rtl,
+                            EntityId = parentGroupedProduct.Id,
+                            Url = Url.RouteUrl("Product", new { SeName = parentGroupedProduct.GetSeName() })
+                        });
+                    }
+                }
+
 				_breadcrumb.Track(new MenuItem
 				{
 					Text = model.Name,
 					Rtl = model.Name.CurrentLanguage.Rtl,
 					EntityId = product.Id,
-					Url = Url.RouteUrl("Product", new { productId = product.Id, SeName = model.SeName })
+					Url = Url.RouteUrl("Product", new { model.SeName })
 				});
 			}
 

From 14a1c4b4865613a9e30335c131ba5b5399a940be Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Sat, 6 Oct 2018 03:50:19 +0200
Subject: [PATCH 53/71] Minor theming stuff

---
 .../Views/Shared/Partials/Navbar.cshtml        |  2 +-
 src/Presentation/SmartStore.Web/Global.asax    |  2 +-
 .../SmartStore.Web/SmartStore.Web.csproj       |  1 +
 .../Themes/Flex/Content/_layout.scss           | 18 +++++++++++++-----
 .../Views/Shared/Layouts/_Layout.Bare.cshtml   |  7 +++++++
 src/Presentation/SmartStore.Web/Web.config     |  2 +-
 6 files changed, 24 insertions(+), 8 deletions(-)
 create mode 100644 src/Presentation/SmartStore.Web/Views/Shared/Layouts/_Layout.Bare.cshtml

diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Shared/Partials/Navbar.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Shared/Partials/Navbar.cshtml
index 3cfa083c98..b101bfe37e 100644
--- a/src/Presentation/SmartStore.Web/Administration/Views/Shared/Partials/Navbar.cshtml
+++ b/src/Presentation/SmartStore.Web/Administration/Views/Shared/Partials/Navbar.cshtml
@@ -7,7 +7,7 @@
     var currentCustomer = this.WorkContext.CurrentCustomer;
     var currentLanguage = this.WorkContext.WorkingLanguage;
     var userName = (string)ViewBag.UserName;
-    var stores = (IList<Store>)ViewBag.Stores;
+    var stores = ((IList<Store>)ViewBag.Stores) ?? new List<Store>();
     string currentLanguageCode = currentLanguage.UniqueSeoCode.EmptyNull().ToLower();
     string communityUrl = (currentLanguageCode == "de" ?
         "http://community.smartstore.com" :
diff --git a/src/Presentation/SmartStore.Web/Global.asax b/src/Presentation/SmartStore.Web/Global.asax
index 612debf2a2..ebaeaa3f40 100644
--- a/src/Presentation/SmartStore.Web/Global.asax
+++ b/src/Presentation/SmartStore.Web/Global.asax
@@ -1 +1 @@
-<%@ Application Codebehind="Global.asax.cs" Inherits="SmartStore.Web.MvcApplication" Language="C#" %>
+<%@ Application Codebehind="Global.asax.cs" Inherits="SmartStore.Web.MvcApplication" Language="C#" %> 
diff --git a/src/Presentation/SmartStore.Web/SmartStore.Web.csproj b/src/Presentation/SmartStore.Web/SmartStore.Web.csproj
index 92d4ab19c7..0a9ee64ef5 100644
--- a/src/Presentation/SmartStore.Web/SmartStore.Web.csproj
+++ b/src/Presentation/SmartStore.Web/SmartStore.Web.csproj
@@ -1767,6 +1767,7 @@
     <Content Include="Views\Boards\Partials\InstantSearch.cshtml" />
     <Content Include="Views\Boards\Partials\SearchHits.cshtml" />
     <Content Include="Views\Shared\Partials\Customer.Avatar.cshtml" />
+    <Content Include="Views\Shared\Layouts\_Layout.Bare.cshtml" />
     <None Include="Web.EFMigrations.config">
       <DependentUpon>Web.config</DependentUpon>
     </None>
diff --git a/src/Presentation/SmartStore.Web/Themes/Flex/Content/_layout.scss b/src/Presentation/SmartStore.Web/Themes/Flex/Content/_layout.scss
index a04290db25..d459899755 100644
--- a/src/Presentation/SmartStore.Web/Themes/Flex/Content/_layout.scss
+++ b/src/Presentation/SmartStore.Web/Themes/Flex/Content/_layout.scss
@@ -29,12 +29,20 @@ html {
 }
 
 body { 
-    background: $site-bg; 
-}
+    background: $site-bg;
 
-body.popup { 
-    padding: 1.25rem; 
-    background: $body-bg;
+    &.popup { 
+        padding: 1.25rem; 
+        background: $body-bg;
+    }
+
+    &.bare {
+        padding: 0;
+        margin: 0;
+        background: $body-bg;
+        border: 0;
+        overflow-y: auto;
+    }
 }
 
 #header {
diff --git a/src/Presentation/SmartStore.Web/Views/Shared/Layouts/_Layout.Bare.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/Layouts/_Layout.Bare.cshtml
new file mode 100644
index 0000000000..71063b0a77
--- /dev/null
+++ b/src/Presentation/SmartStore.Web/Views/Shared/Layouts/_Layout.Bare.cshtml
@@ -0,0 +1,7 @@
+@{
+
+    Layout = "_Document";
+    Html.AddBodyCssClass("bare py-0 m-0");
+}
+
+@RenderBody()
\ No newline at end of file
diff --git a/src/Presentation/SmartStore.Web/Web.config b/src/Presentation/SmartStore.Web/Web.config
index bbc22f262e..ad41f1171d 100644
--- a/src/Presentation/SmartStore.Web/Web.config
+++ b/src/Presentation/SmartStore.Web/Web.config
@@ -79,7 +79,7 @@
     <sessionState configSource="Config\SessionState.config" />
     <trace enabled="true" localOnly="true" pageOutput="true" requestLimit="40" />
     <httpRuntime targetFramework="4.5.2" maxRequestLength="1536000" executionTimeout="5400" maxQueryStringLength="16384" fcnMode="Single" />
-    <compilation debug="true" targetFramework="4.6.1" numRecompilesBeforeAppRestart="256" batch="true" optimizeCompilations="true">
+    <compilation debug="true" targetFramework="4.6.1" numRecompilesBeforeAppRestart="257" batch="true" optimizeCompilations="true">
       <assemblies>
         <add assembly="System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
         <add assembly="System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />

From 6adbcae87ac38676c907cb24149676745c2bc6f1 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Sun, 7 Oct 2018 10:42:44 +0200
Subject: [PATCH 54/71] Resolves #1518 Allow for blank salutation and country
 in company settings

---
 .../Administration/Views/Setting/GeneralCommon.cshtml       | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Setting/GeneralCommon.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Setting/GeneralCommon.cshtml
index 717b94043a..9178e6f490 100644
--- a/src/Presentation/SmartStore.Web/Administration/Views/Setting/GeneralCommon.cshtml
+++ b/src/Presentation/SmartStore.Web/Administration/Views/Setting/GeneralCommon.cshtml
@@ -551,7 +551,7 @@
             </td>
             <td class="adminData">
 				@Html.SettingEditorFor(model => model.CompanyInformationSettings.Salutation, 
-					Html.DropDownListFor(model => model.CompanyInformationSettings.Salutation, Model.CompanyInformationSettings.Salutations))
+					Html.DropDownListFor(model => model.CompanyInformationSettings.Salutation, Model.CompanyInformationSettings.Salutations, T("Common.Unspecified")))
                 @Html.ValidationMessageFor(model => model.CompanyInformationSettings.Salutation)
             </td>
         </tr>
@@ -588,7 +588,7 @@
             </td>
             <td class="adminData">
 				@Html.SettingEditorFor(model => model.CompanyInformationSettings.CompanyManagementDescription, 
-					Html.DropDownListFor(model => model.CompanyInformationSettings.CompanyManagementDescription, Model.CompanyInformationSettings.ManagementDescriptions))
+					Html.DropDownListFor(model => model.CompanyInformationSettings.CompanyManagementDescription, Model.CompanyInformationSettings.ManagementDescriptions, T("Common.Unspecified")))
                 @Html.ValidationMessageFor(model => model.CompanyInformationSettings.CompanyManagementDescription)
             </td>
         </tr>
@@ -645,7 +645,7 @@
             </td>
             <td class="adminData">
 				@Html.SettingEditorFor(model => model.CompanyInformationSettings.CountryId, 
-					Html.DropDownListFor(model => model.CompanyInformationSettings.CountryId, Model.CompanyInformationSettings.AvailableCountries))
+					Html.DropDownListFor(model => model.CompanyInformationSettings.CountryId, Model.CompanyInformationSettings.AvailableCountries, T("Common.Unspecified")))
                 @Html.ValidationMessageFor(model => model.CompanyInformationSettings.CountryId)
             </td>
         </tr>

From fa7606cb963269c87bb05d7deb7662eb067e3da2 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Mon, 8 Oct 2018 12:22:55 +0200
Subject: [PATCH 55/71] Resolves #909 Email & Phone number should be optional
 fields for Address form fields

---
 .../Controllers/CheckoutController.cs         | 120 +++++++++---------
 .../Controllers/CustomerController.cs         |   1 +
 2 files changed, 63 insertions(+), 58 deletions(-)

diff --git a/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs b/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs
index 33a72adf27..bde2fc97f0 100644
--- a/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs
+++ b/src/Presentation/SmartStore.Web/Controllers/CheckoutController.cs
@@ -14,7 +14,6 @@
 using SmartStore.Core.Logging;
 using SmartStore.Services.Catalog;
 using SmartStore.Services.Common;
-using SmartStore.Services.Configuration;
 using SmartStore.Services.Customers;
 using SmartStore.Services.Directory;
 using SmartStore.Services.Localization;
@@ -52,9 +51,7 @@ public partial class CheckoutController : PublicControllerBase
         private readonly IPaymentService _paymentService;
         private readonly IOrderTotalCalculationService _orderTotalCalculationService;
         private readonly IOrderService _orderService;
-        private readonly IWebHelper _webHelper;
         private readonly HttpContextBase _httpContext;
-		private readonly ISettingService _settingService;
         private readonly OrderSettings _orderSettings;
         private readonly PaymentSettings _paymentSettings;
         private readonly AddressSettings _addressSettings;
@@ -66,47 +63,54 @@ public partial class CheckoutController : PublicControllerBase
 
 		#region Constructors
 
-		public CheckoutController(IWorkContext workContext, IStoreContext storeContext,
-            IShoppingCartService shoppingCartService, ILocalizationService localizationService, 
-            ITaxService taxService, ICurrencyService currencyService, 
-            IPriceFormatter priceFormatter, IOrderProcessingService orderProcessingService,
-            ICustomerService customerService,  IGenericAttributeService genericAttributeService,
+		public CheckoutController(
+            IWorkContext workContext,
+            IStoreContext storeContext,
+            IShoppingCartService shoppingCartService, 
+            ILocalizationService localizationService, 
+            ITaxService taxService, 
+            ICurrencyService currencyService, 
+            IPriceFormatter priceFormatter, 
+            IOrderProcessingService orderProcessingService,
+            ICustomerService customerService,
+            IGenericAttributeService genericAttributeService,
             ICountryService countryService,
-            IStateProvinceService stateProvinceService, IShippingService shippingService,
+            IStateProvinceService stateProvinceService, 
+            IShippingService shippingService,
 			IPaymentService paymentService, 
 			IOrderTotalCalculationService orderTotalCalculationService,
-            IOrderService orderService, IWebHelper webHelper,
-            HttpContextBase httpContext, IMobileDeviceHelper mobileDeviceHelper,
+            IOrderService orderService,
+            HttpContextBase httpContext,
             OrderSettings orderSettings, 
-            PaymentSettings paymentSettings, AddressSettings addressSettings,
-            ShoppingCartSettings shoppingCartSettings, ShippingSettings shippingSettings,
-			ISettingService settingService, PluginMediator pluginMediator)
+            PaymentSettings paymentSettings,
+            AddressSettings addressSettings,
+            ShoppingCartSettings shoppingCartSettings,
+            ShippingSettings shippingSettings,
+			PluginMediator pluginMediator)
         {
-            this._workContext = workContext;
-			this._storeContext = storeContext;
-            this._shoppingCartService = shoppingCartService;
-            this._localizationService = localizationService;
-            this._taxService = taxService;
-            this._currencyService = currencyService;
-            this._priceFormatter = priceFormatter;
-            this._orderProcessingService = orderProcessingService;
-            this._customerService = customerService;
-            this._genericAttributeService = genericAttributeService;
-            this._countryService = countryService;
-            this._stateProvinceService = stateProvinceService;
-            this._shippingService = shippingService;
-            this._paymentService = paymentService;
-            this._orderTotalCalculationService = orderTotalCalculationService;
-            this._orderService = orderService;
-            this._webHelper = webHelper;
-            this._httpContext = httpContext;
-			this._settingService = settingService;
-            this._orderSettings = orderSettings;
-            this._paymentSettings = paymentSettings;
-            this._addressSettings = addressSettings;
-            this._shippingSettings = shippingSettings;
-            this._shoppingCartSettings = shoppingCartSettings;
-			this._pluginMediator = pluginMediator;
+            _workContext = workContext;
+			_storeContext = storeContext;
+            _shoppingCartService = shoppingCartService;
+            _localizationService = localizationService;
+            _taxService = taxService;
+            _currencyService = currencyService;
+            _priceFormatter = priceFormatter;
+            _orderProcessingService = orderProcessingService;
+            _customerService = customerService;
+            _genericAttributeService = genericAttributeService;
+            _countryService = countryService;
+            _stateProvinceService = stateProvinceService;
+            _shippingService = shippingService;
+            _paymentService = paymentService;
+            _orderTotalCalculationService = orderTotalCalculationService;
+            _orderService = orderService;
+            _httpContext = httpContext;
+            _orderSettings = orderSettings;
+            _paymentSettings = paymentSettings;
+            _addressSettings = addressSettings;
+            _shippingSettings = shippingSettings;
+            _shoppingCartSettings = shoppingCartSettings;
+			_pluginMediator = pluginMediator;
         }
 
         #endregion
@@ -131,19 +135,19 @@ protected bool IsPaymentWorkflowRequired(IList<OrganizedShoppingCartItem> cart,
         [NonAction]
         protected CheckoutBillingAddressModel PrepareBillingAddressModel(int? selectedCountryId = null)
         {
+            var customer = _workContext.CurrentCustomer;
             var model = new CheckoutBillingAddressModel();
-            //existing addresses
-            var addresses = _workContext.CurrentCustomer.Addresses.Where(a => a.Country == null || a.Country.AllowsBilling).ToList();
+            
+            // Existing addresses.
+            var addresses = customer.Addresses.Where(a => a.Country == null || a.Country.AllowsBilling).ToList();
             foreach (var address in addresses)
             {
                 var addressModel = new AddressModel();
-                addressModel.PrepareModel(address, 
-                    false, 
-                    _addressSettings);
+                addressModel.PrepareModel(address, false, _addressSettings);
                 model.ExistingAddresses.Add(addressModel);
             }
 
-            //new address
+            // New address.
             model.NewAddress.CountryId = selectedCountryId;
             model.NewAddress.PrepareModel(null,
                 false,
@@ -151,25 +155,27 @@ protected CheckoutBillingAddressModel PrepareBillingAddressModel(int? selectedCo
                 _localizationService,
                 _stateProvinceService,
                 () => _countryService.GetAllCountriesForBilling());
+            model.NewAddress.Email = customer?.Email;
+
             return model;
         }
 
         [NonAction]
         protected CheckoutShippingAddressModel PrepareShippingAddressModel(int? selectedCountryId = null)
         {
+            var customer = _workContext.CurrentCustomer;
             var model = new CheckoutShippingAddressModel();
-            //existing addresses
-            var addresses = _workContext.CurrentCustomer.Addresses.Where(a => a.Country == null || a.Country.AllowsShipping).ToList();
+            
+            // Existing addresses.
+            var addresses = customer.Addresses.Where(a => a.Country == null || a.Country.AllowsShipping).ToList();
             foreach (var address in addresses)
             {
                 var addressModel = new AddressModel();
-                addressModel.PrepareModel(address,
-                    false,
-                    _addressSettings);
+                addressModel.PrepareModel(address, false, _addressSettings);
                 model.ExistingAddresses.Add(addressModel);
             }
 
-            //new address
+            // New address.
             model.NewAddress.CountryId = selectedCountryId;
             model.NewAddress.PrepareModel(null,
                 false,
@@ -177,6 +183,8 @@ protected CheckoutShippingAddressModel PrepareShippingAddressModel(int? selected
                 _localizationService,
                 _stateProvinceService,
                 () => _countryService.GetAllCountriesForShipping());
+            model.NewAddress.Email = customer?.Email;
+
             return model;
         }
 
@@ -468,16 +476,14 @@ public ActionResult Index()
 
         public ActionResult BillingAddress()
         {
-            //validation
 			var cart = _workContext.CurrentCustomer.GetCartItems(ShoppingCartType.ShoppingCart, _storeContext.CurrentStore.Id);
 
 			if (cart.Count == 0)
                 return RedirectToRoute("ShoppingCart");
 
-            if ((_workContext.CurrentCustomer.IsGuest() && !_orderSettings.AnonymousCheckoutAllowed))
+            if (_workContext.CurrentCustomer.IsGuest() && !_orderSettings.AnonymousCheckoutAllowed)
                 return new HttpUnauthorizedResult();
 
-            //model
             var model = PrepareBillingAddressModel();
             return View(model);
         }
@@ -529,13 +535,12 @@ public ActionResult NewBillingAddress(CheckoutBillingAddressModel model)
 
         public ActionResult ShippingAddress()
         {
-            //validation
 			var cart = _workContext.CurrentCustomer.GetCartItems(ShoppingCartType.ShoppingCart, _storeContext.CurrentStore.Id);
 
 			if (cart.Count == 0)
                 return RedirectToRoute("ShoppingCart");
 
-            if ((_workContext.CurrentCustomer.IsGuest() && !_orderSettings.AnonymousCheckoutAllowed))
+            if (_workContext.CurrentCustomer.IsGuest() && !_orderSettings.AnonymousCheckoutAllowed)
                 return new HttpUnauthorizedResult();
 
             if (!cart.RequiresShipping())
@@ -545,7 +550,6 @@ public ActionResult ShippingAddress()
                 return RedirectToAction("ShippingMethod");
             }
 
-            //model
             var model = PrepareShippingAddressModel();
             return View(model);
         }
@@ -980,7 +984,7 @@ public ActionResult CheckoutProgress(CheckoutProgressStep step)
 
             return PartialView(model);
         }
+        
         #endregion
-
     }
 }
diff --git a/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs b/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs
index 21fdd3e78d..3313cc158e 100644
--- a/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs
+++ b/src/Presentation/SmartStore.Web/Controllers/CustomerController.cs
@@ -1361,6 +1361,7 @@ public ActionResult AddressAdd()
 
             var model = new CustomerAddressEditModel();
             model.Address.PrepareModel(null, false, _addressSettings, _localizationService, _stateProvinceService, () => _countryService.GetAllCountries());
+            model.Address.Email = customer?.Email;
 
             return View(model);
         }

From 3734b2d15404e54cc9934cf680b8515276c1b4c4 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Mon, 8 Oct 2018 12:50:27 +0200
Subject: [PATCH 56/71] #425 Updates two unclear string resources

---
 .../SmartStore.Data/Migrations/MigrationsConfiguration.cs | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs b/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
index c3970d15b8..3ff6e108d7 100644
--- a/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
+++ b/src/Libraries/SmartStore.Data/Migrations/MigrationsConfiguration.cs
@@ -569,6 +569,14 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder)
 
             builder.AddOrUpdate("Common.Voting", "Voting", "Abstimmung");
             builder.AddOrUpdate("Common.Answer", "Answer", "Antwort");
+
+            builder.AddOrUpdate("Admin.Configuration.Settings.CustomerUser.CustomerFormFields.Description",
+                "Manage form fields that are displayed during registration.",
+                "Verwalten Sie Formularfelder, die während der Registrierung angezeigt werden.");
+
+            builder.AddOrUpdate("Admin.Configuration.Settings.CustomerUser.AddressFormFields.Description",
+                "Manage form fields that are displayed during checkout and on \"My account\" page.",
+                "Verwalten Sie Formularfelder, die während des Checkout-Prozesses und im \"Mein Konto\" Bereich angezeigt werden.");
         }
     }
 }

From eb922b0e1bd9e396bbf9b6c7658660f9b35926dc Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Mon, 8 Oct 2018 19:56:31 +0200
Subject: [PATCH 57/71] More on "Breadcrumb of an associated product should
 include the grouped product if it has no assigned categories"

---
 .../SmartStore.Web/Controllers/ProductController.cs       | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/Presentation/SmartStore.Web/Controllers/ProductController.cs b/src/Presentation/SmartStore.Web/Controllers/ProductController.cs
index e2e77bbcde..2591bfcc9b 100644
--- a/src/Presentation/SmartStore.Web/Controllers/ProductController.cs
+++ b/src/Presentation/SmartStore.Web/Controllers/ProductController.cs
@@ -125,11 +125,11 @@ public ActionResult ProductDetails(int productId, string attributes, ProductVari
 			if (!product.Published && !_services.Permissions.Authorize(StandardPermissionProvider.ManageCatalog))
 				return HttpNotFound();
 
-			//ACL (access control list)
+			// ACL (access control list)
 			if (!_aclService.Authorize(product))
 				return HttpNotFound();
 
-			//Store mapping
+			// Store mapping
 			if (!_storeMappingService.Authorize(product))
 				return HttpNotFound();
 
@@ -172,13 +172,15 @@ public ActionResult ProductDetails(int productId, string attributes, ProductVari
 			{
 				_helper.GetCategoryBreadCrumb(0, productId).Select(x => x.Value).Each(x => _breadcrumb.Track(x));
 
-                // Add parent product if product has no category assigned.
+                // Add trail of parent product if product has no category assigned.
                 var hasTrail = _breadcrumb.Trail?.Any() ?? false;
                 if (!hasTrail)
                 {
                     var parentGroupedProduct = _productService.GetProductById(product.ParentGroupedProductId);
                     if (parentGroupedProduct != null)
                     {
+                        _helper.GetCategoryBreadCrumb(0, parentGroupedProduct.Id).Select(x => x.Value).Each(x => _breadcrumb.Track(x));
+
                         _breadcrumb.Track(new MenuItem
                         {
                             Text = parentGroupedProduct.GetLocalized(x => x.Name),

From 652cf161d7f4de12bfbb52b706ece8ff55e011fc Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Tue, 9 Oct 2018 11:47:52 +0200
Subject: [PATCH 58/71] Removed an unused private method

---
 .../Messages/MessageContext.cs                | 23 ++++---------------
 1 file changed, 5 insertions(+), 18 deletions(-)

diff --git a/src/Libraries/SmartStore.Services/Messages/MessageContext.cs b/src/Libraries/SmartStore.Services/Messages/MessageContext.cs
index 9d3014b713..056ab70126 100644
--- a/src/Libraries/SmartStore.Services/Messages/MessageContext.cs
+++ b/src/Libraries/SmartStore.Services/Messages/MessageContext.cs
@@ -1,5 +1,4 @@
 using System;
-using System.Collections.Generic;
 using System.Globalization;
 using SmartStore.Core.Domain.Customers;
 using SmartStore.Core.Domain.Localization;
@@ -10,11 +9,11 @@
 
 namespace SmartStore.Services.Messages
 {
-	/// <summary>
-	/// A context object which contains all required and optional information
-	/// for the creation of message templates.
-	/// </summary>
-	public class MessageContext
+    /// <summary>
+    /// A context object which contains all required and optional information
+    /// for the creation of message templates.
+    /// </summary>
+    public class MessageContext
 	{
 		private IFormatProvider _formatProvider;
 
@@ -88,18 +87,6 @@ public IFormatProvider FormatProvider
 			}
 		}
 
-		private IFormatProvider GetFormatProvider(MessageContext messageContext)
-		{
-			var culture = messageContext.Language.LanguageCulture;
-
-			if (LocalizationHelper.IsValidCultureCode(culture))
-			{
-				return CultureInfo.GetCultureInfo(culture);
-			}
-
-			return CultureInfo.CurrentCulture;
-		}
-
 		public static MessageContext Create(string messageTemplateName, int languageId, int? storeId = null, Customer customer = null)
 		{
 			return new MessageContext

From e59f7e4e1f6f9e96faa3c45091e49579e102fc7f Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Wed, 10 Oct 2018 02:45:31 +0200
Subject: [PATCH 59/71] Storytelling (wip)

---
 .../SmartStore.Web.Framework/UI/Blocks/IBlockHandler.cs          | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockHandler.cs b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockHandler.cs
index 370a4e1b42..867d97ed5d 100644
--- a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockHandler.cs
+++ b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockHandler.cs
@@ -8,6 +8,7 @@ public enum StoryViewMode
 	{
 		Public,
 		Preview,
+		GridEdit,
 		Edit
 	}
 

From ba131a7a7d5de6472f65dd167b8df76405314613 Mon Sep 17 00:00:00 2001
From: Marcus  Gesing <home@footwear-box.de>
Date: Thu, 11 Oct 2018 20:02:00 +0200
Subject: [PATCH 60/71] Dialog to create an import profile was out of function

---
 .../Administration/Views/Import/List.cshtml   | 34 +++++++++++--------
 1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/src/Presentation/SmartStore.Web/Administration/Views/Import/List.cshtml b/src/Presentation/SmartStore.Web/Administration/Views/Import/List.cshtml
index fcca0e6992..97060764d4 100644
--- a/src/Presentation/SmartStore.Web/Administration/Views/Import/List.cshtml
+++ b/src/Presentation/SmartStore.Web/Administration/Views/Import/List.cshtml
@@ -113,13 +113,12 @@ else
 	</div>
 }
 
-<form method="POST" action="@Url.Action("Create", "Import", new { area = "Admin" })">
-	@{Html.SmartStore().Window()
-		.Name("import-profile-dialog")
-		.Title(T("Common.Profile") + " - " + T("Admin.Common.AddNew"))
-		.RenderAtPageEnd(false)
-		.HtmlAttribute("data-profile", T("Common.Profile").Text)
-		.Content(@<text>
+@{Html.SmartStore().Window()
+	.Name("import-profile-dialog")
+	.Title(T("Common.Profile") + " - " + T("Admin.Common.AddNew"))
+	.HtmlAttribute("data-profile", T("Common.Profile").Text)
+	.Content(@<text>
+        <form method="POST" action="@Url.Action("Create", "Import", new { area = "Admin" })" class="import-profile-form">
 			<p class="text-muted">
 				@T("Admin.DataExchange.Import.ProfileCreationNote")
 			</p>
@@ -146,14 +145,14 @@ else
 					&nbsp;
 				</div>
 			</div>
-		</text>)
-		.FooterContent(@<text>
-			<button class="btn btn-secondary btn-flat" data-dismiss="modal">@T("Common.Cancel")</button>
-			<button type="submit" class="btn btn-primary" disabled="disabled">@T("Common.OK")</button>
-		</text>)
-		.Render();
-	}
-</form>
+        </form>
+	</text>)
+	.FooterContent(@<text>
+		<button class="btn btn-secondary btn-flat" data-dismiss="modal">@T("Common.Cancel")</button>
+		<button type="button" class="btn btn-primary" disabled="disabled">@T("Common.OK")</button>
+	</text>)
+	.Render();
+}
 
 <script>
 	window['onUploadCompleted'] = function (e, el, data) {
@@ -175,6 +174,11 @@ else
 			e.preventDefault();
 			$('#import-profile-dialog').modal('show');
 			return false;
+        });
+
+		// submit dialog form
+        $('#import-profile-dialog').on('click', '.btn-primary', function () {
+			$('#import-profile-dialog').find('.import-profile-form').submit();
 		});
 
 		// start task

From 48996e3062a04342379a3151e3cb03dbb2b13fcd Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Fri, 12 Oct 2018 03:35:21 +0200
Subject: [PATCH 61/71] min, max, step params for numeric textbox editor

---
 .../SmartStore.Web/Views/Shared/EditorTemplates/Boolean.cshtml | 3 +--
 .../SmartStore.Web/Views/Shared/EditorTemplates/Byte.cshtml    | 1 +
 .../SmartStore.Web/Views/Shared/EditorTemplates/Decimal.cshtml | 3 +++
 .../SmartStore.Web/Views/Shared/EditorTemplates/Double.cshtml  | 3 +++
 .../SmartStore.Web/Views/Shared/EditorTemplates/Int32.cshtml   | 3 +++
 5 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Boolean.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Boolean.cshtml
index 23e4e0c0fc..7ca9bc1e7f 100644
--- a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Boolean.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Boolean.cshtml
@@ -1,5 +1,4 @@
-@functions{
-    
+@functions{    
     private bool? Value
     {
         get
diff --git a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Byte.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Byte.cshtml
index e1085d1bf2..c7360886a3 100644
--- a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Byte.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Byte.cshtml
@@ -44,6 +44,7 @@
 			.EmptyMessage(T("Common.EnterValue"))
 			.MinValue(0)
 			.MaxValue(255)
+			.IncrementStep(ViewData["step"].Convert<byte?>() ?? 1)
 			.Value(Value)
 	)
 
diff --git a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Decimal.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Decimal.cshtml
index 4c93f01990..efce4fc607 100644
--- a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Decimal.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Decimal.cshtml
@@ -43,6 +43,9 @@
 			.Name(ViewData.TemplateInfo.GetFullHtmlFieldName(string.Empty))
 			.EmptyMessage(T("Common.EnterValue"))
 			.Value(Value)
+			.MinValue(ViewData["min"].Convert<decimal?>())
+			.MaxValue(ViewData["max"].Convert<decimal?>())
+			.IncrementStep(ViewData["step"].Convert<decimal?>() ?? 1)
 			.DecimalDigits(4)   //always display 4 digits
 	)
 
diff --git a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Double.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Double.cshtml
index 8946e81ae3..2396030733 100644
--- a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Double.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Double.cshtml
@@ -43,6 +43,9 @@
 			.Name(ViewData.TemplateInfo.GetFullHtmlFieldName(string.Empty))
 			.EmptyMessage(T("Common.EnterValue"))
 			.Value(Value)
+			.MinValue(ViewData["min"].Convert<double?>())
+			.MaxValue(ViewData["max"].Convert<double?>())
+			.IncrementStep(ViewData["step"].Convert<double?>() ?? 1)
 			.DecimalDigits(4)   //always display 4 digits
 	)
 
diff --git a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Int32.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Int32.cshtml
index e70f0e6446..166826c1c8 100644
--- a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Int32.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Int32.cshtml
@@ -42,6 +42,9 @@
 	@(Html.Telerik().IntegerTextBox()
 			.Name(ViewData.TemplateInfo.GetFullHtmlFieldName(string.Empty))
 			.EmptyMessage(T("Common.EnterValue"))
+			.MinValue(ViewData["min"].Convert<int?>())
+			.MaxValue(ViewData["max"].Convert<int?>())
+			.IncrementStep(ViewData["step"].Convert<int?>() ?? 1)
 			.Value(Value)
 	)
 

From 456887d8219120df978b1e9445cb62db1b5385c7 Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Fri, 12 Oct 2018 03:35:54 +0200
Subject: [PATCH 62/71] New EditorTemplate "Range"

---
 .../Extensions/RouteExtensions.cs             |  3 +-
 .../Extensions/TypeExtensions.cs              | 29 +++++++++++++++-
 .../Views/Shared/EditorTemplates/Range.cshtml | 34 +++++++++++++++++++
 3 files changed, 63 insertions(+), 3 deletions(-)
 create mode 100644 src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Range.cshtml

diff --git a/src/Libraries/SmartStore.Core/Extensions/RouteExtensions.cs b/src/Libraries/SmartStore.Core/Extensions/RouteExtensions.cs
index 70bbe2eb28..e57d2ca275 100644
--- a/src/Libraries/SmartStore.Core/Extensions/RouteExtensions.cs
+++ b/src/Libraries/SmartStore.Core/Extensions/RouteExtensions.cs
@@ -9,8 +9,7 @@ public static class RouteExtensions
 	{
 		public static string GetAreaName(this RouteData routeData)
 		{
-			object area;
-			if (routeData.DataTokens.TryGetValue("area", out area))
+			if (routeData.DataTokens.TryGetValue("area", out object area))
 			{
 				return (area as string);
 			}
diff --git a/src/Libraries/SmartStore.Core/Extensions/TypeExtensions.cs b/src/Libraries/SmartStore.Core/Extensions/TypeExtensions.cs
index d2b270c7e5..41b1e64e44 100644
--- a/src/Libraries/SmartStore.Core/Extensions/TypeExtensions.cs
+++ b/src/Libraries/SmartStore.Core/Extensions/TypeExtensions.cs
@@ -26,7 +26,34 @@ public static string AssemblyQualifiedNameWithoutVersion(this Type type)
 	        return null;
         }
 
-        public static bool IsSequenceType(this Type type)
+		public static bool IsNumericType(this Type type)
+		{
+			switch (Type.GetTypeCode(type))
+			{
+				case TypeCode.Byte:
+				case TypeCode.SByte:
+				case TypeCode.UInt16:
+				case TypeCode.UInt32:
+				case TypeCode.UInt64:
+				case TypeCode.Int16:
+				case TypeCode.Int32:
+				case TypeCode.Int64:
+				case TypeCode.Decimal:
+				case TypeCode.Double:
+				case TypeCode.Single:
+					return true;
+				case TypeCode.Object:
+					if (type.IsNullable(out var innerType))
+					{
+						return innerType.IsNumericType();
+					}
+					return false;
+				default:
+					return false;
+			}
+		}
+
+		public static bool IsSequenceType(this Type type)
         {
 			if (type == typeof(string))
 				return false;
diff --git a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Range.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Range.cshtml
new file mode 100644
index 0000000000..f532432349
--- /dev/null
+++ b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Range.cshtml
@@ -0,0 +1,34 @@
+@model object
+
+@using System.Globalization;
+
+@{ 
+	if (Model == null || !Model.GetType().IsNumericType() || Model.GetType().IsGenericType)
+	{
+		//throw new InvalidOperationException("The model item to be used in a range editor must be numeric and non-nullable.");
+	}
+
+	var containerCssClass = "range-slider";
+	if (ViewData.ContainsKey("class"))
+	{
+		containerCssClass += " " + ViewData["class"].ToString();
+	}
+
+	var sliderCssClass = "form-control{0} form-control-range px-0".FormatInvariant(ViewData.ContainsKey("size") ? "-" + ViewData["size"].ToString() : "");
+
+	var id = ViewData.TemplateInfo.GetFullHtmlFieldId(string.Empty);
+	var name = ViewData.TemplateInfo.GetFullHtmlFieldName(string.Empty);
+
+	var metadataValues = ViewData.ModelMetadata.AdditionalValues;
+
+	var min = (ViewData["min"].Convert<decimal?>() ?? metadataValues.Get("min").Convert<decimal?>() ?? 0m).ToString(CultureInfo.InvariantCulture);
+	var max = (ViewData["max"].Convert<decimal?>() ?? metadataValues.Get("max").Convert<decimal?>() ?? 100m).ToString(CultureInfo.InvariantCulture);
+	var step = (ViewData["step"].Convert<decimal?>() ?? metadataValues.Get("step").Convert<decimal?>() ?? 1m).ToString(CultureInfo.InvariantCulture);
+
+	var invariantValue = ViewData.Model.Convert<decimal>().ToString(CultureInfo.InvariantCulture);
+}
+
+<div class="@containerCssClass" style="--slider-value: @invariantValue">
+	@Html.Hidden(string.Empty, ViewData.Model)
+	<input type="range" class="@sliderCssClass" data-target="#@id" min="@min" max="@max" step="@step" value="@invariantValue" />
+</div>
\ No newline at end of file

From dda751d4ef5e3c2ba4f7b99f52f96b49f0af2d6b Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Fri, 12 Oct 2018 03:36:20 +0200
Subject: [PATCH 63/71] Compact version of FileUploader component

---
 .../UI/Components/FileUploader/FileUploader.cs            | 1 +
 .../UI/Components/FileUploader/FileUploaderBuilder.cs     | 6 ++++++
 .../Views/Shared/Components/FileUploader.cshtml           | 8 ++++----
 3 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/src/Presentation/SmartStore.Web.Framework/UI/Components/FileUploader/FileUploader.cs b/src/Presentation/SmartStore.Web.Framework/UI/Components/FileUploader/FileUploader.cs
index 0616d36231..73f3d991e3 100644
--- a/src/Presentation/SmartStore.Web.Framework/UI/Components/FileUploader/FileUploader.cs
+++ b/src/Presentation/SmartStore.Web.Framework/UI/Components/FileUploader/FileUploader.cs
@@ -37,6 +37,7 @@ public string UploadUrl
 		public ButtonStyle ButtonStyle { get; set; }
 		public bool ButtonOutlineStyle { get; set; }
 		public bool ShowRemoveButton { get; set; }
+		public bool Compact { get; set; }
 
 		public string CancelText { get; set; }
 		public string RemoveText { get; set; }
diff --git a/src/Presentation/SmartStore.Web.Framework/UI/Components/FileUploader/FileUploaderBuilder.cs b/src/Presentation/SmartStore.Web.Framework/UI/Components/FileUploader/FileUploaderBuilder.cs
index 761a51bcf1..2784575e45 100644
--- a/src/Presentation/SmartStore.Web.Framework/UI/Components/FileUploader/FileUploaderBuilder.cs
+++ b/src/Presentation/SmartStore.Web.Framework/UI/Components/FileUploader/FileUploaderBuilder.cs
@@ -53,6 +53,12 @@ public FileUploaderBuilder<TModel> ShowRemoveButtonAfterUpload(bool value)
 			return this;
 		}
 
+		public FileUploaderBuilder<TModel> Compact(bool value)
+		{
+			base.Component.Compact = value;
+			return this;
+		}
+
 		public FileUploaderBuilder<TModel> AcceptedFileTypes(string value)
 		{
 			if (value.IsEmpty())
diff --git a/src/Presentation/SmartStore.Web/Views/Shared/Components/FileUploader.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/Components/FileUploader.cshtml
index 6f568e86b9..83db6b39cf 100644
--- a/src/Presentation/SmartStore.Web/Views/Shared/Components/FileUploader.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Shared/Components/FileUploader.cshtml
@@ -16,11 +16,11 @@
 
 <div @Html.Attrs(Model.HtmlAttributes)>
 	<div class="col-auto">
-		<button class="btn btn-danger remove@(Model.ShowRemoveButton ? "" : " hide")">
+		<button class="btn btn-danger remove@(Model.ShowRemoveButton ? "" : " hide")@(Model.Compact ? " btn-sm" : "")">
 			<span>@Model.RemoveText</span>
 		</button>
 
-		<span class="btn btn-@(Model.ButtonOutlineStyle ? "outline-" : "")@Model.ButtonStyle.ToString().ToLower() fileinput-button">
+		<span class="btn btn-@(Model.ButtonOutlineStyle ? "outline-" : "")@Model.ButtonStyle.ToString().ToLower() fileinput-button@(Model.Compact ? " btn-sm" : "")">
 			@if (Model.IconCssClass.HasValue())
 			{
 				<i class="@Model.IconCssClass"></i>
@@ -29,7 +29,7 @@
 			<input type="file" id="@(Model.Id)-file" name="@(Model.Id)-file" />
 		</span>
 
-		<button class="btn btn-outline-secondary cancel hide">
+		<button class="btn btn-outline-secondary cancel hide@(Model.Compact ? " btn-sm" : "")">
 			<span>@Model.CancelText</span>
 		</button>
 	</div>
@@ -39,7 +39,7 @@
 		<div class="fileupload-progress fade">
 			<!-- The global progress bar -->
 			<div class="progress">
-				<div class="progress-bar x-bg-gray" role="progressbar" style="width: 0%" aria-valuemin="0" aria-valuemax="100"></div>
+				<div class="progress-bar" role="progressbar" style="width: 0%" aria-valuemin="0" aria-valuemax="100"></div>
 			</div>
 
 			<!-- The extended global progress information -->

From b6e437fbe1a4f05dbf7873f60e6c0bf3fe78bad8 Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Fri, 12 Oct 2018 03:37:02 +0200
Subject: [PATCH 64/71] Backend theming: made buttons slightly rounded

---
 .../Administration/Content/_variables.scss           | 12 ++++++------
 .../SmartStore.Web/Content/shared/_forms.scss        |  1 -
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/src/Presentation/SmartStore.Web/Administration/Content/_variables.scss b/src/Presentation/SmartStore.Web/Administration/Content/_variables.scss
index cd940a8f7d..5e0ee904b4 100644
--- a/src/Presentation/SmartStore.Web/Administration/Content/_variables.scss
+++ b/src/Presentation/SmartStore.Web/Administration/Content/_variables.scss
@@ -133,9 +133,9 @@ $input-btn-line-height:         1.5;
 $input-box-shadow:              none;
 $input-focus-border-color:		lighten($sm-blue2, 30%);
 $input-focus-box-shadow:        none;
-$input-border-radius:           0;
-$input-border-radius-lg:        0;
-$input-border-radius-sm:        0;
+$input-border-radius:           2px;
+$input-border-radius-lg:        3px;
+$input-border-radius-sm:        2px;
 $input-transition:              none;
 $input-group-addon-bg:			$gray-100;
 
@@ -145,9 +145,9 @@ $btn-box-shadow:				inset 0 0 0 rgba(#fff, 0.15), 0 0 0 rgba(#000, 0.075);
 $btn-focus-box-shadow:			$input-btn-focus-box-shadow;
 //$btn-active-box-shadow:         inset 0 2px 3px rgba(#000, .125);
 $btn-transition:				background-color .05s ease-in-out, border-color .05s ease-in-out, box-shadow .05s ease-in-out;
-$btn-border-radius:				0; //.125rem;
-$btn-border-radius-lg:          0; //.1875rem;
-$btn-border-radius-sm:          0; //.125rem;
+$btn-border-radius:				$input-border-radius; //.125rem;
+$btn-border-radius-lg:          $input-border-radius-lg; //.1875rem;
+$btn-border-radius-sm:          $input-border-radius-sm; //.125rem;
 $btn-disabled-opacity:			0.5;
 
 $dropdown-box-shadow:			0 3px 12px rgba(27,31,35, 0.15); //0 2px 6px rgba(#000, .15);
diff --git a/src/Presentation/SmartStore.Web/Content/shared/_forms.scss b/src/Presentation/SmartStore.Web/Content/shared/_forms.scss
index 3745cec8f7..940816a2ad 100644
--- a/src/Presentation/SmartStore.Web/Content/shared/_forms.scss
+++ b/src/Presentation/SmartStore.Web/Content/shared/_forms.scss
@@ -133,7 +133,6 @@ fieldset.content-group {
 }
 
 
-//
 // Validation
 // ------------------------------------------------------
 

From c0b973daac5c755058758cb30285815de43369b0 Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Fri, 12 Oct 2018 03:37:31 +0200
Subject: [PATCH 65/71] Color opacity mode for new Range editor

---
 .../Scripts/admin.globalinit.js               | 13 +++++++++++++
 .../smartstore.globalization.adapter.js       | 19 +++++++++++++------
 2 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/src/Presentation/SmartStore.Web/Administration/Scripts/admin.globalinit.js b/src/Presentation/SmartStore.Web/Administration/Scripts/admin.globalinit.js
index d66b1ead3f..5e3296d96c 100644
--- a/src/Presentation/SmartStore.Web/Administration/Scripts/admin.globalinit.js
+++ b/src/Presentation/SmartStore.Web/Administration/Scripts/admin.globalinit.js
@@ -117,6 +117,19 @@
             }
 		});
 
+        // Range slider
+        $(document).on('input', '.range-slider > .form-control-range[data-target]', function (e) {
+            // move invariant value from slider to an associated hidden field
+            // as formatted value. Client validation will fail otherwise.
+            var el = $(this);
+
+            if (el.parent().is('.color-opacity-slider')) {
+                el.parent().css('--slider-value', el.val());
+            }
+
+            $(el.data('target')).val(SmartStore.globalization.formatNumber(parseFloat(el.val())));
+        });
+
 		// Because we restyled the grid, the filter dropdown does not position
 		// correctly anymore. We have to reposition it.
 		Hacks.Telerik.handleGridFilter();
diff --git a/src/Presentation/SmartStore.Web/Scripts/smartstore.globalization.adapter.js b/src/Presentation/SmartStore.Web/Scripts/smartstore.globalization.adapter.js
index 92586dc4fa..e76aeb9c75 100644
--- a/src/Presentation/SmartStore.Web/Scripts/smartstore.globalization.adapter.js
+++ b/src/Presentation/SmartStore.Web/Scripts/smartstore.globalization.adapter.js
@@ -55,18 +55,25 @@
 		}
 
 		// Adapt to jQuery validate
-		if (typeof $.validator !== undefined) {
-			$.extend($.validator.methods, {
-				number: function (value, element) {
-					return this.optional(element) || !isNaN(g.parseFloat(value));
+        if (typeof $.validator !== undefined) {
+
+            function _getValue(value, element) {
+                return $(element).is('[type=range]')
+                    ? parseFloat(value)
+                    : g.parseFloat(value);
+            }
+
+            $.extend($.validator.methods, {
+                number: function (value, element) {
+                    return this.optional(element) || !isNaN(_getValue(value, element));
 				},
 				date: function (value, element) {
 					if (this.optional(element)) return true;
 					var validPatterns = ['L LTS', 'L LT', 'L', 'LTS', 'LT'];
 					return moment(value, $(element).data('format') || validPatterns, true /* exact */).isValid();
 				},
-				range: function (value, element, param) {
-					var val = g.parseFloat(value);
+                range: function (value, element, param) {
+                    var val = _getValue(value, element);
 					return this.optional(element) || (val >= param[0] && val <= param[1]);
 				}
 			});

From 849efdf0f69a928317fe3321ba054275d7d37176 Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Fri, 12 Oct 2018 03:39:22 +0200
Subject: [PATCH 66/71] AdminControllerBase now takes new "NonAdminAttribute"
 into account before setting IWorkContext.IsAdmin to true

---
 .../Controllers/AdminControllerBase.cs        | 42 +++++++++----------
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/src/Presentation/SmartStore.Web.Framework/Controllers/AdminControllerBase.cs b/src/Presentation/SmartStore.Web.Framework/Controllers/AdminControllerBase.cs
index 8f7c1412fd..0511597b70 100644
--- a/src/Presentation/SmartStore.Web.Framework/Controllers/AdminControllerBase.cs
+++ b/src/Presentation/SmartStore.Web.Framework/Controllers/AdminControllerBase.cs
@@ -19,6 +19,11 @@
 
 namespace SmartStore.Web.Framework.Controllers
 {
+	[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
+	public sealed class NonAdminAttribute : Attribute
+	{
+	}
+
 	[AdminValidateIpAddress(Order = 100)]
 	[RequireHttpsByConfig(SslRequirement.Yes, Order = 110)]
     [CustomerLastActivity(Order = 100)]
@@ -26,27 +31,22 @@ namespace SmartStore.Web.Framework.Controllers
 	[AdminThemed(Order = -1)]
 	public abstract class AdminControllerBase : SmartController
     { 
-        /// <summary>
-        /// Initialize controller
-        /// </summary>
-        /// <param name="requestContext">Request context</param>
-        protected override void Initialize(RequestContext requestContext)
-        {
-			var routeData = requestContext.RouteData;
-			if (routeData != null && !routeData.DataTokens.ContainsKey("ParentActionViewContext"))
-			{
-				EngineContext.Current.Resolve<IWorkContext>().IsAdmin = true;
-			}
-            base.Initialize(requestContext);
-        }
-        
-        /// <summary>
-        /// Add locales for localizable entities
-        /// </summary>
-        /// <typeparam name="TLocalizedModelLocal">Localizable model</typeparam>
-        /// <param name="languageService">Language service</param>
-        /// <param name="locales">Locales</param>
-        protected virtual void AddLocales<TLocalizedModelLocal>(ILanguageService languageService, IList<TLocalizedModelLocal> locales) where TLocalizedModelLocal : ILocalizedModelLocal
+		protected override void OnActionExecuting(ActionExecutingContext filterContext)
+		{
+			if (filterContext.IsChildAction)
+				return;
+
+			var isNonAdmin = filterContext.ActionDescriptor.HasAttribute<NonAdminAttribute>(true);
+			Services.Resolve<IWorkContext>().IsAdmin = !isNonAdmin;
+		}
+
+		/// <summary>
+		/// Add locales for localizable entities
+		/// </summary>
+		/// <typeparam name="TLocalizedModelLocal">Localizable model</typeparam>
+		/// <param name="languageService">Language service</param>
+		/// <param name="locales">Locales</param>
+		protected virtual void AddLocales<TLocalizedModelLocal>(ILanguageService languageService, IList<TLocalizedModelLocal> locales) where TLocalizedModelLocal : ILocalizedModelLocal
         {
             AddLocales(languageService, locales, null);
         }

From eb909bdcff676d7cd2f4990e3e85f543c12f6324 Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Fri, 12 Oct 2018 03:40:50 +0200
Subject: [PATCH 67/71] "nowidgets" query bypasses rendering of request scoped
 widgets (required for frontend pages embedded in a backend IFrame)

---
 .../SmartStore.Web.Framework/UI/WidgetProvider.cs  | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/src/Presentation/SmartStore.Web.Framework/UI/WidgetProvider.cs b/src/Presentation/SmartStore.Web.Framework/UI/WidgetProvider.cs
index 425a8ec920..5e842f0af4 100644
--- a/src/Presentation/SmartStore.Web.Framework/UI/WidgetProvider.cs
+++ b/src/Presentation/SmartStore.Web.Framework/UI/WidgetProvider.cs
@@ -14,13 +14,15 @@ namespace SmartStore.Web.Framework.UI
 	public class WidgetProvider : IWidgetProvider
 	{
 		private readonly IApplicationEnvironment _env;
+		private readonly HttpRequestBase _httpRequest;
 
 		private Multimap<string, WidgetRouteInfo> _zoneWidgetsMap = new Multimap<string, WidgetRouteInfo>();
 		private Multimap<Regex, WidgetRouteInfo> _zoneExpressionWidgetsMap = new Multimap<Regex, WidgetRouteInfo>();
 
-		public WidgetProvider(IApplicationEnvironment env)
+		public WidgetProvider(IApplicationEnvironment env, HttpRequestBase httpRequest)
 		{
 			_env = env;
+			_httpRequest = httpRequest;
 		}
 
 		public void RegisterAction(string[] widgetZones, string actionName, string controllerName, RouteValueDictionary routeValues, int order = 0)
@@ -29,6 +31,11 @@ public void RegisterAction(string[] widgetZones, string actionName, string contr
 			Guard.NotEmpty(actionName, nameof(actionName));
 			Guard.NotEmpty(controllerName, nameof(controllerName));
 
+			if (_httpRequest.QueryString["nowidgets"] != null)
+			{
+				return;
+			}
+
 			if (_zoneWidgetsMap == null)
 			{
 				_zoneWidgetsMap = new Multimap<string, WidgetRouteInfo>();
@@ -55,6 +62,11 @@ public void RegisterAction(Regex widgetZoneExpression, string actionName, string
 			Guard.NotEmpty(actionName, nameof(actionName));
 			Guard.NotEmpty(controllerName, nameof(controllerName));
 
+			if (_httpRequest.QueryString["nowidgets"] != null)
+			{
+				return;
+			}
+
 			if (_zoneExpressionWidgetsMap == null)
 			{
 				_zoneExpressionWidgetsMap = new Multimap<Regex, WidgetRouteInfo>();

From 2288225bf581d332f66722860fec8f9a964c6a3a Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Fri, 12 Oct 2018 03:42:51 +0200
Subject: [PATCH 68/71] (perf) prevent libSass file globbing mess (checking
 files again and again even if they exist)

---
 .../Assets/BundlingVirtualPathProvider.cs     | 169 +++++++++++++++++-
 .../Theming/ThemeHelper.cs                    |  77 ++++----
 .../Administration/Content/_admin.scss        |  37 +++-
 src/Presentation/SmartStore.Web/Global.asax   |   2 +-
 .../SmartStore.Web/SmartStore.Web.csproj      |   1 +
 .../Shared/EditorTemplates/Picture.cshtml     |   9 +
 src/Presentation/SmartStore.Web/Web.config    |   6 +-
 7 files changed, 249 insertions(+), 52 deletions(-)

diff --git a/src/Presentation/SmartStore.Web.Framework/Theming/Assets/BundlingVirtualPathProvider.cs b/src/Presentation/SmartStore.Web.Framework/Theming/Assets/BundlingVirtualPathProvider.cs
index af308fdb66..7ae70c3a2c 100644
--- a/src/Presentation/SmartStore.Web.Framework/Theming/Assets/BundlingVirtualPathProvider.cs
+++ b/src/Presentation/SmartStore.Web.Framework/Theming/Assets/BundlingVirtualPathProvider.cs
@@ -1,27 +1,71 @@
 using System;
 using System.Collections;
+using System.Collections.Generic;
 using System.Linq;
+using System.IO;
 using System.Web.Caching;
 using System.Web.Hosting;
+using SmartStore.Core.Infrastructure;
 
 namespace SmartStore.Web.Framework.Theming.Assets
 {
-    public sealed class BundlingVirtualPathProvider : ThemingVirtualPathProvider
-    {
-        public BundlingVirtualPathProvider(VirtualPathProvider previous)
+	public sealed class BundlingVirtualPathProvider : ThemingVirtualPathProvider
+	{
+		private readonly SassCheckedPathStack _sassCheckedPathStack;
+
+		private string _yoooooo;
+
+		public BundlingVirtualPathProvider(VirtualPathProvider previous)
 			: base(previous)
         {
-        }
+			_sassCheckedPathStack = new SassCheckedPathStack();
+		}
 
         public override bool FileExists(string virtualPath)
         {
+			var exists = false;
 			var styleResult = ThemeHelper.IsStyleSheet(virtualPath);
-			if (styleResult != null && (styleResult.IsThemeVars || styleResult.IsModuleImports))
+
+			TokenizedSassPath sassPath = null;
+
+			if (styleResult != null)
 			{
-				return true;
+				exists = _sassCheckedPathStack.Check(styleResult, out sassPath);
+				if (exists)
+				{
+					// It seems awkward to return false when check result actually says true.
+					// But true in this context means: a check for THIS sass file pattern (e.g. _slick.scss.sass)
+					// yielded true previously (because _slick.scss really exists on disks), therefore _slick.scss.sass
+					// CANNOT exist (or SHOULD not by convention). By returning false we prevent that a real filesystem check
+					// is made against _slick.scss.sass (which is huge performace saver considering that IThemeFileResolver
+					// also does some additional checks).
+					return false;
+				}
+
+				if (styleResult.IsThemeVars || styleResult.IsModuleImports)
+				{
+					_sassCheckedPathStack.PushExistingPath(sassPath);
+					return true;
+				}
+			}
+
+			//if (virtualPath.Contains("slick.scss"))
+			//{
+			//	var xxx = true;
+			////	throw new Exception("dfsfs");
+			//}
+
+			//System.Diagnostics.Debug.WriteLine("VPATH: " + virtualPath);
+			_yoooooo += virtualPath + Environment.NewLine;
+
+			exists = base.FileExists(virtualPath);
+
+			if (exists && sassPath != null)
+			{
+				_sassCheckedPathStack.PushExistingPath(sassPath);
 			}
 
-			return base.FileExists(virtualPath);
+			return exists;
         }
          
         public override VirtualFile GetFile(string virtualPath)
@@ -118,4 +162,115 @@ public override CacheDependency GetCacheDependency(string virtualPath, IEnumerab
 			return null;
         }
     }
+
+	internal class SassCheckedPathStack
+	{
+		private readonly string[] _styleExtensions = new[] { ".scss", ".sass", ".css" };
+
+		private readonly ContextState<Stack<TokenizedSassPath>> _state 
+			= new ContextState<Stack<TokenizedSassPath>>("SassCheckedPathStack.State", () => new Stack<TokenizedSassPath>());
+
+		public SassCheckedPathStack()
+		{
+		}
+
+		/// <summary>
+		/// Checks last path existence
+		/// </summary>
+		/// <returns>true = does exist, no need to check | false = not checked yet</returns>
+		public bool Check(StyleSheetResult styleResult, out TokenizedSassPath path)
+		{
+			path = new TokenizedSassPath(styleResult);
+
+			var state = _state.GetState();
+			if (state.Count == 0)
+				return false;
+
+			var currentPath = path;
+			var lastPath = _state.GetState().Peek();
+
+			if (currentPath.Extension.IsEmpty())
+			{
+				// We dont't allow extension-less Sass files, so no need to check.
+				return true;
+			}
+
+			if (lastPath.Dir != currentPath.Dir)
+			{
+				return false;
+			}
+
+			if (currentPath.StyleResult.IsExplicit && lastPath.StyleResult.IsExplicit && currentPath.FileName == lastPath.FileName)
+			{
+				return true;
+			}
+
+			if (currentPath.StyleResult.IsModuleImports && lastPath.StyleResult.IsModuleImports)
+			{
+				return true;
+			}
+
+			if (currentPath.StyleResult.IsThemeVars && lastPath.StyleResult.IsThemeVars)
+			{
+				return true;
+			}
+
+			// slick.scss.(scss|sass|css) > slick.scss
+			if (Path.GetExtension(currentPath.FileNameWithoutExtension) == ".scss")
+			{
+				return true;
+			}
+
+			// slick.(sass|css) > slick.scss
+			if (!currentPath.StyleResult.IsExplicit && _styleExtensions.Contains(currentPath.Extension) && currentPath.FileNameWithoutExtension == lastPath.FileNameWithoutExtension)
+			{
+				return true;
+			}
+
+			// _slick.scss > slick.scss
+			if (currentPath.FileName.StartsWith("_"))
+			{
+				if (currentPath.FileName.Substring(1) == lastPath.FileName)
+				{
+					return true;
+				}
+			}
+
+			// slick.(scss|sass|css) > _slick.scss
+			if (lastPath.FileNameWithoutExtension.StartsWith("_"))
+			{
+				if (lastPath.FileNameWithoutExtension == "_" + currentPath.FileNameWithoutExtension)
+				{
+					return true;
+				}
+			}
+
+			return false;
+		}
+
+		public void PushExistingPath(TokenizedSassPath path)
+		{
+			_state.GetState().Push(path);
+		}
+	}
+
+	internal class TokenizedSassPath
+	{
+		public TokenizedSassPath(StyleSheetResult styleResult)
+		{
+			StyleResult = styleResult;
+			VirtualPath = styleResult.Path;
+			Extension = styleResult.Extension.EmptyNull();
+			FileName = Path.GetFileName(styleResult.Path);
+			FileNameWithoutExtension = FileName.Substring(0, FileName.Length - Extension.Length);
+			Dir = VirtualPath.Substring(0, VirtualPath.Length - FileName.Length);
+		}
+
+		public StyleSheetResult StyleResult { get; set; }
+		public string VirtualPath { get; private set; }
+		public string Dir { get; private set; }
+		public string FileName { get; private set; }
+		public string FileNameWithoutExtension { get; private set; }
+		public string Extension { get; private set; }
+	}
 }
\ No newline at end of file
diff --git a/src/Presentation/SmartStore.Web.Framework/Theming/ThemeHelper.cs b/src/Presentation/SmartStore.Web.Framework/Theming/ThemeHelper.cs
index 9e5474c48e..949190ae40 100644
--- a/src/Presentation/SmartStore.Web.Framework/Theming/ThemeHelper.cs
+++ b/src/Presentation/SmartStore.Web.Framework/Theming/ThemeHelper.cs
@@ -28,8 +28,8 @@ static ThemeHelper()
 
 			var pattern = @"^{0}(.*)/(.+)(\.)(png|gif|jpg|jpeg|css|scss|js|cshtml|svg|json|liquid)(\?explicit)*$".FormatInvariant(ThemesBasePath);
 			s_inheritableThemeFilePattern = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
-			s_themeVarsPattern = new Regex(@"\.(db|app)/themevars(.scss)$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
-			s_moduleImportsPattern = new Regex(@"\.app/moduleimports.scss$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
+			s_themeVarsPattern = new Regex(@"\.(db|app)/[_]?themevars(.scss)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
+			s_moduleImportsPattern = new Regex(@"\.app/[_]?moduleimports.scss", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
 			s_extensionlessPathPattern = new Regex(@"~/(.+)/([^/.]*)$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
 		}
 
@@ -114,7 +114,7 @@ internal static bool IsStyleValidationRequest()
 			return HttpContext.Current?.Request?.QueryString["validate"] != null;
 		}
 
-		internal static IsStyleSheetResult IsStyleSheet(string path)
+		internal static StyleSheetResult IsStyleSheet(string path)
 		{
 			var extension = Path.GetExtension(path).ToLowerInvariant();
 
@@ -125,14 +125,20 @@ internal static IsStyleSheetResult IsStyleSheet(string path)
 			}
 			else if (extension == ".css")
 			{
-				return new IsStyleSheetResult { Path = path, IsCss = true };
+				return new StyleSheetResult { Path = path, IsCss = true, Extension = extension };
 			}
-			else if (extension == ".scss")
+			else if (extension == ".scss" || extension == ".sass")
 			{
-				return new IsStyleSheetResult { Path = path, IsSass = true };
+				return new StyleSheetResult { Path = path, IsSass = true, Extension = extension };
 			}
 			else if (extension.IsEmpty())
 			{
+				if (path.Contains("/scss/"))
+				{
+					// Bootstrap and other libaries may import SASS files without extension
+					return new StyleSheetResult { Path = path, IsSass = true };
+				}
+				
 				// StyleBundles are  extension-less, so we have to ask 'BundleTable' 
 				// if a style bundle has been registered for the given path.
 				if (s_extensionlessPathPattern.IsMatch(path))
@@ -140,18 +146,20 @@ internal static IsStyleSheetResult IsStyleSheet(string path)
 					var bundle = BundleTable.Bundles.GetBundleFor(path);
 					if (bundle != null && ((bundle is SmartStyleBundle || bundle is StyleBundle)))
 					{
-						return new IsStyleSheetResult { Path = path, IsBundle = true };
+						return new StyleSheetResult { Path = path, IsBundle = true };
 					}
 				}
 			}
-			else if (extension.EndsWith("?explicit"))
+			else if (extension.Contains("?explicit"))
 			{
 				// Handle virtual Sass imports with '?explicit' query
 				// TBD: (mc) other query params could exist
 
 				// Process again, this time without query
 				var pathWithoutQuery = path.Substring(0, path.IndexOf('?'));
-				return IsStyleSheet(pathWithoutQuery);
+				var result = IsStyleSheet(pathWithoutQuery);
+				result.IsExplicit = true;
+				return result;
 			}
 
 			return null;
@@ -187,41 +195,30 @@ internal static string TokenizePath(string virtualPath, out string themeName, ou
 			// strip out query
 			return "{0}{1}/{2}".FormatCurrent(ThemesBasePath, themeName, relativePath);
 		}
+	}
 
-		internal class IsStyleSheetResult
-		{
-			public string Path { get; set; }
-			public bool IsCss { get; set; }
-			public bool IsSass { get; set; }
-			public bool IsBundle { get; set; }
-
-			public string Extension
-			{
-				get
-				{
-					if (IsSass)
-						return ".scss";
-					else if (IsBundle)
-						return "";
-
-					return ".css";
-				}
-			}
+	internal class StyleSheetResult
+	{
+		public string Path { get; set; }
+		public string Extension { get; set; }
+		public bool IsCss { get; set; }
+		public bool IsSass { get; set; }
+		public bool IsBundle { get; set; }
+		public bool IsExplicit { get; set; }
 
-			public bool IsPreprocessor
-			{
-				get { return IsSass; }
-			}
+		public bool IsPreprocessor
+		{
+			get { return IsSass; }
+		}
 
-			public bool IsThemeVars
-			{
-				get { return IsPreprocessor && ThemeHelper.PathIsThemeVars(Path); }
-			}
+		public bool IsThemeVars
+		{
+			get { return IsPreprocessor && ThemeHelper.PathIsThemeVars(Path); }
+		}
 
-			public bool IsModuleImports
-			{
-				get { return IsSass && ThemeHelper.PathIsModuleImports(Path); }
-			}
+		public bool IsModuleImports
+		{
+			get { return IsSass && ThemeHelper.PathIsModuleImports(Path); }
 		}
 	}
 }
diff --git a/src/Presentation/SmartStore.Web/Administration/Content/_admin.scss b/src/Presentation/SmartStore.Web/Administration/Content/_admin.scss
index c0180abd6b..da3b95273e 100644
--- a/src/Presentation/SmartStore.Web/Administration/Content/_admin.scss
+++ b/src/Presentation/SmartStore.Web/Administration/Content/_admin.scss
@@ -432,7 +432,6 @@ legend {
 		transition: all .1s ease-in-out;
 		opacity: 0;
 		text-align: center;
-		/*@extend .col-form-label;*/
 
 		&:hover {
 			color: $gray-600;
@@ -448,6 +447,42 @@ legend {
 	}
 }
 
+.range-slider {
+    position: relative;
+
+    &.color-opacity-slider {
+        /*border: $input-border-width solid $input-border-color;
+        border-radius: $input-border-radius;*/
+
+        &:after,
+        &:before {
+            position: absolute;
+            content: ' ';
+            left: 0;
+            top: 0;
+            right: 0;
+            bottom: 0;
+            z-index: -1;
+        }
+
+        &:after {
+            border: $input-border-width solid $input-border-color;
+            border-radius: $input-border-radius;
+        }
+
+        &:before {
+            left: 1px;
+            top: 1px;
+            right: 1px;
+            bottom: 1px;
+            overflow: hidden;
+            background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAIAAAD/gAIDAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3ggRDQA1Yl77tAAAAN1JREFUeNrt1rEJwCAURVEVFwruv4BEMtGHdGJpF4LHLqQ7+OTm3u+0nNau9XOMx995SnK2DyxYsD4/OSK86Jt/3SwzhAXrT6d60RW8GcKCpeAVvPtihrBgKXgFb4YIYMFS8AreDGEhgKXgFbwZwoKFQMEreDOEBUvBe9EVvBnCgqXgFbz7YoawYCl4BW+GCGDBUvAK3gxhIYCl4BW8GcKChUDBK3gzhAVLwXvRFbwZwoKl4BW8+2KGsGApeAVvhghgwVLwCt4MYSGApeAVvBnCgoVAwSt4M4QF6/jzAlCrcKXDcpR1AAAAAElFTkSuQmCC');
+            background-repeat: repeat;
+            opacity: calc(1 - var(--slider-value, 0));
+        }
+    }
+}
+
 
 //
 // Multi-store settings
diff --git a/src/Presentation/SmartStore.Web/Global.asax b/src/Presentation/SmartStore.Web/Global.asax
index ebaeaa3f40..612debf2a2 100644
--- a/src/Presentation/SmartStore.Web/Global.asax
+++ b/src/Presentation/SmartStore.Web/Global.asax
@@ -1 +1 @@
-<%@ Application Codebehind="Global.asax.cs" Inherits="SmartStore.Web.MvcApplication" Language="C#" %> 
+<%@ Application Codebehind="Global.asax.cs" Inherits="SmartStore.Web.MvcApplication" Language="C#" %>
diff --git a/src/Presentation/SmartStore.Web/SmartStore.Web.csproj b/src/Presentation/SmartStore.Web/SmartStore.Web.csproj
index 0a9ee64ef5..b0e5cc8985 100644
--- a/src/Presentation/SmartStore.Web/SmartStore.Web.csproj
+++ b/src/Presentation/SmartStore.Web/SmartStore.Web.csproj
@@ -1768,6 +1768,7 @@
     <Content Include="Views\Boards\Partials\SearchHits.cshtml" />
     <Content Include="Views\Shared\Partials\Customer.Avatar.cshtml" />
     <Content Include="Views\Shared\Layouts\_Layout.Bare.cshtml" />
+    <Content Include="Views\Shared\EditorTemplates\Range.cshtml" />
     <None Include="Web.EFMigrations.config">
       <DependentUpon>Web.config</DependentUpon>
     </None>
diff --git a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Picture.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Picture.cshtml
index 5bd494ff9a..3b4294d2a5 100644
--- a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Picture.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Picture.cshtml
@@ -23,6 +23,14 @@
 			return true;
 		}
 	}
+
+	private bool Compact
+	{
+		get
+		{
+			return ViewData["compact"].Convert<bool?>() == true;
+		}
+	}
 }
 
 @{
@@ -46,6 +54,7 @@
 			.AcceptedFileTypes("gif|jpe?g|png")
 			.ShowRemoveButton(picture != null)
 			.ShowRemoveButtonAfterUpload(true)
+			.Compact(ViewData["compact"].Convert<bool?>() == true)
 			.OnUploadCompletedHandlerName("onUploadCompleted_" + random)
 		)
 	</div>
diff --git a/src/Presentation/SmartStore.Web/Web.config b/src/Presentation/SmartStore.Web/Web.config
index ad41f1171d..1d04a910d6 100644
--- a/src/Presentation/SmartStore.Web/Web.config
+++ b/src/Presentation/SmartStore.Web/Web.config
@@ -11,7 +11,7 @@
     </sectionGroup>
   </configSections>
   <appSettings>
-    <add key="webpages:Version" value="3.0.0.0" />
+    <add key="webpages:Version" value="3.0.0.0" /> 
     <add key="webpages:Enabled" value="false" />
     <add key="PreserveLoginUrl" value="true" />
     <add key="ClientValidationEnabled" value="true" /> 
@@ -22,7 +22,7 @@
     <add key="GoogleMerchantKey" value="" />
     <add key="GoogleEnvironment" value="Sandbox" />
     <add key="GoogleAuthenticateCallback" value="True" />
-    <add key="log4net.Config" value="Config\log4net.config" /> 
+    <add key="log4net.Config" value="Config\log4net.config" />
     <add key="sm:ApplicationName" value="SmartStore.NET" />
     <add key="sm:EnableDynamicDiscovery" value="true" />
     <add key="sm:EngineType" value="" />
@@ -79,7 +79,7 @@
     <sessionState configSource="Config\SessionState.config" />
     <trace enabled="true" localOnly="true" pageOutput="true" requestLimit="40" />
     <httpRuntime targetFramework="4.5.2" maxRequestLength="1536000" executionTimeout="5400" maxQueryStringLength="16384" fcnMode="Single" />
-    <compilation debug="true" targetFramework="4.6.1" numRecompilesBeforeAppRestart="257" batch="true" optimizeCompilations="true">
+    <compilation debug="true" targetFramework="4.6.1" numRecompilesBeforeAppRestart="258" batch="true" optimizeCompilations="true">
       <assemblies>
         <add assembly="System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
         <add assembly="System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />

From 027a554e91f41a7837b888d6b7075eba318c2c3a Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Fri, 12 Oct 2018 17:38:45 +0200
Subject: [PATCH 69/71] Minor refactoring in block interfaces

---
 .../SmartStore.Web.Framework/UI/Blocks/BlockHandlerBase.cs  | 6 +++---
 .../SmartStore.Web.Framework/UI/Blocks/IBlockHandler.cs     | 5 +++--
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockHandlerBase.cs b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockHandlerBase.cs
index b94ab59af3..a43347aa1d 100644
--- a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockHandlerBase.cs
+++ b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/BlockHandlerBase.cs
@@ -62,12 +62,12 @@ public virtual void Save(T block, IBlockEntity entity)
 			entity.Model = JsonConvert.SerializeObject(block, Formatting.None, settings);
 		}
 
-		public void Render(IBlockContainer element, string[] templates, HtmlHelper htmlHelper)
+		public void Render(IBlockContainer element, IEnumerable<string> templates, HtmlHelper htmlHelper)
 		{
 			RenderCore(element, templates, htmlHelper, htmlHelper.ViewContext.Writer);
 		}
 
-		public IHtmlString ToHtmlString(IBlockContainer element, string[] templates, HtmlHelper htmlHelper)
+		public IHtmlString ToHtmlString(IBlockContainer element, IEnumerable<string> templates, HtmlHelper htmlHelper)
 		{
 			using (var writer = new StringWriter(CultureInfo.CurrentCulture))
 			{
@@ -76,7 +76,7 @@ public IHtmlString ToHtmlString(IBlockContainer element, string[] templates, Htm
 			}
 		}
 
-		protected virtual void RenderCore(IBlockContainer element, string[] templates, HtmlHelper htmlHelper, TextWriter textWriter)
+		protected virtual void RenderCore(IBlockContainer element, IEnumerable<string> templates, HtmlHelper htmlHelper, TextWriter textWriter)
 		{
 			Guard.NotNull(element, nameof(element));
 			Guard.NotNull(templates, nameof(templates));
diff --git a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockHandler.cs b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockHandler.cs
index 867d97ed5d..bb932356f1 100644
--- a/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockHandler.cs
+++ b/src/Presentation/SmartStore.Web.Framework/UI/Blocks/IBlockHandler.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Generic;
 using System.Web;
 using System.Web.Mvc;
 
@@ -14,8 +15,8 @@ public enum StoryViewMode
 
 	public interface IBlockHandler
 	{
-		void Render(IBlockContainer element, string[] templates, HtmlHelper htmlHeper);
-		IHtmlString ToHtmlString(IBlockContainer element, string[] templates, HtmlHelper htmlHelper);
+		void Render(IBlockContainer element, IEnumerable<string> templates, HtmlHelper htmlHeper);
+		IHtmlString ToHtmlString(IBlockContainer element, IEnumerable<string> templates, HtmlHelper htmlHelper);
 	}
 
 	public interface IBlockHandler<T> : IBlockHandler where T : IBlock

From f506c117d8f308b0832429bd29d01b4bc2e17c16 Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Sat, 13 Oct 2018 01:15:58 +0200
Subject: [PATCH 70/71] Fixed EfDbCache mem leak (hopefully)

---
 .../SmartStore.Core/Caching/RequestCache.cs   |  8 +-
 .../Caching/DbCacheExtensions.cs              | 82 +++++++------------
 .../SmartStore.Data/Caching/IDbCache.cs       |  2 +-
 3 files changed, 38 insertions(+), 54 deletions(-)

diff --git a/src/Libraries/SmartStore.Core/Caching/RequestCache.cs b/src/Libraries/SmartStore.Core/Caching/RequestCache.cs
index cb05f3f288..5fb74d2400 100644
--- a/src/Libraries/SmartStore.Core/Caching/RequestCache.cs
+++ b/src/Libraries/SmartStore.Core/Caching/RequestCache.cs
@@ -8,7 +8,7 @@
 
 namespace SmartStore.Core.Caching
 {
-	public class RequestCache : IRequestCache
+	public class RequestCache : DisposableObject, IRequestCache
 	{
 		const string RegionName = "SmartStoreNET:";
 
@@ -124,5 +124,11 @@ private string BuildKey(string key)
 		{
 			return RegionName + key.EmptyNull();
 		}
+
+		protected override void OnDispose(bool disposing)
+		{
+			if (disposing)
+				Clear();
+		}
 	}
 }
diff --git a/src/Libraries/SmartStore.Data/Caching/DbCacheExtensions.cs b/src/Libraries/SmartStore.Data/Caching/DbCacheExtensions.cs
index a53b2597af..cdb68ddb14 100644
--- a/src/Libraries/SmartStore.Data/Caching/DbCacheExtensions.cs
+++ b/src/Libraries/SmartStore.Data/Caching/DbCacheExtensions.cs
@@ -116,8 +116,7 @@ internal static DbCacheEntry GetCacheEntry<T>(this IQueryable<T> source, string
 				return null;
 			}
 			
-			DbCacheEntry entry;
-			if (!cache.RequestTryGet(cacheKey.Key, out entry))
+			if (!cache.RequestTryGet(cacheKey.Key, out var entry))
 			{
 				entry = cache.RequestPut(cacheKey.Key, valueFactory(), cacheKey.AffectedEntitySets);
 			}
@@ -196,73 +195,52 @@ public static IQueryable<T> Cached<T>(this IQueryable<T> source)
 
 		private class CacheKey<T>
 		{
-			private readonly IQueryable<T> _source;
-			private string _key;
-			private string[] _affectedEntitySets;
-			private ObjectQuery _objectQuery;
-			private bool _objectQueryResolved;
-
 			public CacheKey(IQueryable<T> source, string customKey = null)
 			{
 				Guard.NotNull(source, nameof(source));
 
-				_source = source;
-				_key = customKey.NullEmpty();
+				GenerateKeyAndAffectedEntitySets(source, customKey);
 			}
 
-			private void EnsureObjectQuery()
+			private void GenerateKeyAndAffectedEntitySets(IQueryable<T> source, string customKey = null)
 			{
-				if (!_objectQueryResolved && _objectQuery == null)
-				{
-					_objectQuery = DbCacheUtil.GetObjectQuery(_source) ?? _source as ObjectQuery;
-					_objectQueryResolved = true;
-				}
-			}
+				var objectQuery = DbCacheUtil.GetObjectQuery(source) ?? source as ObjectQuery;
 
-			public string Key
-			{
-				get
+				var key = customKey.NullEmpty();
+				if (objectQuery != null && string.IsNullOrEmpty(key))
 				{
-					if (_key == null && !_objectQueryResolved)
+					var commandInfo = objectQuery.GetCommandInfo();
+
+					var sb = new StringBuilder();
+					sb.AppendLine(commandInfo.Sql);
+
+					foreach (DbParameter parameter in commandInfo.Parameters)
 					{
-						EnsureObjectQuery();
-						if (_objectQuery != null)
-						{
-							var commandInfo = _objectQuery.GetCommandInfo();
-
-							var sb = new StringBuilder();
-							sb.AppendLine(commandInfo.Sql);
-
-							foreach (DbParameter parameter in commandInfo.Parameters)
-							{
-								sb.Append(parameter.ParameterName);
-								sb.Append(";");
-								sb.Append(parameter.Value);
-								sb.AppendLine(";");
-							}
-
-							_key = sb.ToString();
-						}
+						sb.Append(parameter.ParameterName);
+						sb.Append(";");
+						sb.Append(parameter.Value);
+						sb.AppendLine(";");
 					}
 
-					return _key;
+					key = sb.ToString();
 				}
+
+				Key = key;
+				AffectedEntitySets = objectQuery != null
+					? objectQuery.GetAffectedEntitySets()
+					: new string[0];
 			}
 
-			public string[] AffectedEntitySets
+			public string Key
 			{
-				get
-				{
-					if (_affectedEntitySets == null)
-					{
-						EnsureObjectQuery();
-						_affectedEntitySets = _objectQuery != null
-							? _objectQuery.GetAffectedEntitySets()
-							: new string[0];
-					}
+				get;
+				private set;
+			}
 
-					return _affectedEntitySets;
-				}
+			public string[] AffectedEntitySets
+			{
+				get;
+				private set;
 			}
 		}
 	}
diff --git a/src/Libraries/SmartStore.Data/Caching/IDbCache.cs b/src/Libraries/SmartStore.Data/Caching/IDbCache.cs
index 3ca2c570fb..086fdf447c 100644
--- a/src/Libraries/SmartStore.Data/Caching/IDbCache.cs
+++ b/src/Libraries/SmartStore.Data/Caching/IDbCache.cs
@@ -77,7 +77,7 @@ public interface IDbCache
 		void RequestInvalidateItem(string key);
 	}
 
-	internal class NullDbCache : IDbCache
+	public class NullDbCache : IDbCache
 	{
 		public bool Enabled
 		{

From 950027633b0876d998b6ece27b8cdfdefa6fd189 Mon Sep 17 00:00:00 2001
From: Murat Cakir <muratc@smartstore.de>
Date: Sat, 13 Oct 2018 02:43:55 +0200
Subject: [PATCH 71/71] Redesigned file uploader component

---
 .../Components/FileUploader/FileUploader.cs   |  2 +-
 .../Content/skinning/_fileupload.scss         | 70 ++++++++++++++++-
 .../jquery.fileupload-single-ui.js            | 78 +++++++++----------
 .../Shared/Components/FileUploader.cshtml     | 25 +++---
 .../Shared/EditorTemplates/Picture.cshtml     | 12 +--
 .../Views/Shared/Partials/_ClientRes.cshtml   |  1 +
 6 files changed, 123 insertions(+), 65 deletions(-)

diff --git a/src/Presentation/SmartStore.Web.Framework/UI/Components/FileUploader/FileUploader.cs b/src/Presentation/SmartStore.Web.Framework/UI/Components/FileUploader/FileUploader.cs
index 73f3d991e3..15e4d6915f 100644
--- a/src/Presentation/SmartStore.Web.Framework/UI/Components/FileUploader/FileUploader.cs
+++ b/src/Presentation/SmartStore.Web.Framework/UI/Components/FileUploader/FileUploader.cs
@@ -13,7 +13,7 @@ public FileUploader()
 
 		public FileUploader(Localizer localizer)
         {
-			HtmlAttributes.AppendCssClass("fileupload form-row align-items-center");
+			HtmlAttributes.AppendCssClass("fileupload");
 			HtmlAttributes.Add("data-accept", "gif|jpe?g|png");
 			HtmlAttributes.Add("data-show-remove-after-upload", "false");
 			IconCssClass = "fa fa-upload";
diff --git a/src/Presentation/SmartStore.Web/Content/skinning/_fileupload.scss b/src/Presentation/SmartStore.Web/Content/skinning/_fileupload.scss
index 5ea03a6c59..f10367867c 100644
--- a/src/Presentation/SmartStore.Web/Content/skinning/_fileupload.scss
+++ b/src/Presentation/SmartStore.Web/Content/skinning/_fileupload.scss
@@ -18,11 +18,49 @@
  * http://www.opensource.org/licenses/MIT
  */
 
+ .fileupload-container {
+    position: relative;
+    display: flex;
+    flex-wrap: nowrap;
+    border: $input-border-width solid $input-border-color;
+    background-color: $input-bg;
+    border-radius: $input-border-radius;
+    overflow: hidden;
+
+    .fileupload-thumb-stage {
+        position: relative;
+        width: 64px;
+        max-width: 64px;
+        border-right: 1px solid rgba(#000, 0.2);
+        background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAIAAAD/gAIDAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3ggRDQA1Yl77tAAAAN1JREFUeNrt1rEJwCAURVEVFwruv4BEMtGHdGJpF4LHLqQ7+OTm3u+0nNau9XOMx995SnK2DyxYsD4/OSK86Jt/3SwzhAXrT6d60RW8GcKCpeAVvPtihrBgKXgFb4YIYMFS8AreDGEhgKXgFbwZwoKFQMEreDOEBUvBe9EVvBnCgqXgFbz7YoawYCl4BW+GCGDBUvAK3gxhIYCl4BW8GcKChUDBK3gzhAVLwXvRFbwZwoKl4BW8+2KGsGApeAVvhghgwVLwCt4MYSGApeAVvBnCgoVAwSt4M4QF6/jzAlCrcKXDcpR1AAAAAElFTkSuQmCC') repeat;
+    }
+
+    .fileupload-thumb {
+        position: absolute;
+        left: 0;
+        top: 0;
+        width: 100%;
+        height: 100%;
+        background-size: contain;
+        background-position: center;
+        background-repeat: no-repeat;
+    }
+
+    .fileupload-controls {
+        flex-grow: 1;
+        padding: 0.5rem 0.5rem;
+    }
+ }
+
 .fileupload {
 	.btn.cancel {
 		display: none;
 	}
 
+    .fileupload-buttons {
+        position: relative;
+    }
+
 	.fileinput-button {
 		position: relative;
 		overflow: hidden;
@@ -42,9 +80,35 @@
 		cursor: pointer;
 	}
 
-	.fileupload-progress .progress {
-		margin-bottom: 6px;
-	}
+    > .fileupload-progress {
+        position: absolute;
+        left: 0;
+        bottom: -1px;
+        right: 0;  
+        
+	    .progress {
+            height: 0.25rem;
+		    background: transparent;
+            margin: 0;
+            border-radius: 0;
+            border-bottom-left-radius: $input-border-radius;
+            border-bottom-right-radius: $input-border-radius;
+            box-shadow: none;
+
+            .progress-bar {
+                background-color: $primary;
+                transition: width 0.25s ease, background-color 0.25s ease;
+            }
+	    }
+
+        &.success {
+            transition-delay: 0.4s;
+        }
+
+        &.success .progress-bar {
+            background-color: $success !important;
+        }
+    }
 }
 
 
diff --git a/src/Presentation/SmartStore.Web/Content/vendors/fileuploader/jquery.fileupload-single-ui.js b/src/Presentation/SmartStore.Web/Content/vendors/fileuploader/jquery.fileupload-single-ui.js
index f99e4d4cad..8277cf3a04 100644
--- a/src/Presentation/SmartStore.Web/Content/vendors/fileuploader/jquery.fileupload-single-ui.js
+++ b/src/Presentation/SmartStore.Web/Content/vendors/fileuploader/jquery.fileupload-single-ui.js
@@ -39,22 +39,15 @@
 
         _transition: function (node) {
             var dfd = $.Deferred();
-            if ($.support.transition && node.hasClass('fade')) {
-                node.on(
-                    $.support.transitionEnd,
-                    function (e) {
-                        // Make sure we don't respond to other transitions events
-                        // in the container element, e.g. from button elements:
-                        if (e.target === node[0]) {
-                        	node.off($.support.transitionEnd);
-                            dfd.resolveWith(node);
-                        }
-                    }
-                ).toggleClass('show in');
-            } else {
-                node.toggleClass('show in');
-                dfd.resolveWith(node);
-            }
+            node.on(Prefixer.event.transitionEnd, function (e) {
+                // Make sure we don't respond to other transitions events
+                // in the container element, e.g. from button elements:
+                if (e.target === node[0]) {
+                    node.off(Prefixer.event.transitionEnd);
+                    dfd.resolveWith(node);
+                }
+            }).addClass('success').removeClass("show");
+
             return dfd;
         },
 
@@ -128,7 +121,7 @@
             	    }
 
             	    toggleButtons(true);
-            	    el.find('.fileupload-progress').addClass("show in");
+            	    el.find('.fileupload-progress').addClass("show");
 
             	    if (data.dataType && data.dataType.substr(0, 6) === 'iframe') {
             	        // Iframe Transport does not support progress events.
@@ -143,36 +136,41 @@
             	    //console.log("fail");
             	})
 			    .on(pre + 'always.' + ns, function (e, data) {
-			        var elProgress = el.find('.fileupload-progress');
-			        if (!elProgress.hasClass("show in")) {
+                    var elProgress = el.find('.fileupload-progress');
+                    
+                    if (!elProgress.hasClass("show")) {
 			            return
-			        }
-			        self._transition(elProgress).done(
-		                function () {
-		                    toggleButtons(false);
-		                    elProgress
-			                	.find('.progress-bar').attr('aria-valuenow', 0)
-			                  	.css("width", "0%");
-		                    elProgress
-			                	.find('.progress-extended').html('&nbsp;');
-		                }
-	                );
+                    }
+
+                    self._transition(elProgress)
+                        .done(function () {
+                            toggleButtons(false);
+                            elProgress
+                                .removeClass('success')
+                                .find('.progress-bar')
+                                .attr('aria-valuenow', 0)
+                                .css("width", "0%")
+                                .find('.progress-extended').html('&nbsp;');
+                        });
 			    })
 			    .on(pre + 'progressall.' + ns, function (e, data) {
 			        var elProgress = el.find('.fileupload-progress'),
 	            		progress = parseInt(data.loaded / data.total * 100, 10),
 	                    extendedProgressNode = elProgress.find('.progress-extended');
 
-			        if (extendedProgressNode.length) {
-			            extendedProgressNode.html(self._getProgressInfo(data));
-			        }
+                    if (extendedProgressNode.length) {
+                        extendedProgressNode.html(self._getProgressInfo(data));
+                    }
+                    else {
+                        console.debug(self._getProgressInfo(data));
+                    }
 
 			        elProgress
 	                    .find('.progress-bar')
 	                    .attr('aria-valuenow', progress)
 	                    .css('width', progress + '%');
 			    })
-            // cancel button
+                // cancel button
                 .on('click.' + ns, 'button.cancel', eventData, function (e) {
                     e.preventDefault();
                     var data = el.data('data') || {};
@@ -204,10 +202,6 @@
                 .parent().addClass('disabled');
         },
 
-        /*_create: function () {
-        parentWidget.prototype._create.call(this);
-        },*/
-
         enable: function () {
             var wasDisabled = false;
             if (this.options.disabled) {
@@ -247,7 +241,7 @@
 				send: function (e, data) {
 					if (options.onUploading) options.onUploading.apply(this, [e, el, data]);
 				},
-				done: function (e, data) {
+                done: function (e, data) {
 					var result = data.result;
 					if (result.success) {
 
@@ -256,7 +250,7 @@
 						}
 
 						var cnt = el.closest('.fileupload-container');
-						cnt.find('.img-thumbnail').attr('src', data.result.imageUrl);
+						cnt.find('.fileupload-thumb').css('background-image', 'url("' + data.result.imageUrl + '")');
 						cnt.find('.hidden').val(data.result.pictureId);
 
 						elCancel.addClass("hide");
@@ -273,7 +267,7 @@
 						if (options.onError) options.onError.apply(this, [el, textStatus, errorThrown]);
 					}
 				},
-				always: function (e, data) {
+                always: function (e, data) {
 					if (options.onCompleted) options.onCompleted.apply(this, [e, el, data]);
 				}
 			};
@@ -286,7 +280,7 @@
 				e.preventDefault();
 
 				var cnt = el.closest('.fileupload-container');
-				cnt.find('.img-thumbnail').attr('src', el.data('fallback-url'));
+				cnt.find('.fileupload-thumb').css('background-image', 'url("' + el.data('fallback-url') + '")');
 				cnt.find('.hidden').val(0);
 				$(this).addClass("hide");
 				if (options.onFileRemove) options.onFileRemove.apply(this, [e, el]);
diff --git a/src/Presentation/SmartStore.Web/Views/Shared/Components/FileUploader.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/Components/FileUploader.cshtml
index 83db6b39cf..c41bef7f05 100644
--- a/src/Presentation/SmartStore.Web/Views/Shared/Components/FileUploader.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Shared/Components/FileUploader.cshtml
@@ -15,7 +15,17 @@
 }
 
 <div @Html.Attrs(Model.HtmlAttributes)>
-	<div class="col-auto">
+	<!-- The global progress information -->
+	<div class="fileupload-progress fade">
+		<!-- The global progress bar -->
+		<div class="progress">
+			<div class="progress-bar" role="progressbar" style="width: 0%" aria-valuemin="0" aria-valuemax="100"></div>
+		</div>
+
+		@*<div class="progress-extended fs-xs text-muted text-truncate">&nbsp;</div>*@
+	</div>
+
+	<div class="fileupload-buttons">
 		<button class="btn btn-danger remove@(Model.ShowRemoveButton ? "" : " hide")@(Model.Compact ? " btn-sm" : "")">
 			<span>@Model.RemoveText</span>
 		</button>
@@ -33,19 +43,6 @@
 			<span>@Model.CancelText</span>
 		</button>
 	</div>
-
-	<div class="col">
-		<!-- The global progress information -->
-		<div class="fileupload-progress fade">
-			<!-- The global progress bar -->
-			<div class="progress">
-				<div class="progress-bar" role="progressbar" style="width: 0%" aria-valuemin="0" aria-valuemax="100"></div>
-			</div>
-
-			<!-- The extended global progress information -->
-			<div class="progress-extended fs-xs text-muted text-truncate">&nbsp;</div>
-		</div>
-	</div>
 </div>
 
 @using (Html.BeginZoneContent("end"))
diff --git a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Picture.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Picture.cshtml
index 3b4294d2a5..f2d04cbe0c 100644
--- a/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Picture.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Shared/EditorTemplates/Picture.cshtml
@@ -41,13 +41,15 @@
 	var picture = pictureService.GetPictureById(pictureId);
 }
 
-<div class="form-row align-items-center fileupload-container">
-	<div class="col-auto">
-		@Html.HiddenFor(x => x, new { @class = "hidden" })
-		<img src="@Url.Picture(pictureId, mediaSettings.ProductThumbPictureSize)" style="max-width: 100px; max-height: 64px" class="img-thumbnail" alt="" />
+<div class="fileupload-container">
+	<div class="fileupload-thumb-stage">
+		<div class="fileupload-thumb" style="background-image: url('@Url.Picture(pictureId, mediaSettings.ProductThumbPictureSize)')">
+			@Html.HiddenFor(x => x, new { @class = "hidden" })
+			@*<img src="@Url.Picture(pictureId, mediaSettings.ProductThumbPictureSize)" style="max-width: 64px; max-height: 64px" class="yimg-thumbnail" alt="" />*@
+		</div>
 	</div>
 
-	<div class="col">
+	<div class="fileupload-controls">
 		@(Html.SmartStore().FileUploader()
 			.UploadUrl(Url.Action("AsyncUpload", "Picture", new { isTransient = TransientUpload, validate = ValidatePicture, area = "Admin" }))
 			.HtmlAttribute("data-fallback-url", pictureService.GetFallbackUrl(mediaSettings.ProductThumbPictureSize))
diff --git a/src/Presentation/SmartStore.Web/Views/Shared/Partials/_ClientRes.cshtml b/src/Presentation/SmartStore.Web/Views/Shared/Partials/_ClientRes.cshtml
index 4e609a7d06..11c2cba0b9 100644
--- a/src/Presentation/SmartStore.Web/Views/Shared/Partials/_ClientRes.cshtml
+++ b/src/Presentation/SmartStore.Web/Views/Shared/Partials/_ClientRes.cshtml
@@ -25,6 +25,7 @@
 		"jquery.Validate.Range",
 		"Jquery.Validate.Max",
 		"Jquery.Validate.Min",
+		"Admin.Common.AreYouSure"
 	};
 }