using Nop.Core;
using Nop.Core.Caching;
using Nop.Core.Domain.Blogs;
using Nop.Data;
using Nop.Services.Stores;
namespace Nop.Services.Blogs;
///
/// Blog service
///
public partial class BlogService : IBlogService
{
#region Fields
protected readonly IRepository _blogCommentRepository;
protected readonly IRepository _blogPostRepository;
protected readonly IStaticCacheManager _staticCacheManager;
protected readonly IStoreMappingService _storeMappingService;
private static readonly char[] _separator = [','];
#endregion
#region Ctor
public BlogService(
IRepository blogCommentRepository,
IRepository blogPostRepository,
IStaticCacheManager staticCacheManager,
IStoreMappingService storeMappingService)
{
_blogCommentRepository = blogCommentRepository;
_blogPostRepository = blogPostRepository;
_staticCacheManager = staticCacheManager;
_storeMappingService = storeMappingService;
}
#endregion
#region Methods
#region Blog posts
///
/// Deletes a blog post
///
/// Blog post
/// A task that represents the asynchronous operation
public virtual async Task DeleteBlogPostAsync(BlogPost blogPost)
{
await _blogPostRepository.DeleteAsync(blogPost);
}
///
/// Gets a blog post
///
/// Blog post identifier
///
/// A task that represents the asynchronous operation
/// The task result contains the blog post
///
public virtual async Task GetBlogPostByIdAsync(int blogPostId)
{
return await _blogPostRepository.GetByIdAsync(blogPostId, cache => default, useShortTermCache: true);
}
///
/// Gets all blog posts
///
/// The store identifier; pass 0 to load all records
/// Language identifier; 0 if you want to get all records
/// Filter by created date; null if you want to get all records
/// Filter by created date; null if you want to get all records
/// Page index
/// Page size
/// A value indicating whether to show hidden records
/// Filter by blog post title
///
/// A task that represents the asynchronous operation
/// The task result contains the blog posts
///
public virtual async Task> GetAllBlogPostsAsync(int storeId = 0, int languageId = 0,
DateTime? dateFrom = null, DateTime? dateTo = null,
int pageIndex = 0, int pageSize = int.MaxValue, bool showHidden = false, string title = null)
{
return await _blogPostRepository.GetAllPagedAsync(async query =>
{
if (dateFrom.HasValue)
query = query.Where(b => dateFrom.Value <= (b.StartDateUtc ?? b.CreatedOnUtc));
if (dateTo.HasValue)
query = query.Where(b => dateTo.Value >= (b.StartDateUtc ?? b.CreatedOnUtc));
if (languageId > 0)
query = query.Where(b => languageId == b.LanguageId);
if (!string.IsNullOrEmpty(title))
query = query.Where(b => b.Title.Contains(title));
if (!showHidden || storeId > 0)
{
//apply store mapping constraints
query = await _storeMappingService.ApplyStoreMapping(query, storeId);
}
if (!showHidden)
{
query = query.Where(b => !b.StartDateUtc.HasValue || b.StartDateUtc <= DateTime.UtcNow);
query = query.Where(b => !b.EndDateUtc.HasValue || b.EndDateUtc >= DateTime.UtcNow);
}
query = query.OrderByDescending(b => b.StartDateUtc ?? b.CreatedOnUtc);
return query;
}, pageIndex, pageSize);
}
///
/// Gets all blog posts
///
/// The store identifier; pass 0 to load all records
/// Language identifier. 0 if you want to get all blog posts
/// Tag
/// Page index
/// Page size
/// A value indicating whether to show hidden records
///
/// A task that represents the asynchronous operation
/// The task result contains the blog posts
///
public virtual async Task> GetAllBlogPostsByTagAsync(int storeId = 0,
int languageId = 0, string tag = "",
int pageIndex = 0, int pageSize = int.MaxValue, bool showHidden = false)
{
tag = tag.Trim();
//we load all records and only then filter them by tag
var blogPostsAll = await GetAllBlogPostsAsync(storeId: storeId, languageId: languageId, showHidden: showHidden);
var taggedBlogPosts = new List();
foreach (var blogPost in blogPostsAll)
{
var tags = await ParseTagsAsync(blogPost);
if (!string.IsNullOrEmpty(tags.FirstOrDefault(t => t.Equals(tag, StringComparison.InvariantCultureIgnoreCase))))
taggedBlogPosts.Add(blogPost);
}
//server-side paging
var result = new PagedList(taggedBlogPosts, pageIndex, pageSize);
return result;
}
///
/// Gets all blog post tags
///
/// The store identifier; pass 0 to load all records
/// Language identifier. 0 if you want to get all blog posts
/// A value indicating whether to show hidden records
///
/// A task that represents the asynchronous operation
/// The task result contains the blog post tags
///
public virtual async Task> GetAllBlogPostTagsAsync(int storeId, int languageId, bool showHidden = false)
{
var cacheKey = _staticCacheManager.PrepareKeyForDefaultCache(NopBlogsDefaults.BlogTagsCacheKey, languageId, storeId, showHidden);
var blogPostTags = await _staticCacheManager.GetAsync(cacheKey, async () =>
{
var rezBlogPostTags = new List();
var blogPosts = await GetAllBlogPostsAsync(storeId, languageId, showHidden: showHidden);
foreach (var blogPost in blogPosts)
{
var tags = await ParseTagsAsync(blogPost);
foreach (var tag in tags)
{
var foundBlogPostTag = rezBlogPostTags.Find(bpt =>
bpt.Name.Equals(tag, StringComparison.InvariantCultureIgnoreCase));
if (foundBlogPostTag == null)
{
foundBlogPostTag = new BlogPostTag
{
Name = tag,
BlogPostCount = 1
};
rezBlogPostTags.Add(foundBlogPostTag);
}
else
foundBlogPostTag.BlogPostCount++;
}
}
return rezBlogPostTags;
});
return blogPostTags;
}
///
/// Inserts a blog post
///
/// Blog post
/// A task that represents the asynchronous operation
public virtual async Task InsertBlogPostAsync(BlogPost blogPost)
{
await _blogPostRepository.InsertAsync(blogPost);
}
///
/// Updates the blog post
///
/// Blog post
/// A task that represents the asynchronous operation
public virtual async Task UpdateBlogPostAsync(BlogPost blogPost)
{
await _blogPostRepository.UpdateAsync(blogPost);
}
///
/// Returns all posts published between the two dates.
///
/// Source
/// Date from
/// Date to
///
/// A task that represents the asynchronous operation
/// The task result contains the filtered posts
///
public virtual async Task> GetPostsByDateAsync(IList blogPosts, DateTime dateFrom, DateTime dateTo)
{
ArgumentNullException.ThrowIfNull(blogPosts);
var rez = await blogPosts
.Where(p => dateFrom.Date <= (p.StartDateUtc ?? p.CreatedOnUtc) && (p.StartDateUtc ?? p.CreatedOnUtc).Date <= dateTo)
.ToListAsync();
return rez;
}
///
/// Parse tags
///
/// Blog post
///
/// A task that represents the asynchronous operation
/// The task result contains the ags
///
public virtual async Task> ParseTagsAsync(BlogPost blogPost)
{
ArgumentNullException.ThrowIfNull(blogPost);
if (blogPost.Tags == null)
return new List();
var tags = await blogPost.Tags.Split(_separator, StringSplitOptions.RemoveEmptyEntries)
.Select(tag => tag.Trim())
.Where(tag => !string.IsNullOrEmpty(tag))
.ToListAsync();
return tags;
}
///
/// Get a value indicating whether a blog post is available now (availability dates)
///
/// Blog post
/// Datetime to check; pass null to use current date
/// Result
public virtual bool BlogPostIsAvailable(BlogPost blogPost, DateTime? dateTime = null)
{
ArgumentNullException.ThrowIfNull(blogPost);
if (blogPost.StartDateUtc.HasValue && blogPost.StartDateUtc.Value >= (dateTime ?? DateTime.UtcNow))
return false;
if (blogPost.EndDateUtc.HasValue && blogPost.EndDateUtc.Value <= (dateTime ?? DateTime.UtcNow))
return false;
return true;
}
#endregion
#region Blog comments
///
/// Gets all comments
///
/// Customer identifier; 0 to load all records
/// Store identifier; pass 0 to load all records
/// Blog post ID; 0 or null to load all records
/// A value indicating whether to content is approved; null to load all records
/// Item creation from; null to load all records
/// Item creation to; null to load all records
/// Search comment text; null to load all records
///
/// A task that represents the asynchronous operation
/// The task result contains the comments
///
public virtual async Task> GetAllCommentsAsync(int customerId = 0, int storeId = 0, int? blogPostId = null,
bool? approved = null, DateTime? fromUtc = null, DateTime? toUtc = null, string commentText = null)
{
return await _blogCommentRepository.GetAllAsync(query =>
{
if (approved.HasValue)
query = query.Where(comment => comment.IsApproved == approved);
if (blogPostId > 0)
query = query.Where(comment => comment.BlogPostId == blogPostId);
if (customerId > 0)
query = query.Where(comment => comment.CustomerId == customerId);
if (storeId > 0)
query = query.Where(comment => comment.StoreId == storeId);
if (fromUtc.HasValue)
query = query.Where(comment => fromUtc.Value <= comment.CreatedOnUtc);
if (toUtc.HasValue)
query = query.Where(comment => toUtc.Value >= comment.CreatedOnUtc);
if (!string.IsNullOrEmpty(commentText))
query = query.Where(c => c.CommentText.Contains(commentText));
query = query.OrderBy(comment => comment.CreatedOnUtc);
return query;
});
}
///
/// Gets a blog comment
///
/// Blog comment identifier
///
/// A task that represents the asynchronous operation
/// The task result contains the blog comment
///
public virtual async Task GetBlogCommentByIdAsync(int blogCommentId)
{
return await _blogCommentRepository.GetByIdAsync(blogCommentId, cache => default, useShortTermCache: true);
}
///
/// Get blog comments by identifiers
///
/// Blog comment identifiers
///
/// A task that represents the asynchronous operation
/// The task result contains the blog comments
///
public virtual async Task> GetBlogCommentsByIdsAsync(int[] commentIds)
{
return await _blogCommentRepository.GetByIdsAsync(commentIds);
}
///
/// Get the count of blog comments
///
/// Blog post
/// Store identifier; pass 0 to load all records
/// A value indicating whether to count only approved or not approved comments; pass null to get number of all comments
///
/// A task that represents the asynchronous operation
/// The task result contains the number of blog comments
///
public virtual async Task GetBlogCommentsCountAsync(BlogPost blogPost, int storeId = 0, bool? isApproved = null)
{
var query = _blogCommentRepository.Table.Where(comment => comment.BlogPostId == blogPost.Id);
if (storeId > 0)
query = query.Where(comment => comment.StoreId == storeId);
if (isApproved.HasValue)
query = query.Where(comment => comment.IsApproved == isApproved.Value);
var cacheKey = _staticCacheManager.PrepareKeyForDefaultCache(NopBlogsDefaults.BlogCommentsNumberCacheKey, blogPost, storeId, isApproved);
return await _staticCacheManager.GetAsync(cacheKey, async () => await query.CountAsync());
}
///
/// Deletes a blog comment
///
/// Blog comment
/// A task that represents the asynchronous operation
public virtual async Task DeleteBlogCommentAsync(BlogComment blogComment)
{
await _blogCommentRepository.DeleteAsync(blogComment);
}
///
/// Deletes blog comments
///
/// Blog comments
/// A task that represents the asynchronous operation
public virtual async Task DeleteBlogCommentsAsync(IList blogComments)
{
await _blogCommentRepository.DeleteAsync(blogComments);
}
///
/// Inserts a blog comment
///
/// Blog comment
/// A task that represents the asynchronous operation
public virtual async Task InsertBlogCommentAsync(BlogComment blogComment)
{
await _blogCommentRepository.InsertAsync(blogComment);
}
///
/// Update a blog comment
///
/// Blog comment
/// A task that represents the asynchronous operation
public virtual async Task UpdateBlogCommentAsync(BlogComment blogComment)
{
await _blogCommentRepository.UpdateAsync(blogComment);
}
#endregion
#endregion
}