121291eeed
Build and Deploy to Kubernetes / build-and-deploy (push) Has been cancelled
Allow optional slug on create/update, generate from title with unique fallback, so BackOffice can publish posts without manual slug entry. Co-authored-by: Cursor <cursoragent@cursor.com>
101 lines
3.6 KiB
C#
101 lines
3.6 KiB
C#
using CMSMicroservice.Application.Common;
|
|
using CMSMicroservice.Application.Common.FileManager;
|
|
using CMSMicroservice.Application.Common.Interfaces;
|
|
using CMSMicroservice.Domain.Entities.Blog;
|
|
using CMSMicroservice.Domain.Enums;
|
|
using MediatR;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace CMSMicroservice.Application.BlogPostCQ.Commands.CreateBlogPost;
|
|
|
|
public class CreateBlogPostCommandHandler : IRequestHandler<CreateBlogPostCommand, long>
|
|
{
|
|
private readonly IApplicationDbContext _context;
|
|
private readonly ICurrentUserService _currentUser;
|
|
private readonly IFileManager _fileManager;
|
|
private readonly ILogger<CreateBlogPostCommandHandler> _logger;
|
|
|
|
public CreateBlogPostCommandHandler(
|
|
IApplicationDbContext context,
|
|
ICurrentUserService currentUser,
|
|
IFileManager fileManager,
|
|
ILogger<CreateBlogPostCommandHandler> logger)
|
|
{
|
|
_context = context;
|
|
_currentUser = currentUser;
|
|
_fileManager = fileManager;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task<long> Handle(CreateBlogPostCommand request, CancellationToken cancellationToken)
|
|
{
|
|
var currentUserId = _currentUser.UserId;
|
|
if (string.IsNullOrEmpty(currentUserId) || !long.TryParse(currentUserId, out var authorUserId))
|
|
throw new UnauthorizedAccessException("کاربر احراز هویت نشده است");
|
|
|
|
var slug = BlogSlugHelper.ResolveForCreate(request.Slug, request.Title.Trim());
|
|
slug = await BlogSlugHelper.EnsureUniquePostSlugAsync(_context, slug, cancellationToken: cancellationToken);
|
|
|
|
var post = new BlogPost
|
|
{
|
|
Title = request.Title.Trim(),
|
|
Slug = slug,
|
|
Summary = request.Summary?.Trim(),
|
|
HtmlContent = request.HtmlContent,
|
|
FeaturedImagePath = request.FeaturedImagePath,
|
|
FeaturedImageThumbnailPath = request.FeaturedImageThumbnailPath,
|
|
Status = BlogPostStatus.Draft,
|
|
AuthorUserId = authorUserId,
|
|
IsFeatured = request.IsFeatured,
|
|
SortOrder = request.SortOrder,
|
|
ViewCount = 0
|
|
};
|
|
|
|
// آپلود تصویر شاخص (اگر فایل ارسال شده باشد)
|
|
if (request.ImageFileBytes is { Length: > 0 })
|
|
{
|
|
var result = await _fileManager.UploadImageAsync(
|
|
"Images/BlogPosts",
|
|
request.ImageFileBytes,
|
|
request.ImageFileMime ?? "image/jpeg",
|
|
request.ImageFileName,
|
|
cancellationToken);
|
|
|
|
post.FeaturedImagePath = result.Main.Path;
|
|
post.FeaturedImageThumbnailPath = result.Thumbnail.Path;
|
|
}
|
|
|
|
_context.BlogPosts.Add(post);
|
|
await _context.SaveChangesAsync(cancellationToken);
|
|
|
|
// افزودن دستهبندیها
|
|
foreach (var categoryId in request.CategoryIds)
|
|
{
|
|
_context.BlogPostCategories.Add(new BlogPostCategory
|
|
{
|
|
BlogPostId = post.Id,
|
|
BlogCategoryId = categoryId
|
|
});
|
|
}
|
|
|
|
// افزودن تگها
|
|
foreach (var tagId in request.TagIds)
|
|
{
|
|
_context.BlogPostTags.Add(new BlogPostTag
|
|
{
|
|
BlogPostId = post.Id,
|
|
TagId = tagId
|
|
});
|
|
}
|
|
|
|
if (request.CategoryIds.Any() || request.TagIds.Any())
|
|
await _context.SaveChangesAsync(cancellationToken);
|
|
|
|
_logger.LogInformation(
|
|
"Blog post created. Id: {Id}, Title: {Title}, Author: {Author}",
|
|
post.Id, post.Title, authorUserId);
|
|
|
|
return post.Id;
|
|
}
|
|
}
|