using Microsoft.AspNetCore.Mvc; using Nop.Core; using Nop.Core.Domain.Customers; using Nop.Core.Domain.Topics; using Nop.Services.Common; using Nop.Services.Customers; using Nop.Services.Localization; using Nop.Services.Logging; using Nop.Services.Messages; using Nop.Services.Security; using Nop.Services.Seo; using Nop.Services.Stores; using Nop.Services.Topics; using Nop.Web.Areas.Admin.Factories; using Nop.Web.Areas.Admin.Infrastructure.Mapper.Extensions; using Nop.Web.Areas.Admin.Models.Topics; using Nop.Web.Framework.Mvc.Filters; namespace Nop.Web.Areas.Admin.Controllers; public partial class TopicController : BaseAdminController { #region Fields protected readonly IAclService _aclService; protected readonly ICustomerActivityService _customerActivityService; protected readonly ICustomerService _customerService; protected readonly ILocalizationService _localizationService; protected readonly ILocalizedEntityService _localizedEntityService; protected readonly INotificationService _notificationService; protected readonly IPermissionService _permissionService; protected readonly IStoreMappingService _storeMappingService; protected readonly IStoreService _storeService; protected readonly ITopicModelFactory _topicModelFactory; protected readonly ITopicService _topicService; protected readonly IUrlRecordService _urlRecordService; protected readonly IGenericAttributeService _genericAttributeService; protected readonly IWorkContext _workContext; #endregion Fields #region Ctor public TopicController(IAclService aclService, ICustomerActivityService customerActivityService, ICustomerService customerService, ILocalizationService localizationService, ILocalizedEntityService localizedEntityService, INotificationService notificationService, IPermissionService permissionService, IStoreMappingService storeMappingService, IStoreService storeService, ITopicModelFactory topicModelFactory, ITopicService topicService, IUrlRecordService urlRecordService, IGenericAttributeService genericAttributeService, IWorkContext workContext) { _aclService = aclService; _customerActivityService = customerActivityService; _customerService = customerService; _localizationService = localizationService; _localizedEntityService = localizedEntityService; _notificationService = notificationService; _permissionService = permissionService; _storeMappingService = storeMappingService; _storeService = storeService; _topicModelFactory = topicModelFactory; _topicService = topicService; _urlRecordService = urlRecordService; _genericAttributeService = genericAttributeService; _workContext = workContext; } #endregion #region Utilities protected virtual async Task UpdateLocalesAsync(Topic topic, TopicModel model) { foreach (var localized in model.Locales) { await _localizedEntityService.SaveLocalizedValueAsync(topic, x => x.Title, localized.Title, localized.LanguageId); await _localizedEntityService.SaveLocalizedValueAsync(topic, x => x.Body, localized.Body, localized.LanguageId); await _localizedEntityService.SaveLocalizedValueAsync(topic, x => x.MetaKeywords, localized.MetaKeywords, localized.LanguageId); await _localizedEntityService.SaveLocalizedValueAsync(topic, x => x.MetaDescription, localized.MetaDescription, localized.LanguageId); await _localizedEntityService.SaveLocalizedValueAsync(topic, x => x.MetaTitle, localized.MetaTitle, localized.LanguageId); //search engine name var seName = await _urlRecordService.ValidateSeNameAsync(topic, localized.SeName, localized.Title, false); await _urlRecordService.SaveSlugAsync(topic, seName, localized.LanguageId); } } protected virtual async Task SaveStoreMappingsAsync(Topic topic, TopicModel model) { topic.LimitedToStores = model.SelectedStoreIds.Any(); await _topicService.UpdateTopicAsync(topic); var existingStoreMappings = await _storeMappingService.GetStoreMappingsAsync(topic); var allStores = await _storeService.GetAllStoresAsync(); foreach (var store in allStores) { if (model.SelectedStoreIds.Contains(store.Id)) { //new store if (!existingStoreMappings.Any(sm => sm.StoreId == store.Id)) await _storeMappingService.InsertStoreMappingAsync(topic, store.Id); } else { //remove store var storeMappingToDelete = existingStoreMappings.FirstOrDefault(sm => sm.StoreId == store.Id); if (storeMappingToDelete != null) await _storeMappingService.DeleteStoreMappingAsync(storeMappingToDelete); } } } #endregion #region List public virtual IActionResult Index() { return RedirectToAction("List"); } [CheckPermission(StandardPermission.ContentManagement.TOPICS_VIEW)] public virtual async Task List(bool showtour = false) { //prepare model var model = await _topicModelFactory.PrepareTopicSearchModelAsync(new TopicSearchModel()); //show configuration tour if (showtour) { var customer = await _workContext.GetCurrentCustomerAsync(); var hideCard = await _genericAttributeService.GetAttributeAsync(customer, NopCustomerDefaults.HideConfigurationStepsAttribute); var closeCard = await _genericAttributeService.GetAttributeAsync(customer, NopCustomerDefaults.CloseConfigurationStepsAttribute); if (!hideCard && !closeCard) ViewBag.ShowTour = true; } return View(model); } [HttpPost] [CheckPermission(StandardPermission.ContentManagement.TOPICS_VIEW)] public virtual async Task List(TopicSearchModel searchModel) { //prepare model var model = await _topicModelFactory.PrepareTopicListModelAsync(searchModel); return Json(model); } #endregion #region Create / Edit / Delete [CheckPermission(StandardPermission.ContentManagement.TOPICS_CREATE_EDIT_DELETE)] public virtual async Task Create() { //prepare model var model = await _topicModelFactory.PrepareTopicModelAsync(new TopicModel(), null); return View(model); } [HttpPost, ParameterBasedOnFormName("save-continue", "continueEditing")] [CheckPermission(StandardPermission.ContentManagement.TOPICS_CREATE_EDIT_DELETE)] public virtual async Task Create(TopicModel model, bool continueEditing) { if (ModelState.IsValid) { if (!model.IsPasswordProtected) model.Password = null; var topic = model.ToEntity(); await _topicService.InsertTopicAsync(topic); //search engine name model.SeName = await _urlRecordService.ValidateSeNameAsync(topic, model.SeName, topic.Title ?? topic.SystemName, true); await _urlRecordService.SaveSlugAsync(topic, model.SeName, 0); //stores await SaveStoreMappingsAsync(topic, model); //locales await UpdateLocalesAsync(topic, model); _notificationService.SuccessNotification(await _localizationService.GetResourceAsync("Admin.ContentManagement.Topics.Added")); //activity log await _customerActivityService.InsertActivityAsync("AddNewTopic", string.Format(await _localizationService.GetResourceAsync("ActivityLog.AddNewTopic"), topic.Title ?? topic.SystemName), topic); if (!continueEditing) return RedirectToAction("List"); return RedirectToAction("Edit", new { id = topic.Id }); } //prepare model model = await _topicModelFactory.PrepareTopicModelAsync(model, null, true); //if we got this far, something failed, redisplay form return View(model); } [CheckPermission(StandardPermission.ContentManagement.TOPICS_VIEW)] public virtual async Task Edit(int id, bool showtour = false) { //try to get a topic with the specified id var topic = await _topicService.GetTopicByIdAsync(id); if (topic == null) return RedirectToAction("List"); //prepare model var model = await _topicModelFactory.PrepareTopicModelAsync(null, topic); //show configuration tour if (showtour) { var customer = await _workContext.GetCurrentCustomerAsync(); var hideCard = await _genericAttributeService.GetAttributeAsync(customer, NopCustomerDefaults.HideConfigurationStepsAttribute); var closeCard = await _genericAttributeService.GetAttributeAsync(customer, NopCustomerDefaults.CloseConfigurationStepsAttribute); if (!hideCard && !closeCard) ViewBag.ShowTour = true; } return View(model); } [HttpPost, ParameterBasedOnFormName("save-continue", "continueEditing")] [CheckPermission(StandardPermission.ContentManagement.TOPICS_CREATE_EDIT_DELETE)] public virtual async Task Edit(TopicModel model, bool continueEditing) { //try to get a topic with the specified id var topic = await _topicService.GetTopicByIdAsync(model.Id); if (topic == null) return RedirectToAction("List"); if (!model.IsPasswordProtected) model.Password = null; if (ModelState.IsValid) { topic = model.ToEntity(topic); await _topicService.UpdateTopicAsync(topic); //search engine name model.SeName = await _urlRecordService.ValidateSeNameAsync(topic, model.SeName, topic.Title ?? topic.SystemName, true); await _urlRecordService.SaveSlugAsync(topic, model.SeName, 0); //stores await SaveStoreMappingsAsync(topic, model); //locales await UpdateLocalesAsync(topic, model); _notificationService.SuccessNotification(await _localizationService.GetResourceAsync("Admin.ContentManagement.Topics.Updated")); //activity log await _customerActivityService.InsertActivityAsync("EditTopic", string.Format(await _localizationService.GetResourceAsync("ActivityLog.EditTopic"), topic.Title ?? topic.SystemName), topic); if (!continueEditing) return RedirectToAction("List"); return RedirectToAction("Edit", new { id = topic.Id }); } //prepare model model = await _topicModelFactory.PrepareTopicModelAsync(model, topic, true); //if we got this far, something failed, redisplay form return View(model); } [HttpPost] [CheckPermission(StandardPermission.ContentManagement.TOPICS_CREATE_EDIT_DELETE)] public virtual async Task Delete(int id) { //try to get a topic with the specified id var topic = await _topicService.GetTopicByIdAsync(id); if (topic == null) return RedirectToAction("List"); await _topicService.DeleteTopicAsync(topic); _notificationService.SuccessNotification(await _localizationService.GetResourceAsync("Admin.ContentManagement.Topics.Deleted")); //activity log await _customerActivityService.InsertActivityAsync("DeleteTopic", string.Format(await _localizationService.GetResourceAsync("ActivityLog.DeleteTopic"), topic.Title ?? topic.SystemName), topic); return RedirectToAction("List"); } #endregion }