using Microsoft.AspNetCore.Mvc.Rendering; using Nop.Core.Domain.Catalog; using Nop.Core.Domain.Customers; using Nop.Core.Domain.News; using Nop.Services.Customers; using Nop.Services.Helpers; using Nop.Services.Html; using Nop.Services.Localization; using Nop.Services.News; using Nop.Services.Seo; using Nop.Services.Stores; using Nop.Web.Areas.Admin.Infrastructure.Mapper.Extensions; using Nop.Web.Areas.Admin.Models.News; using Nop.Web.Framework.Extensions; using Nop.Web.Framework.Factories; using Nop.Web.Framework.Models.Extensions; namespace Nop.Web.Areas.Admin.Factories; /// /// Represents the news model factory implementation /// public partial class NewsModelFactory : INewsModelFactory { #region Fields protected readonly CatalogSettings _catalogSettings; protected readonly IBaseAdminModelFactory _baseAdminModelFactory; protected readonly ICustomerService _customerService; protected readonly IDateTimeHelper _dateTimeHelper; protected readonly IHtmlFormatter _htmlFormatter; protected readonly ILanguageService _languageService; protected readonly ILocalizationService _localizationService; protected readonly INewsService _newsService; protected readonly IStoreMappingSupportedModelFactory _storeMappingSupportedModelFactory; protected readonly IStoreService _storeService; protected readonly IUrlRecordService _urlRecordService; #endregion #region Ctor public NewsModelFactory(CatalogSettings catalogSettings, IBaseAdminModelFactory baseAdminModelFactory, ICustomerService customerService, IDateTimeHelper dateTimeHelper, IHtmlFormatter htmlFormatter, ILanguageService languageService, ILocalizationService localizationService, INewsService newsService, IStoreMappingSupportedModelFactory storeMappingSupportedModelFactory, IStoreService storeService, IUrlRecordService urlRecordService) { _catalogSettings = catalogSettings; _customerService = customerService; _baseAdminModelFactory = baseAdminModelFactory; _dateTimeHelper = dateTimeHelper; _htmlFormatter = htmlFormatter; _languageService = languageService; _localizationService = localizationService; _newsService = newsService; _storeMappingSupportedModelFactory = storeMappingSupportedModelFactory; _storeService = storeService; _urlRecordService = urlRecordService; } #endregion #region Methods /// /// Prepare news content model /// /// News content model /// Filter by news item ID /// /// A task that represents the asynchronous operation /// The task result contains the news content model /// public virtual async Task PrepareNewsContentModelAsync(NewsContentModel newsContentModel, int? filterByNewsItemId) { ArgumentNullException.ThrowIfNull(newsContentModel); //prepare nested search models await PrepareNewsItemSearchModelAsync(newsContentModel.NewsItems); var newsItem = await _newsService.GetNewsByIdAsync(filterByNewsItemId ?? 0); await PrepareNewsCommentSearchModelAsync(newsContentModel.NewsComments, newsItem); return newsContentModel; } /// /// Prepare paged news item list model /// /// News item search model /// /// A task that represents the asynchronous operation /// The task result contains the news item list model /// public virtual async Task PrepareNewsItemListModelAsync(NewsItemSearchModel searchModel) { ArgumentNullException.ThrowIfNull(searchModel); //get news items var newsItems = await _newsService.GetAllNewsAsync(showHidden: true, storeId: searchModel.SearchStoreId, pageIndex: searchModel.Page - 1, pageSize: searchModel.PageSize, title: searchModel.SearchTitle); //prepare list model var model = await new NewsItemListModel().PrepareToGridAsync(searchModel, newsItems, () => { return newsItems.SelectAwait(async newsItem => { //fill in model values from the entity var newsItemModel = newsItem.ToModel(); //little performance optimization: ensure that "Full" is not returned newsItemModel.Full = string.Empty; //convert dates to the user time if (newsItem.StartDateUtc.HasValue) newsItemModel.StartDateUtc = await _dateTimeHelper.ConvertToUserTimeAsync(newsItem.StartDateUtc.Value, DateTimeKind.Utc); if (newsItem.EndDateUtc.HasValue) newsItemModel.EndDateUtc = await _dateTimeHelper.ConvertToUserTimeAsync(newsItem.EndDateUtc.Value, DateTimeKind.Utc); newsItemModel.CreatedOn = await _dateTimeHelper.ConvertToUserTimeAsync(newsItem.CreatedOnUtc, DateTimeKind.Utc); //fill in additional values (not existing in the entity) newsItemModel.SeName = await _urlRecordService.GetSeNameAsync(newsItem, newsItem.LanguageId, true, false); newsItemModel.LanguageName = (await _languageService.GetLanguageByIdAsync(newsItem.LanguageId))?.Name; newsItemModel.ApprovedComments = await _newsService.GetNewsCommentsCountAsync(newsItem, isApproved: true); newsItemModel.NotApprovedComments = await _newsService.GetNewsCommentsCountAsync(newsItem, isApproved: false); return newsItemModel; }); }); return model; } /// /// Prepare news item model /// /// News item model /// News item /// Whether to exclude populating of some properties of model /// /// A task that represents the asynchronous operation /// The task result contains the news item model /// public virtual async Task PrepareNewsItemModelAsync(NewsItemModel model, NewsItem newsItem, bool excludeProperties = false) { //fill in model values from the entity if (newsItem != null) { if (model == null) { model = newsItem.ToModel(); model.SeName = await _urlRecordService.GetSeNameAsync(newsItem, newsItem.LanguageId, true, false); } model.StartDateUtc = newsItem.StartDateUtc; model.EndDateUtc = newsItem.EndDateUtc; } //set default values for the new model if (newsItem == null) { model.Published = true; model.AllowComments = true; } //prepare available languages await _baseAdminModelFactory.PrepareLanguagesAsync(model.AvailableLanguages, false); //prepare available stores await _storeMappingSupportedModelFactory.PrepareModelStoresAsync(model, newsItem, excludeProperties); return model; } /// /// Prepare news comment search model /// /// News comment search model /// News item /// /// A task that represents the asynchronous operation /// The task result contains the news comment search model /// public virtual async Task PrepareNewsCommentSearchModelAsync(NewsCommentSearchModel searchModel, NewsItem newsItem) { ArgumentNullException.ThrowIfNull(searchModel); //prepare "approved" property (0 - all; 1 - approved only; 2 - disapproved only) searchModel.AvailableApprovedOptions.Add(new SelectListItem { Text = await _localizationService.GetResourceAsync("Admin.ContentManagement.News.Comments.List.SearchApproved.All"), Value = "0" }); searchModel.AvailableApprovedOptions.Add(new SelectListItem { Text = await _localizationService.GetResourceAsync("Admin.ContentManagement.News.Comments.List.SearchApproved.ApprovedOnly"), Value = "1" }); searchModel.AvailableApprovedOptions.Add(new SelectListItem { Text = await _localizationService.GetResourceAsync("Admin.ContentManagement.News.Comments.List.SearchApproved.DisapprovedOnly"), Value = "2" }); searchModel.NewsItemId = newsItem?.Id; //prepare page parameters searchModel.SetGridPageSize(); return searchModel; } /// /// Prepare paged news comment list model /// /// News comment search model /// News item Id; pass null to prepare comment models for all news items /// /// A task that represents the asynchronous operation /// The task result contains the news comment list model /// public virtual async Task PrepareNewsCommentListModelAsync(NewsCommentSearchModel searchModel, int? newsItemId) { ArgumentNullException.ThrowIfNull(searchModel); //get parameters to filter comments var createdOnFromValue = searchModel.CreatedOnFrom == null ? null : (DateTime?)_dateTimeHelper.ConvertToUtcTime(searchModel.CreatedOnFrom.Value, await _dateTimeHelper.GetCurrentTimeZoneAsync()); var createdOnToValue = searchModel.CreatedOnTo == null ? null : (DateTime?)_dateTimeHelper.ConvertToUtcTime(searchModel.CreatedOnTo.Value, await _dateTimeHelper.GetCurrentTimeZoneAsync()).AddDays(1); var isApprovedOnly = searchModel.SearchApprovedId == 0 ? null : searchModel.SearchApprovedId == 1 ? true : (bool?)false; //get comments var comments = (await _newsService.GetAllCommentsAsync(newsItemId: newsItemId, approved: isApprovedOnly, fromUtc: createdOnFromValue, toUtc: createdOnToValue, commentText: searchModel.SearchText)).ToPagedList(searchModel); //prepare store names (to avoid loading for each comment) var storeNames = (await _storeService.GetAllStoresAsync()) .ToDictionary(store => store.Id, store => store.Name); //prepare list model var model = await new NewsCommentListModel().PrepareToGridAsync(searchModel, comments, () => { return comments.SelectAwait(async newsComment => { //fill in model values from the entity var commentModel = newsComment.ToModel(); //convert dates to the user time commentModel.CreatedOn = await _dateTimeHelper.ConvertToUserTimeAsync(newsComment.CreatedOnUtc, DateTimeKind.Utc); //fill in additional values (not existing in the entity) commentModel.NewsItemTitle = (await _newsService.GetNewsByIdAsync(newsComment.NewsItemId))?.Title; if ((await _customerService.GetCustomerByIdAsync(newsComment.CustomerId)) is Customer customer) { commentModel.CustomerInfo = (await _customerService.IsRegisteredAsync(customer)) ? customer.Email : await _localizationService.GetResourceAsync("Admin.Customers.Guest"); } commentModel.CommentText = _htmlFormatter.FormatText(newsComment.CommentText, false, true, false, false, false, false); commentModel.StoreName = storeNames.TryGetValue(newsComment.StoreId, out var value) ? value : "Deleted"; return commentModel; }); }); return model; } /// /// Prepare news item search model /// /// News item search model /// /// A task that represents the asynchronous operation /// The task result contains the news item search model /// public virtual async Task PrepareNewsItemSearchModelAsync(NewsItemSearchModel searchModel) { ArgumentNullException.ThrowIfNull(searchModel); //prepare available stores await _baseAdminModelFactory.PrepareStoresAsync(searchModel.AvailableStores); searchModel.HideStoresList = _catalogSettings.IgnoreStoreLimitations || searchModel.AvailableStores.SelectionIsNotPossible(); //prepare page parameters searchModel.SetGridPageSize(); return searchModel; } #endregion }