320 lines
13 KiB
C#
320 lines
13 KiB
C#
using System.Text;
|
|
using System.Text.Encodings.Web;
|
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
|
using Nop.Core.Domain.Blogs;
|
|
using Nop.Core.Domain.Catalog;
|
|
using Nop.Core.Domain.Customers;
|
|
using Nop.Services.Blogs;
|
|
using Nop.Services.Customers;
|
|
using Nop.Services.Helpers;
|
|
using Nop.Services.Html;
|
|
using Nop.Services.Localization;
|
|
using Nop.Services.Seo;
|
|
using Nop.Services.Stores;
|
|
using Nop.Web.Areas.Admin.Infrastructure.Mapper.Extensions;
|
|
using Nop.Web.Areas.Admin.Models.Blogs;
|
|
using Nop.Web.Framework.Extensions;
|
|
using Nop.Web.Framework.Factories;
|
|
using Nop.Web.Framework.Models.Extensions;
|
|
|
|
namespace Nop.Web.Areas.Admin.Factories;
|
|
|
|
/// <summary>
|
|
/// Represents the blog model factory implementation
|
|
/// </summary>
|
|
public partial class BlogModelFactory : IBlogModelFactory
|
|
{
|
|
#region Fields
|
|
|
|
protected readonly CatalogSettings _catalogSettings;
|
|
protected readonly IBaseAdminModelFactory _baseAdminModelFactory;
|
|
protected readonly IBlogService _blogService;
|
|
protected readonly ICustomerService _customerService;
|
|
protected readonly IDateTimeHelper _dateTimeHelper;
|
|
protected readonly IHtmlFormatter _htmlFormatter;
|
|
protected readonly ILanguageService _languageService;
|
|
protected readonly ILocalizationService _localizationService;
|
|
protected readonly IStoreMappingSupportedModelFactory _storeMappingSupportedModelFactory;
|
|
protected readonly IStoreService _storeService;
|
|
protected readonly IUrlRecordService _urlRecordService;
|
|
|
|
#endregion
|
|
|
|
#region Ctor
|
|
|
|
public BlogModelFactory(CatalogSettings catalogSettings,
|
|
IBaseAdminModelFactory baseAdminModelFactory,
|
|
IBlogService blogService,
|
|
ICustomerService customerService,
|
|
IDateTimeHelper dateTimeHelper,
|
|
IHtmlFormatter htmlFormatter,
|
|
ILanguageService languageService,
|
|
ILocalizationService localizationService,
|
|
IStoreMappingSupportedModelFactory storeMappingSupportedModelFactory,
|
|
IStoreService storeService,
|
|
IUrlRecordService urlRecordService)
|
|
{
|
|
_catalogSettings = catalogSettings;
|
|
_baseAdminModelFactory = baseAdminModelFactory;
|
|
_blogService = blogService;
|
|
_customerService = customerService;
|
|
_dateTimeHelper = dateTimeHelper;
|
|
_htmlFormatter = htmlFormatter;
|
|
_languageService = languageService;
|
|
_localizationService = localizationService;
|
|
_storeMappingSupportedModelFactory = storeMappingSupportedModelFactory;
|
|
_storeService = storeService;
|
|
_urlRecordService = urlRecordService;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Methods
|
|
|
|
/// <summary>
|
|
/// Prepare blog content model
|
|
/// </summary>
|
|
/// <param name="blogContentModel">Blog content model</param>
|
|
/// <param name="filterByBlogPostId">Blog post ID</param>
|
|
/// <returns>
|
|
/// A task that represents the asynchronous operation
|
|
/// The task result contains the blog content model
|
|
/// </returns>
|
|
public virtual async Task<BlogContentModel> PrepareBlogContentModelAsync(BlogContentModel blogContentModel, int? filterByBlogPostId)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(blogContentModel);
|
|
|
|
//prepare nested search models
|
|
await PrepareBlogPostSearchModelAsync(blogContentModel.BlogPosts);
|
|
var blogPost = await _blogService.GetBlogPostByIdAsync(filterByBlogPostId ?? 0);
|
|
await PrepareBlogCommentSearchModelAsync(blogContentModel.BlogComments, blogPost);
|
|
|
|
return blogContentModel;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Prepare paged blog post list model
|
|
/// </summary>
|
|
/// <param name="searchModel">Blog post search model</param>
|
|
/// <returns>
|
|
/// A task that represents the asynchronous operation
|
|
/// The task result contains the blog post list model
|
|
/// </returns>
|
|
public virtual async Task<BlogPostListModel> PrepareBlogPostListModelAsync(BlogPostSearchModel searchModel)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(searchModel);
|
|
|
|
//get blog posts
|
|
var blogPosts = await _blogService.GetAllBlogPostsAsync(storeId: searchModel.SearchStoreId, showHidden: true,
|
|
pageIndex: searchModel.Page - 1, pageSize: searchModel.PageSize, title: searchModel.SearchTitle);
|
|
|
|
//prepare list model
|
|
var model = await new BlogPostListModel().PrepareToGridAsync(searchModel, blogPosts, () =>
|
|
{
|
|
return blogPosts.SelectAwait(async blogPost =>
|
|
{
|
|
//fill in model values from the entity
|
|
var blogPostModel = blogPost.ToModel<BlogPostModel>();
|
|
|
|
//little performance optimization: ensure that "Body" is not returned
|
|
blogPostModel.Body = string.Empty;
|
|
|
|
//convert dates to the user time
|
|
if (blogPost.StartDateUtc.HasValue)
|
|
blogPostModel.StartDateUtc = await _dateTimeHelper.ConvertToUserTimeAsync(blogPost.StartDateUtc.Value, DateTimeKind.Utc);
|
|
if (blogPost.EndDateUtc.HasValue)
|
|
blogPostModel.EndDateUtc = await _dateTimeHelper.ConvertToUserTimeAsync(blogPost.EndDateUtc.Value, DateTimeKind.Utc);
|
|
blogPostModel.CreatedOn = await _dateTimeHelper.ConvertToUserTimeAsync(blogPost.CreatedOnUtc, DateTimeKind.Utc);
|
|
|
|
//fill in additional values (not existing in the entity)
|
|
blogPostModel.LanguageName = (await _languageService.GetLanguageByIdAsync(blogPost.LanguageId))?.Name;
|
|
blogPostModel.ApprovedComments = await _blogService.GetBlogCommentsCountAsync(blogPost, isApproved: true);
|
|
blogPostModel.NotApprovedComments = await _blogService.GetBlogCommentsCountAsync(blogPost, isApproved: false);
|
|
blogPostModel.SeName = await _urlRecordService.GetSeNameAsync(blogPost, blogPost.LanguageId, true, false);
|
|
|
|
return blogPostModel;
|
|
});
|
|
});
|
|
|
|
return model;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Prepare blog post model
|
|
/// </summary>
|
|
/// <param name="model">Blog post model</param>
|
|
/// <param name="blogPost">Blog post</param>
|
|
/// <param name="excludeProperties">Whether to exclude populating of some properties of model</param>
|
|
/// <returns>
|
|
/// A task that represents the asynchronous operation
|
|
/// The task result contains the blog post model
|
|
/// </returns>
|
|
public virtual async Task<BlogPostModel> PrepareBlogPostModelAsync(BlogPostModel model, BlogPost blogPost, bool excludeProperties = false)
|
|
{
|
|
//fill in model values from the entity
|
|
if (blogPost != null)
|
|
{
|
|
if (model == null)
|
|
{
|
|
model = blogPost.ToModel<BlogPostModel>();
|
|
model.SeName = await _urlRecordService.GetSeNameAsync(blogPost, blogPost.LanguageId, true, false);
|
|
}
|
|
model.StartDateUtc = blogPost.StartDateUtc;
|
|
model.EndDateUtc = blogPost.EndDateUtc;
|
|
}
|
|
|
|
//set default values for the new model
|
|
if (blogPost == null)
|
|
{
|
|
model.AllowComments = true;
|
|
model.IncludeInSitemap = true;
|
|
}
|
|
|
|
var blogTags = await _blogService.GetAllBlogPostTagsAsync(0, 0, true);
|
|
var blogTagsSb = new StringBuilder();
|
|
blogTagsSb.Append("var initialBlogTags = [");
|
|
for (var i = 0; i < blogTags.Count; i++)
|
|
{
|
|
var tag = blogTags[i];
|
|
blogTagsSb.Append('\'');
|
|
blogTagsSb.Append(JavaScriptEncoder.Default.Encode(tag.Name));
|
|
blogTagsSb.Append('\'');
|
|
if (i != blogTags.Count - 1)
|
|
blogTagsSb.Append(',');
|
|
}
|
|
blogTagsSb.Append(']');
|
|
|
|
model.InitialBlogTags = blogTagsSb.ToString();
|
|
|
|
//prepare available languages
|
|
await _baseAdminModelFactory.PrepareLanguagesAsync(model.AvailableLanguages, false);
|
|
|
|
//prepare available stores
|
|
await _storeMappingSupportedModelFactory.PrepareModelStoresAsync(model, blogPost, excludeProperties);
|
|
|
|
return model;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Prepare blog comment search model
|
|
/// </summary>
|
|
/// <param name="searchModel">Blog comment search model</param>
|
|
/// <param name="blogPost">Blog post</param>
|
|
/// <returns>
|
|
/// A task that represents the asynchronous operation
|
|
/// The task result contains the blog comment search model
|
|
/// </returns>
|
|
public virtual async Task<BlogCommentSearchModel> PrepareBlogCommentSearchModelAsync(BlogCommentSearchModel searchModel, BlogPost blogPost)
|
|
{
|
|
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.Blog.Comments.List.SearchApproved.All"),
|
|
Value = "0"
|
|
});
|
|
searchModel.AvailableApprovedOptions.Add(new SelectListItem
|
|
{
|
|
Text = await _localizationService.GetResourceAsync("Admin.ContentManagement.Blog.Comments.List.SearchApproved.ApprovedOnly"),
|
|
Value = "1"
|
|
});
|
|
searchModel.AvailableApprovedOptions.Add(new SelectListItem
|
|
{
|
|
Text = await _localizationService.GetResourceAsync("Admin.ContentManagement.Blog.Comments.List.SearchApproved.DisapprovedOnly"),
|
|
Value = "2"
|
|
});
|
|
|
|
searchModel.BlogPostId = blogPost?.Id;
|
|
|
|
//prepare page parameters
|
|
searchModel.SetGridPageSize();
|
|
|
|
return searchModel;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Prepare paged blog comment list model
|
|
/// </summary>
|
|
/// <param name="searchModel">Blog comment search model</param>
|
|
/// <param name="blogPostId">Blog post ID</param>
|
|
/// <returns>
|
|
/// A task that represents the asynchronous operation
|
|
/// The task result contains the blog comment list model
|
|
/// </returns>
|
|
public virtual async Task<BlogCommentListModel> PrepareBlogCommentListModelAsync(BlogCommentSearchModel searchModel, int? blogPostId)
|
|
{
|
|
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 _blogService.GetAllCommentsAsync(blogPostId: blogPostId,
|
|
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 BlogCommentListModel().PrepareToGridAsync(searchModel, comments, () =>
|
|
{
|
|
return comments.SelectAwait(async blogComment =>
|
|
{
|
|
//fill in model values from the entity
|
|
var commentModel = blogComment.ToModel<BlogCommentModel>();
|
|
|
|
//set title from linked blog post
|
|
commentModel.BlogPostTitle = (await _blogService.GetBlogPostByIdAsync(blogComment.BlogPostId))?.Title;
|
|
|
|
if ((await _customerService.GetCustomerByIdAsync(blogComment.CustomerId)) is Customer customer)
|
|
{
|
|
commentModel.CustomerInfo = (await _customerService.IsRegisteredAsync(customer))
|
|
? customer.Email
|
|
: await _localizationService.GetResourceAsync("Admin.Customers.Guest");
|
|
}
|
|
//fill in additional values (not existing in the entity)
|
|
commentModel.CreatedOn = await _dateTimeHelper.ConvertToUserTimeAsync(blogComment.CreatedOnUtc, DateTimeKind.Utc);
|
|
commentModel.Comment = _htmlFormatter.FormatText(blogComment.CommentText, false, true, false, false, false, false);
|
|
commentModel.StoreName = storeNames.TryGetValue(blogComment.StoreId, out var value) ? value : "Deleted";
|
|
|
|
return commentModel;
|
|
});
|
|
});
|
|
|
|
return model;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Prepare blog post search model
|
|
/// </summary>
|
|
/// <param name="searchModel">Blog post search model</param>
|
|
/// <returns>
|
|
/// A task that represents the asynchronous operation
|
|
/// The task result contains the blog post search model
|
|
/// </returns>
|
|
public virtual async Task<BlogPostSearchModel> PrepareBlogPostSearchModelAsync(BlogPostSearchModel 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
|
|
} |