|
|
|
@ -16,231 +16,231 @@ namespace Volo.CmsKit.MongoDB.Comments; |
|
|
|
|
|
|
|
public class MongoCommentRepository : MongoDbRepository<ICmsKitMongoDbContext, Comment, Guid>, ICommentRepository |
|
|
|
{ |
|
|
|
public MongoCommentRepository(IMongoDbContextProvider<ICmsKitMongoDbContext> dbContextProvider) : base(dbContextProvider) |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
public virtual async Task<CommentWithAuthorQueryResultItem> GetWithAuthorAsync(Guid id, CancellationToken cancellationToken = default) |
|
|
|
{ |
|
|
|
var comment = await GetAsync(id); |
|
|
|
var author = await (await GetDbContextAsync()) |
|
|
|
.CmsUsers |
|
|
|
.AsQueryable() |
|
|
|
.FirstOrDefaultAsync(x => x.Id == comment.CreatorId, GetCancellationToken(cancellationToken)); |
|
|
|
|
|
|
|
return new CommentWithAuthorQueryResultItem() |
|
|
|
{ |
|
|
|
Comment = comment, |
|
|
|
Author = author |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
public virtual async Task<List<CommentWithAuthorQueryResultItem>> GetListAsync( |
|
|
|
string filter = null, |
|
|
|
string entityType = null, |
|
|
|
Guid? repliedCommentId = null, |
|
|
|
string authorUsername = null, |
|
|
|
DateTime? creationStartDate = null, |
|
|
|
DateTime? creationEndDate = null, |
|
|
|
string sorting = null, |
|
|
|
int maxResultCount = int.MaxValue, |
|
|
|
int skipCount = 0, |
|
|
|
string isApproved = null, |
|
|
|
CancellationToken cancellationToken = default |
|
|
|
) |
|
|
|
|
|
|
|
{ |
|
|
|
//bool? isApprovedValue = ParseIsApproved(isApproved);
|
|
|
|
|
|
|
|
var token = GetCancellationToken(cancellationToken); |
|
|
|
var query = await GetListQueryAsync( |
|
|
|
filter, |
|
|
|
entityType, |
|
|
|
repliedCommentId, |
|
|
|
authorUsername, |
|
|
|
creationStartDate, |
|
|
|
creationEndDate, |
|
|
|
isApproved, |
|
|
|
token); |
|
|
|
|
|
|
|
var comments = await query.OrderBy(sorting.IsNullOrEmpty() ? "creationTime desc" : sorting) |
|
|
|
.As<IMongoQueryable<Comment>>() |
|
|
|
.PageBy<Comment, IMongoQueryable<Comment>>(skipCount, maxResultCount) |
|
|
|
.ToListAsync(token); |
|
|
|
|
|
|
|
var commentIds = comments.Select(x => x.Id).ToList(); |
|
|
|
|
|
|
|
var authorsQuery = from comment in (await GetMongoQueryableAsync(token)) |
|
|
|
join user in (await GetDbContextAsync(token)).CmsUsers on comment.CreatorId equals user.Id |
|
|
|
where commentIds.Contains(comment.Id) |
|
|
|
orderby comment.CreationTime |
|
|
|
select user; |
|
|
|
|
|
|
|
var authors = await ApplyDataFilters<IMongoQueryable<CmsUser>, CmsUser>(authorsQuery).ToListAsync(token); |
|
|
|
|
|
|
|
return comments |
|
|
|
.Select( |
|
|
|
comment => |
|
|
|
new CommentWithAuthorQueryResultItem |
|
|
|
{ |
|
|
|
Comment = comment, |
|
|
|
Author = authors.FirstOrDefault(a => a.Id == comment.CreatorId) |
|
|
|
}).ToList(); |
|
|
|
} |
|
|
|
|
|
|
|
public virtual async Task<long> GetCountAsync( |
|
|
|
string text = null, |
|
|
|
string entityType = null, |
|
|
|
Guid? repliedCommentId = null, |
|
|
|
string authorUsername = null, |
|
|
|
DateTime? creationStartDate = null, |
|
|
|
DateTime? creationEndDate = null, |
|
|
|
string isApproved = null, |
|
|
|
CancellationToken cancellationToken = default |
|
|
|
) |
|
|
|
{ |
|
|
|
//bool? isApprovedValue = ParseIsApproved(isApproved);
|
|
|
|
var query = await GetListQueryAsync( |
|
|
|
text, |
|
|
|
entityType, |
|
|
|
repliedCommentId, |
|
|
|
authorUsername, |
|
|
|
creationStartDate, |
|
|
|
creationEndDate, |
|
|
|
isApproved, |
|
|
|
cancellationToken); |
|
|
|
|
|
|
|
return await query.As<IMongoQueryable<Comment>>() |
|
|
|
.LongCountAsync(GetCancellationToken(cancellationToken)); |
|
|
|
} |
|
|
|
|
|
|
|
public virtual async Task<List<CommentWithAuthorQueryResultItem>> GetListWithAuthorsAsync( |
|
|
|
string entityType, |
|
|
|
string entityId, |
|
|
|
bool? isApproved, |
|
|
|
CancellationToken cancellationToken = default) |
|
|
|
{ |
|
|
|
Check.NotNullOrWhiteSpace(entityType, nameof(entityType)); |
|
|
|
Check.NotNullOrWhiteSpace(entityId, nameof(entityId)); |
|
|
|
|
|
|
|
var authorsQuery = from comment in (await GetMongoQueryableAsync(cancellationToken)) |
|
|
|
join user in (await GetDbContextAsync(cancellationToken)).CmsUsers on comment.CreatorId equals user.Id |
|
|
|
where entityType == comment.EntityType && entityId == comment.EntityId |
|
|
|
orderby comment.CreationTime |
|
|
|
select user; |
|
|
|
|
|
|
|
var authors = await ApplyDataFilters<IMongoQueryable<CmsUser>, CmsUser>(authorsQuery).ToListAsync(GetCancellationToken(cancellationToken)); |
|
|
|
|
|
|
|
var commentsQuery = (await GetMongoQueryableAsync(cancellationToken)) |
|
|
|
.Where(c => c.EntityId == entityId && c.EntityType == entityType); |
|
|
|
|
|
|
|
|
|
|
|
commentsQuery = isApproved.Value ? |
|
|
|
commentsQuery.Where(c => c.IsApproved == true) : |
|
|
|
commentsQuery.Where(c => c.IsApproved == true || c.IsApproved == null); |
|
|
|
|
|
|
|
|
|
|
|
var comments = await commentsQuery |
|
|
|
.OrderBy(c => c.CreationTime) |
|
|
|
.ToListAsync(GetCancellationToken(cancellationToken)); |
|
|
|
|
|
|
|
return comments |
|
|
|
.Select( |
|
|
|
comment => |
|
|
|
new CommentWithAuthorQueryResultItem |
|
|
|
{ |
|
|
|
Comment = comment, |
|
|
|
Author = authors.FirstOrDefault(a => a.Id == comment.CreatorId) |
|
|
|
}).ToList(); |
|
|
|
} |
|
|
|
|
|
|
|
public virtual async Task DeleteWithRepliesAsync( |
|
|
|
Comment comment, |
|
|
|
CancellationToken cancellationToken = default) |
|
|
|
{ |
|
|
|
var replies = await (await GetMongoQueryableAsync(cancellationToken)) |
|
|
|
.Where(x => x.RepliedCommentId == comment.Id) |
|
|
|
.ToListAsync(GetCancellationToken(cancellationToken)); |
|
|
|
|
|
|
|
await base.DeleteAsync( |
|
|
|
comment, |
|
|
|
cancellationToken: GetCancellationToken(cancellationToken) |
|
|
|
); |
|
|
|
|
|
|
|
foreach (var reply in replies) |
|
|
|
{ |
|
|
|
await base.DeleteAsync( |
|
|
|
reply, |
|
|
|
cancellationToken: GetCancellationToken(cancellationToken) |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public virtual async Task<bool> ExistsAsync(string idempotencyToken, CancellationToken cancellationToken = default) |
|
|
|
{ |
|
|
|
return await (await GetMongoQueryableAsync(cancellationToken)) |
|
|
|
.AnyAsync(x => x.IdempotencyToken == idempotencyToken, GetCancellationToken(cancellationToken)); |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual async Task<IQueryable<Comment>> GetListQueryAsync( |
|
|
|
string filter = null, |
|
|
|
string entityType = null, |
|
|
|
Guid? repliedCommentId = null, |
|
|
|
string authorUsername = null, |
|
|
|
DateTime? creationStartDate = null, |
|
|
|
DateTime? creationEndDate = null, |
|
|
|
string isApproved = null, |
|
|
|
CancellationToken cancellationToken = default |
|
|
|
) |
|
|
|
{ |
|
|
|
var queryable = await GetMongoQueryableAsync(cancellationToken); |
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(authorUsername)) |
|
|
|
{ |
|
|
|
var author = await (await GetMongoQueryableAsync<CmsUser>(cancellationToken)).FirstOrDefaultAsync(x => x.UserName == authorUsername, cancellationToken: cancellationToken); |
|
|
|
|
|
|
|
var authorId = author?.Id ?? Guid.Empty; |
|
|
|
|
|
|
|
queryable = queryable.Where(x => x.CreatorId == authorId); |
|
|
|
} |
|
|
|
|
|
|
|
queryable.WhereIf(!filter.IsNullOrWhiteSpace(), c => c.Text.Contains(filter)) |
|
|
|
.WhereIf(!entityType.IsNullOrWhiteSpace(), c => c.EntityType == entityType) |
|
|
|
.WhereIf(repliedCommentId.HasValue, c => c.RepliedCommentId == repliedCommentId) |
|
|
|
.WhereIf(creationStartDate.HasValue, c => c.CreationTime >= creationStartDate) |
|
|
|
.WhereIf(creationEndDate.HasValue, c => c.CreationTime <= creationEndDate); |
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(isApproved)) |
|
|
|
{ |
|
|
|
bool? isApprovedValue = ParseIsApproved(isApproved); |
|
|
|
if (isApprovedValue.HasValue) |
|
|
|
{ |
|
|
|
queryable = queryable.Where(c => c.IsApproved == isApprovedValue); |
|
|
|
} |
|
|
|
else if (isApprovedValue == null) |
|
|
|
{ |
|
|
|
queryable = queryable.Where(c => c.IsApproved == null); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return queryable; |
|
|
|
|
|
|
|
} |
|
|
|
public static bool? ParseIsApproved(string isApproved) |
|
|
|
{ |
|
|
|
if (string.IsNullOrWhiteSpace(isApproved)) |
|
|
|
{ |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
return isApproved.ToLower() switch |
|
|
|
{ |
|
|
|
"true" => true, |
|
|
|
"false" => false, |
|
|
|
"null" => (bool?)null, |
|
|
|
_ => null |
|
|
|
|
|
|
|
}; |
|
|
|
} |
|
|
|
public MongoCommentRepository(IMongoDbContextProvider<ICmsKitMongoDbContext> dbContextProvider) : base(dbContextProvider) |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
public virtual async Task<CommentWithAuthorQueryResultItem> GetWithAuthorAsync(Guid id, CancellationToken cancellationToken = default) |
|
|
|
{ |
|
|
|
var comment = await GetAsync(id); |
|
|
|
var author = await (await GetDbContextAsync()) |
|
|
|
.CmsUsers |
|
|
|
.AsQueryable() |
|
|
|
.FirstOrDefaultAsync(x => x.Id == comment.CreatorId, GetCancellationToken(cancellationToken)); |
|
|
|
|
|
|
|
return new CommentWithAuthorQueryResultItem() |
|
|
|
{ |
|
|
|
Comment = comment, |
|
|
|
Author = author |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
public virtual async Task<List<CommentWithAuthorQueryResultItem>> GetListAsync( |
|
|
|
string filter = null, |
|
|
|
string entityType = null, |
|
|
|
Guid? repliedCommentId = null, |
|
|
|
string authorUsername = null, |
|
|
|
DateTime? creationStartDate = null, |
|
|
|
DateTime? creationEndDate = null, |
|
|
|
string sorting = null, |
|
|
|
int maxResultCount = int.MaxValue, |
|
|
|
int skipCount = 0, |
|
|
|
CommentApproveStateType commentApproveStateType = CommentApproveStateType.All, |
|
|
|
CancellationToken cancellationToken = default |
|
|
|
) |
|
|
|
|
|
|
|
{ |
|
|
|
//bool? isApprovedValue = ParseIsApproved(isApproved);
|
|
|
|
|
|
|
|
var token = GetCancellationToken(cancellationToken); |
|
|
|
var query = await GetListQueryAsync( |
|
|
|
filter, |
|
|
|
entityType, |
|
|
|
repliedCommentId, |
|
|
|
authorUsername, |
|
|
|
creationStartDate, |
|
|
|
creationEndDate, |
|
|
|
commentApproveStateType, |
|
|
|
token); |
|
|
|
|
|
|
|
var comments = await query.OrderBy(sorting.IsNullOrEmpty() ? "creationTime desc" : sorting) |
|
|
|
.As<IMongoQueryable<Comment>>() |
|
|
|
.PageBy<Comment, IMongoQueryable<Comment>>(skipCount, maxResultCount) |
|
|
|
.ToListAsync(token); |
|
|
|
|
|
|
|
var commentIds = comments.Select(x => x.Id).ToList(); |
|
|
|
|
|
|
|
var authorsQuery = from comment in (await GetMongoQueryableAsync(token)) |
|
|
|
join user in (await GetDbContextAsync(token)).CmsUsers on comment.CreatorId equals user.Id |
|
|
|
where commentIds.Contains(comment.Id) |
|
|
|
orderby comment.CreationTime |
|
|
|
select user; |
|
|
|
|
|
|
|
var authors = await ApplyDataFilters<IMongoQueryable<CmsUser>, CmsUser>(authorsQuery).ToListAsync(token); |
|
|
|
|
|
|
|
return comments |
|
|
|
.Select( |
|
|
|
comment => |
|
|
|
new CommentWithAuthorQueryResultItem |
|
|
|
{ |
|
|
|
Comment = comment, |
|
|
|
Author = authors.FirstOrDefault(a => a.Id == comment.CreatorId) |
|
|
|
}).ToList(); |
|
|
|
} |
|
|
|
|
|
|
|
public virtual async Task<long> GetCountAsync( |
|
|
|
string text = null, |
|
|
|
string entityType = null, |
|
|
|
Guid? repliedCommentId = null, |
|
|
|
string authorUsername = null, |
|
|
|
DateTime? creationStartDate = null, |
|
|
|
DateTime? creationEndDate = null, |
|
|
|
CommentApproveStateType commentApproveStateType = CommentApproveStateType.All, |
|
|
|
CancellationToken cancellationToken = default |
|
|
|
) |
|
|
|
{ |
|
|
|
//bool? isApprovedValue = ParseIsApproved(isApproved);
|
|
|
|
var query = await GetListQueryAsync( |
|
|
|
text, |
|
|
|
entityType, |
|
|
|
repliedCommentId, |
|
|
|
authorUsername, |
|
|
|
creationStartDate, |
|
|
|
creationEndDate, |
|
|
|
commentApproveStateType, |
|
|
|
cancellationToken); |
|
|
|
|
|
|
|
return await query.As<IMongoQueryable<Comment>>() |
|
|
|
.LongCountAsync(GetCancellationToken(cancellationToken)); |
|
|
|
} |
|
|
|
|
|
|
|
public virtual async Task<List<CommentWithAuthorQueryResultItem>> GetListWithAuthorsAsync( |
|
|
|
string entityType, |
|
|
|
string entityId, |
|
|
|
CommentApproveStateType commentApproveStateType = CommentApproveStateType.All, |
|
|
|
CancellationToken cancellationToken = default) |
|
|
|
{ |
|
|
|
Check.NotNullOrWhiteSpace(entityType, nameof(entityType)); |
|
|
|
Check.NotNullOrWhiteSpace(entityId, nameof(entityId)); |
|
|
|
|
|
|
|
var authorsQuery = from comment in (await GetMongoQueryableAsync(cancellationToken)) |
|
|
|
join user in (await GetDbContextAsync(cancellationToken)).CmsUsers on comment.CreatorId equals user.Id |
|
|
|
where entityType == comment.EntityType && entityId == comment.EntityId |
|
|
|
orderby comment.CreationTime |
|
|
|
select user; |
|
|
|
|
|
|
|
var authors = await ApplyDataFilters<IMongoQueryable<CmsUser>, CmsUser>(authorsQuery).ToListAsync(GetCancellationToken(cancellationToken)); |
|
|
|
|
|
|
|
var commentsQuery = (await GetMongoQueryableAsync(cancellationToken)) |
|
|
|
.Where(c => c.EntityId == entityId && c.EntityType == entityType); |
|
|
|
|
|
|
|
|
|
|
|
commentsQuery = (IMongoQueryable<Comment>)FilterCommentsByApprovalState(commentsQuery, commentApproveStateType); |
|
|
|
|
|
|
|
var comments = await commentsQuery |
|
|
|
.OrderBy(c => c.CreationTime) |
|
|
|
.ToListAsync(GetCancellationToken(cancellationToken)); |
|
|
|
|
|
|
|
return comments |
|
|
|
.Select( |
|
|
|
comment => |
|
|
|
new CommentWithAuthorQueryResultItem |
|
|
|
{ |
|
|
|
Comment = comment, |
|
|
|
Author = authors.FirstOrDefault(a => a.Id == comment.CreatorId) |
|
|
|
}).ToList(); |
|
|
|
} |
|
|
|
|
|
|
|
public virtual async Task DeleteWithRepliesAsync( |
|
|
|
Comment comment, |
|
|
|
CancellationToken cancellationToken = default) |
|
|
|
{ |
|
|
|
var replies = await (await GetMongoQueryableAsync(cancellationToken)) |
|
|
|
.Where(x => x.RepliedCommentId == comment.Id) |
|
|
|
.ToListAsync(GetCancellationToken(cancellationToken)); |
|
|
|
|
|
|
|
await base.DeleteAsync( |
|
|
|
comment, |
|
|
|
cancellationToken: GetCancellationToken(cancellationToken) |
|
|
|
); |
|
|
|
|
|
|
|
foreach (var reply in replies) |
|
|
|
{ |
|
|
|
await base.DeleteAsync( |
|
|
|
reply, |
|
|
|
cancellationToken: GetCancellationToken(cancellationToken) |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public virtual async Task<bool> ExistsAsync(string idempotencyToken, CancellationToken cancellationToken = default) |
|
|
|
{ |
|
|
|
return await (await GetMongoQueryableAsync(cancellationToken)) |
|
|
|
.AnyAsync(x => x.IdempotencyToken == idempotencyToken, GetCancellationToken(cancellationToken)); |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual async Task<IQueryable<Comment>> GetListQueryAsync( |
|
|
|
string filter = null, |
|
|
|
string entityType = null, |
|
|
|
Guid? repliedCommentId = null, |
|
|
|
string authorUsername = null, |
|
|
|
DateTime? creationStartDate = null, |
|
|
|
DateTime? creationEndDate = null, |
|
|
|
CommentApproveStateType commentApproveStateType = CommentApproveStateType.All, |
|
|
|
CancellationToken cancellationToken = default |
|
|
|
) |
|
|
|
{ |
|
|
|
var queryable = await GetMongoQueryableAsync(cancellationToken); |
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(authorUsername)) |
|
|
|
{ |
|
|
|
var author = await (await GetMongoQueryableAsync<CmsUser>(cancellationToken)).FirstOrDefaultAsync(x => x.UserName == authorUsername, cancellationToken: cancellationToken); |
|
|
|
|
|
|
|
var authorId = author?.Id ?? Guid.Empty; |
|
|
|
|
|
|
|
queryable = queryable.Where(x => x.CreatorId == authorId); |
|
|
|
} |
|
|
|
|
|
|
|
queryable.WhereIf(!filter.IsNullOrWhiteSpace(), c => c.Text.Contains(filter)) |
|
|
|
.WhereIf(!entityType.IsNullOrWhiteSpace(), c => c.EntityType == entityType) |
|
|
|
.WhereIf(repliedCommentId.HasValue, c => c.RepliedCommentId == repliedCommentId) |
|
|
|
.WhereIf(creationStartDate.HasValue, c => c.CreationTime >= creationStartDate) |
|
|
|
.WhereIf(creationEndDate.HasValue, c => c.CreationTime <= creationEndDate); |
|
|
|
//.WhereIf(CommentApproveStateType.True == commentApproveStateType, c => c.IsApproved == true)
|
|
|
|
//.WhereIf(CommentApproveStateType.False == commentApproveStateType, c => c.IsApproved == false)
|
|
|
|
//.WhereIf(CommentApproveStateType.Null == commentApproveStateType, c => c.IsApproved == null);
|
|
|
|
|
|
|
|
if (CommentApproveStateType.True == commentApproveStateType) |
|
|
|
{ |
|
|
|
queryable = queryable.Where(c => c.IsApproved == true); |
|
|
|
} |
|
|
|
else if (CommentApproveStateType.False == commentApproveStateType) |
|
|
|
{ |
|
|
|
queryable = queryable.Where(c => c.IsApproved == false); |
|
|
|
|
|
|
|
} |
|
|
|
else if (CommentApproveStateType.Null == commentApproveStateType) |
|
|
|
{ |
|
|
|
queryable = queryable.Where(c => c.IsApproved == null); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return queryable; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
public IQueryable<Comment> FilterCommentsByApprovalState(IQueryable<Comment> commentsQuery, CommentApproveStateType approveState) |
|
|
|
{ |
|
|
|
switch (approveState) |
|
|
|
{ |
|
|
|
case CommentApproveStateType.True: |
|
|
|
commentsQuery = commentsQuery.Where(c => c.IsApproved == true); |
|
|
|
break; |
|
|
|
case CommentApproveStateType.False: |
|
|
|
commentsQuery = commentsQuery.Where(c => c.IsApproved == true || c.IsApproved == null); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
return commentsQuery; |
|
|
|
} |
|
|
|
} |
|
|
|
|