/// <summary> /// 删除单张图片 /// </summary> /// <param name="contentId">ContentID</param> /// <returns></returns> public async Task DeleteSingleImageContentAsync(long contentId, string filePath) { using(KoalaBlogDbContext dbContext = new KoalaBlogDbContext()) { using(var dbTransaction = dbContext.Database.BeginTransaction()) { try { ContentHandler contentHandler = new ContentHandler(dbContext); //1. 根据ContentID获取Content对象。 var content = await contentHandler.GetByIdAsync(contentId); if(content != null) { FileInfo fileInfo = new FileInfo(filePath + "\\" + Path.GetFileName(content.ContentPath)); //2. 判断当前Content的图片路径是否存在图片,存在则删除图片。 if(fileInfo.Exists) { var deleteTask = Task.Factory.StartNew(() => { fileInfo.Delete(); }); contentHandler.MarkAsDeleted(content); await contentHandler.SaveChangesAsync(); await deleteTask; //3. 刷新FileInfo对象。 fileInfo.Refresh(); //4. 如果图片依旧存在证明删除失败,回滚事务。 if(fileInfo.Exists) { dbTransaction.Rollback(); } } } dbTransaction.Commit(); } catch (Exception) { dbTransaction.Rollback(); } } } }
/// <summary> /// 创建图片Content /// </summary> /// <param name="contentPath">图片路径</param> /// <param name="mimeType">图片类型</param> /// <returns></returns> public async Task<List<ContentDTO>> CreateImagesContentAsync(List<Tuple<string, string>> imageInfos) { using(KoalaBlogDbContext dbContext = new KoalaBlogDbContext()) { ContentHandler contentHandler = new ContentHandler(dbContext); //1. 根据ImageInfos集合创建Content对象。 var contents = await contentHandler.CreateImagesContentAsync(imageInfos); List<ContentDTO> contentDTOs = new List<ContentDTO>(); if(contents != null && contents.Count > 0) { //2. 生成DTO对象。 foreach (var content in contents) { contentDTOs.Add(content.ToDTO()); } } return contentDTOs; } }
public async Task Test_02_CreateBlogIncludeContentAsync() { using (KoalaBlogDbContext dbContext = new KoalaBlogDbContext()) { BlogHandler blogHandler = new BlogHandler(dbContext); ContentHandler contentHandler = new ContentHandler(dbContext); BlogXContentHandler bxcHandler = new BlogXContentHandler(dbContext); GroupHandler groupHandler = new GroupHandler(dbContext); BlogAccessControlHandler acHandler = new BlogAccessControlHandler(dbContext); BlogAccessControlXGroupHandler acxgHandler = new BlogAccessControlXGroupHandler(dbContext); List<long> contentIds = new List<long>(); Content content = new Content() { ContentPath = "testPath", ContentBinary = new byte[] { 1, 3, 5 }, Type = ContentType.Photo, MimeType = "jpg" }; contentHandler.Add(content); contentHandler.SaveChanges(); contentIds.Add(content.ID); Stopwatch sw = Stopwatch.StartNew(); //1. test normal. Blog testBlog = await blogHandler.CreateBlogAsync(testPerson.ID, "testBlog", BlogInfoAccessInfo.All, null, contentIds); var time = sw.ElapsedMilliseconds; Blog testBlog_1 = await blogHandler.GetByIdAsync(testBlog.ID); BlogAccessControl testAC_1 = await acHandler.Fetch(x => x.BlogID == testBlog_1.ID).FirstOrDefaultAsync(); BlogXContent testBXC_1 = await bxcHandler.Fetch(x => x.BlogID == testBlog_1.ID).FirstOrDefaultAsync(); Content testContent_1 = testBXC_1.Content; Assert.IsNotNull(testBlog_1); Assert.IsNotNull(testAC_1); Assert.IsNotNull(testBXC_1); Assert.IsNotNull(testContent_1); Assert.AreEqual(testBlog_1.PersonID, testPerson.ID); Assert.AreEqual(testBlog_1.Content, "testBlog"); Assert.AreEqual(testAC_1.AccessLevel, BlogInfoAccessInfo.All); Assert.AreEqual(testContent_1.ContentPath, "testPath"); Assert.AreEqual(testContent_1.ContentBinary, new byte[] { 1, 3, 5 }); //2. create test group object and test it. contentIds = new List<long>(); Content content1 = new Content() { ContentPath = "testFilePathYesOrNo", ContentBinary = new byte[] { 23, 31, 45, 78, 99 }, Type = ContentType.Video, MimeType = "jpg" }; contentHandler.Add(content1); contentHandler.SaveChanges(); contentIds.Add(content1.ID); Group testGroup = await groupHandler.CreateGroupAsync(testPerson.ID, "testGroup", GroupType.GroupList); testBlog = await blogHandler.CreateBlogAsync(testPerson.ID, "testBlogGroupOnly", BlogInfoAccessInfo.GroupOnly, testGroup.ID, contentIds); Blog testBlog_2 = await blogHandler.GetByIdAsync(testBlog.ID); BlogAccessControl testAC_2 = await acHandler.Fetch(x => x.BlogID == testBlog_2.ID).FirstOrDefaultAsync(); BlogAccessControlXGroup testACXG_2 = await acxgHandler.Fetch(x => x.GroupID == testGroup.ID && x.BlogAccessControlID == testAC_2.ID).FirstOrDefaultAsync(); BlogXContent testBXC_2 = await bxcHandler.Fetch(x => x.BlogID == testBlog_2.ID).FirstOrDefaultAsync(); Content testContent_2 = testBXC_2.Content; Assert.IsNotNull(testBlog_2); Assert.IsNotNull(testAC_2); Assert.IsNotNull(testACXG_2); Assert.IsNotNull(testBXC_2); Assert.IsNotNull(testContent_2); Assert.AreEqual(testBlog_2.PersonID, testPerson.ID); Assert.AreEqual(testBlog_2.Content, "testBlogGroupOnly"); Assert.AreEqual(testAC_2.AccessLevel, BlogInfoAccessInfo.GroupOnly); Assert.AreEqual(testContent_2.ContentPath, "testFilePathYesOrNo"); Assert.AreEqual(testContent_2.ContentBinary, new byte[] { 23, 31, 45, 78, 99 }); Assert.AreEqual(testContent_2.Type, ContentType.Video); } using(KoalaBlogDbContext dbContext = new KoalaBlogDbContext()) { BlogHandler blogHandler = new BlogHandler(dbContext); ContentHandler contentHandler = new ContentHandler(dbContext); BlogXContentHandler bxcHandler = new BlogXContentHandler(dbContext); GroupHandler groupHandler = new GroupHandler(dbContext); BlogAccessControlHandler acHandler = new BlogAccessControlHandler(dbContext); BlogAccessControlXGroupHandler acxgHandler = new BlogAccessControlXGroupHandler(dbContext); List<long> contentIds = new List<long>(); //3. create test group object but set BlogInfoAccessInfo other value. Content content1 = new Content() { ContentPath = "testFilePathYesOrNo", ContentBinary = new byte[] { 23, 31, 45, 78, 99 }, Type = ContentType.Video, MimeType = "jpg" }; contentHandler.Add(content1); contentHandler.SaveChanges(); contentIds.Add(content1.ID); Group testGroup_1 = await groupHandler.CreateGroupAsync(testPerson.ID, "testGroupWithTest", GroupType.GroupList); Blog testBlog = await blogHandler.CreateBlogAsync(testPerson.ID, "testBlogNotSetGroupOnly", BlogInfoAccessInfo.MyselfOnly, testGroup_1.ID, contentIds); Blog testBlog_3 = await blogHandler.GetByIdAsync(testBlog.ID); BlogAccessControl testAC_3 = await acHandler.Fetch(x => x.BlogID == testBlog_3.ID).FirstOrDefaultAsync(); BlogAccessControlXGroup testACXG_3 = await acxgHandler.Fetch(x => x.GroupID == testGroup_1.ID && x.BlogAccessControlID == testAC_3.ID).FirstOrDefaultAsync(); BlogXContent testBXC_3 = await bxcHandler.Fetch(x => x.BlogID == testBlog_3.ID).FirstOrDefaultAsync(); Content testContent_3 = testBXC_3.Content; Assert.IsNotNull(testBlog_3); Assert.IsNotNull(testAC_3); Assert.IsNotNull(testBXC_3); Assert.IsNotNull(testContent_3); //it expect null because BlogInfoAccessInfo is not GroupOnly. Assert.IsNull(testACXG_3); Assert.AreEqual(testBlog_3.PersonID, testPerson.ID); Assert.AreEqual(testBlog_3.Content, "testBlogNotSetGroupOnly"); Assert.AreEqual(testAC_3.AccessLevel, BlogInfoAccessInfo.MyselfOnly); Assert.AreEqual(testContent_3.ContentPath, "testFilePathYesOrNo"); Assert.AreEqual(testContent_3.ContentBinary, new byte[] { 23, 31, 45, 78, 99 }); Assert.AreEqual(testContent_3.Type, ContentType.Video); //4. create multiple content and test it. contentIds = new List<long>(); for (int i = 0; i < 3; i++) { Content c = new Content() { ContentPath = "testMultiplePath", ContentBinary = new byte[] { 12, 3, 4, 5, 7 }, Type = ContentType.Video, MimeType = "jpg" }; contentHandler.Add(c); contentHandler.SaveChanges(); contentIds.Add(c.ID); } bool isChecked = false; try { Blog testBlog_MultipleContent_1 = await blogHandler.CreateBlogAsync(testPerson.ID, "testBlogMultipleContent1", BlogInfoAccessInfo.MyselfOnly, testGroup_1.ID, contentIds); } catch (Exception ex) { isChecked = true; Assert.AreEqual(ex.GetType(), typeof(DisplayableException)); Assert.AreEqual(ex.Message, "发表视频不能超过1个"); } Assert.IsTrue(isChecked); //5. create multiple content but different type and test it. contentIds = new List<long>(); Content cPhoto = new Content() { ContentPath = "testMultiplePath", ContentBinary = new byte[] { 12, 3, 4, 5, 7 }, Type = ContentType.Photo, MimeType = "jpg" }; Content cMusic = new Content() { ContentPath = "testMultiplePath", ContentBinary = new byte[] { 12, 3, 4, 5, 7 }, Type = ContentType.Photo, MimeType = "jpg" }; Content cVideo = new Content() { ContentPath = "testMultiplePath", ContentBinary = new byte[] { 12, 3, 4, 5, 7 }, Type = ContentType.Video, MimeType = "jpg" }; contentHandler.Add(cPhoto); contentHandler.Add(cMusic); contentHandler.Add(cVideo); contentHandler.SaveChanges(); contentIds.Add(cPhoto.ID); contentIds.Add(cMusic.ID); contentIds.Add(cVideo.ID); isChecked = false; try { Blog testBlog_MultipleContent_2 = await blogHandler.CreateBlogAsync(testPerson.ID, "testBlogMultipleContent1", BlogInfoAccessInfo.MyselfOnly, testGroup_1.ID, contentIds); } catch (Exception ex) { isChecked = true; Assert.AreEqual(ex.GetType(), typeof(DisplayableException)); Assert.AreEqual(ex.Message, "不能发不同类型内容的Blog"); } Assert.IsTrue(isChecked); //6. create some photo content and test it. contentIds = new List<long>(); for (int i = 0; i < 6; i++) { Content photo = new Content() { ContentPath = "testPhotoContentPath", ContentBinary = new byte[] { 12, 3, 4, 5, 7 }, Type = ContentType.Photo, MimeType = "jpg" }; contentHandler.Add(photo); contentHandler.SaveChanges(); contentIds.Add(photo.ID); } Group testGroup_2 = await groupHandler.CreateGroupAsync(testPerson.ID, "testGroupWithTest", GroupType.GroupList); Blog testBlog_MultiplePhoto_3 = await blogHandler.CreateBlogAsync(testPerson.ID, "testBlogMultiplePhoto", BlogInfoAccessInfo.GroupOnly, testGroup_2.ID, contentIds); Blog testPhotoBlog = await blogHandler.GetByIdAsync(testBlog_MultiplePhoto_3.ID); BlogAccessControl testPhotoAC = await acHandler.Fetch(x => x.BlogID == testPhotoBlog.ID).FirstOrDefaultAsync(); BlogAccessControlXGroup testPhotoACXG = await acxgHandler.Fetch(x => x.GroupID == testGroup_2.ID && x.BlogAccessControlID == testPhotoAC.ID).FirstOrDefaultAsync(); List<BlogXContent> testPhotoBXC = await bxcHandler.Fetch(x => x.BlogID == testPhotoBlog.ID).ToListAsync(); Assert.IsFalse(testPhotoBlog.IsDeleted); Assert.IsNotNull(testPhotoBlog); Assert.IsNotNull(testPhotoAC); Assert.IsNotNull(testPhotoACXG); Assert.IsNotNull(testPhotoBXC); Assert.AreEqual(testPhotoBXC.Count, 6); Assert.AreEqual(testPhotoBlog.PersonID, testPerson.ID); Assert.AreEqual(testPhotoBlog.Content, "testBlogMultiplePhoto"); Assert.AreEqual(testPhotoAC.AccessLevel, BlogInfoAccessInfo.GroupOnly); foreach (var photoBXC in testPhotoBXC) { Assert.IsNotNull(photoBXC.Content); Assert.AreEqual(photoBXC.Content.Type, ContentType.Photo); Assert.AreEqual(photoBXC.Content.ContentPath, "testPhotoContentPath"); Assert.AreEqual(photoBXC.Content.ContentBinary, new byte[] { 12, 3, 4, 5, 7 }); } } }
public async Task Test_03_ForwardBlogAsync() { using(KoalaBlogDbContext dbContext = new KoalaBlogDbContext()) { BlogHandler blogHandler = new BlogHandler(dbContext); BlogXBlogHandler bxbHandler = new BlogXBlogHandler(dbContext); ContentHandler contentHandler = new ContentHandler(dbContext); BlogXContentHandler bxcHandler = new BlogXContentHandler(dbContext); GroupHandler groupHandler = new GroupHandler(dbContext); BlogAccessControlHandler acHandler = new BlogAccessControlHandler(dbContext); BlogAccessControlXGroupHandler acxgHandler = new BlogAccessControlXGroupHandler(dbContext); //1. without content and test it. Blog testBlog = await blogHandler.CreateBlogAsync(testPerson.ID, "testWithoutContentForwardBlog", BlogInfoAccessInfo.All, null); Blog beForwardBlog = await blogHandler.GetByIdAsync(testBlog.ID); Assert.IsNotNull(beForwardBlog); Assert.AreEqual(beForwardBlog.Content, "testWithoutContentForwardBlog"); //create forward blog Blog testForwardBlog_NoContent = await blogHandler.CreateBlogAsync(testPerson.ID, "testForwardBlogNoContent", BlogInfoAccessInfo.All, null, null, beForwardBlog.ID); Blog testForwardBlog = await blogHandler.GetByIdAsync(testForwardBlog_NoContent.ID); Assert.IsNotNull(testForwardBlog); Assert.IsFalse(testForwardBlog.IsDeleted); Assert.AreEqual(testForwardBlog.Content, "testForwardBlogNoContent"); Assert.AreEqual(testForwardBlog.NewBlogXBlogs.Count, 1); Assert.IsNotNull(testForwardBlog.NewBlogXBlogs.First().NewBlog); Assert.IsNotNull(testForwardBlog.NewBlogXBlogs.First().BaseBlog); Assert.AreEqual(testForwardBlog.NewBlogXBlogs.First().NewBlog.Content, "testForwardBlogNoContent"); Assert.AreEqual(testForwardBlog.NewBlogXBlogs.First().BaseBlog.Content, "testWithoutContentForwardBlog"); //2. set error forward blog id and test it. bool isChecked = false; try { Blog testErrorForwardBlogID = await blogHandler.CreateBlogAsync(testPerson.ID, "testForwardBlogNoContent", BlogInfoAccessInfo.All, null, null, 99999); } catch (Exception ex) { isChecked = true; Assert.AreEqual(ex.GetType(), typeof(DisplayableException)); Assert.AreEqual(ex.Message, "该Blog不存在或者已经被删除"); } Assert.IsTrue(isChecked); //3. include content and test it. List<long> contentIds = new List<long>(); for (int i = 0; i < 6; i++) { Content photo = new Content() { ContentPath = "testPhotoContentPath", ContentBinary = new byte[] { 12, 3, 4, 5, 7 }, Type = ContentType.Photo, MimeType = "jpg" }; contentHandler.Add(photo); contentHandler.SaveChanges(); contentIds.Add(photo.ID); } Blog testIncludeContentBeForwardBlog = await blogHandler.CreateBlogAsync(testPerson.ID, "testIncludeContentBeForwardBlog", BlogInfoAccessInfo.All, attachContentIds: contentIds); Blog testBeForwardBlog = await blogHandler.GetByIdAsync(testIncludeContentBeForwardBlog.ID); Assert.IsNotNull(testBeForwardBlog); Assert.IsFalse(testBeForwardBlog.IsDeleted); Assert.AreEqual(testBeForwardBlog.Content, "testIncludeContentBeForwardBlog"); Assert.AreEqual(testBeForwardBlog.BlogXContents.Count, 6); Assert.IsTrue(testBeForwardBlog.BlogXContents.Any(x => x.BlogID == testBeForwardBlog.ID && x.Content.ContentPath == "testPhotoContentPath" && x.Content.Type == ContentType.Photo)); //forward the blog. contentIds = new List<long>(); Content video = new Content() { ContentPath = "testVideoContentPath", ContentBinary = new byte[] { 1, 3, 5, 6, 99 }, Type = ContentType.Video, MimeType = "jpg" }; contentHandler.Add(video); contentHandler.SaveChanges(); contentIds.Add(video.ID); Blog testIncludeContentForwardBlog = await blogHandler.CreateBlogAsync(testPerson.ID, "testIncludeContentForwardBlog", BlogInfoAccessInfo.All, attachContentIds: contentIds, forwardBlogId: testBeForwardBlog.ID); Blog testForwardBlogIncludeContent = await blogHandler.GetByIdAsync(testIncludeContentForwardBlog.ID); Assert.IsNotNull(testForwardBlogIncludeContent); Assert.IsFalse(testForwardBlogIncludeContent.IsDeleted); Assert.AreEqual(testForwardBlogIncludeContent.Content, "testIncludeContentForwardBlog"); Assert.AreEqual(testForwardBlogIncludeContent.BlogXContents.Count, 1); Assert.IsTrue(testForwardBlogIncludeContent.BlogXContents.Any(x => x.BlogID == testForwardBlogIncludeContent.ID && x.Content.ContentPath == "testVideoContentPath" && x.Content.Type == ContentType.Video)); Assert.AreEqual(testForwardBlogIncludeContent.NewBlogXBlogs.Count, 1); Assert.IsNotNull(testForwardBlogIncludeContent.NewBlogXBlogs.First().NewBlog); Assert.IsNotNull(testForwardBlogIncludeContent.NewBlogXBlogs.First().BaseBlog); Assert.AreEqual(testForwardBlogIncludeContent.NewBlogXBlogs.First().NewBlog.Content, "testIncludeContentForwardBlog"); Assert.AreEqual(testForwardBlogIncludeContent.NewBlogXBlogs.First().BaseBlog.Content, "testIncludeContentBeForwardBlog"); Assert.AreEqual(testForwardBlogIncludeContent.NewBlogXBlogs.First().NewBlog.BlogXContents.Count, 1); Assert.AreEqual(testForwardBlogIncludeContent.NewBlogXBlogs.First().BaseBlog.BlogXContents.Count, 6); foreach (var newBlogContent in testForwardBlogIncludeContent.NewBlogXBlogs.First().NewBlog.BlogXContents) { Assert.AreEqual(newBlogContent.Blog.ID, testForwardBlogIncludeContent.ID); Assert.AreEqual(newBlogContent.Content.ContentPath, "testVideoContentPath"); Assert.AreEqual(newBlogContent.Content.ContentBinary, new byte[] { 1, 3, 5, 6, 99 }); } foreach (var baseBlogContent in testForwardBlogIncludeContent.NewBlogXBlogs.First().BaseBlog.BlogXContents) { Assert.AreEqual(baseBlogContent.Blog.ID, testBeForwardBlog.ID); Assert.AreEqual(baseBlogContent.Content.ContentPath, "testPhotoContentPath"); Assert.AreEqual(baseBlogContent.Content.ContentBinary, new byte[] { 12, 3, 4, 5, 7 }); } } }
public async Task Test_04_AddCommentAllowableCheck() { long eddyId = 0; long eastId = 0; long blogId = 0; using(KoalaBlogDbContext dbContext = new KoalaBlogDbContext()) { BlogHandler blogHandler = new BlogHandler(dbContext); ContentHandler contentHandler = new ContentHandler(dbContext); CommentHandler commentHandler = new CommentHandler(dbContext); //1. check allow follower comment. Person eddy = CreatePerson("TestEddy", "TestEddy", AllowablePersonForComment.FollowerOnly, true); Person east = CreatePerson("TestEast", "TestEast", AllowablePersonForComment.FollowerOnly, true); Blog testBlog = await blogHandler.CreateBlogAsync(eddy.ID, "TestCommentBlog", BlogInfoAccessInfo.MyselfOnly); bool isChecked = false; try { Comment comment = await commentHandler.AddCommentAsync(east.ID, testBlog.ID, "hey, i am new comment test."); } catch (Exception ex) { isChecked = true; Assert.AreEqual(ex.GetType(), typeof(DisplayableException)); Assert.AreEqual(ex.Message, "由于用户设置,你无法回复评论。"); } Assert.IsTrue(isChecked); eddyId = eddy.ID; eastId = east.ID; blogId = testBlog.ID; } using (KoalaBlogDbContext dbContext = new KoalaBlogDbContext()) { BlogHandler blogHandler = new BlogHandler(dbContext); ContentHandler contentHandler = new ContentHandler(dbContext); CommentHandler commentHandler = new CommentHandler(dbContext); //1.1 eddy follow east, and test it again. Follow(eddyId, eastId); Comment comment_1 = await commentHandler.AddCommentAsync(eastId, blogId, "hey, i am new comment test."); Assert.IsNotNull(comment_1); } long alienId = 0; long paulId = 0; long fansBlogId = 0; using (KoalaBlogDbContext dbContext = new KoalaBlogDbContext()) { BlogHandler blogHandler = new BlogHandler(dbContext); ContentHandler contentHandler = new ContentHandler(dbContext); CommentHandler commentHandler = new CommentHandler(dbContext); //1. check allow fans comment. Person alien = CreatePerson("TestAlien", "TestAlien", AllowablePersonForComment.FansOnly, true); Person paul = CreatePerson("TestPaul", "TestPaul", AllowablePersonForComment.FollowerOnly, true); Blog testBlog = await blogHandler.CreateBlogAsync(alien.ID, "TestCommentBlog", BlogInfoAccessInfo.MyselfOnly); bool isChecked = false; try { Comment comment = await commentHandler.AddCommentAsync(paul.ID, testBlog.ID, "hey, i am new comment test."); } catch (Exception ex) { isChecked = true; Assert.AreEqual(ex.GetType(), typeof(DisplayableException)); Assert.AreEqual(ex.Message, "由于用户设置,你无法回复评论。"); } Assert.IsTrue(isChecked); alienId = alien.ID; paulId = paul.ID; fansBlogId = testBlog.ID; } using (KoalaBlogDbContext dbContext = new KoalaBlogDbContext()) { BlogHandler blogHandler = new BlogHandler(dbContext); ContentHandler contentHandler = new ContentHandler(dbContext); CommentHandler commentHandler = new CommentHandler(dbContext); Follow(paulId, alienId); Comment comment_1 = await commentHandler.AddCommentAsync(paulId, fansBlogId, "hey, i am new comment test."); Assert.IsNotNull(comment_1); } using (KoalaBlogDbContext dbContext = new KoalaBlogDbContext()) { BlogHandler blogHandler = new BlogHandler(dbContext); ContentHandler contentHandler = new ContentHandler(dbContext); CommentHandler commentHandler = new CommentHandler(dbContext); //1. check allow fans comment. Person alien = CreatePerson("TestAlien", "TestAlien", AllowablePersonForComment.All, false); Person paul = CreatePerson("TestPaul", "TestPaul", AllowablePersonForComment.FollowerOnly, true); List<long> contentIds = new List<long>(); Content content = new Content() { ContentPath = "testPath", ContentBinary = new byte[] { 1, 3, 5 }, Type = ContentType.Photo, MimeType = "jpg" }; contentHandler.Add(content); contentHandler.SaveChanges(); contentIds.Add(content.ID); Blog testBlog = await blogHandler.CreateBlogAsync(alien.ID, "TestCommentBlog", BlogInfoAccessInfo.MyselfOnly); bool isChecked = false; try { Comment comment = await commentHandler.AddCommentAsync(paul.ID, testBlog.ID, "hey, i am new comment test.", photoContentIds: contentIds); } catch (Exception ex) { isChecked = true; Assert.AreEqual(ex.GetType(), typeof(DisplayableException)); Assert.AreEqual(ex.Message, "由于用户设置,你回复评论无法添加图片。"); } Assert.IsTrue(isChecked); } }
public async Task Test_03_AddCommentIncludeBaseComment() { using(KoalaBlogDbContext dbContext = new KoalaBlogDbContext()) { BlogHandler blogHandler = new BlogHandler(dbContext); ContentHandler contentHandler = new ContentHandler(dbContext); CommentHandler commentHandler = new CommentHandler(dbContext); CommentXCommentHandler cxcHandler = new CommentXCommentHandler(dbContext); CommentXContentHandler ccHandler = new CommentXContentHandler(dbContext); Person rain = CreatePerson("TestRain", "TestRain", AllowablePersonForComment.All, true); Blog testBlog = await blogHandler.CreateBlogAsync(rain.ID, "TestCommentBlog", BlogInfoAccessInfo.MyselfOnly); //1. test normal. List<long> contentIds = new List<long>(); Content content = new Content() { ContentPath = "testBeCommentPath", ContentBinary = new byte[] { 1, 3, 5 }, Type = ContentType.Photo, MimeType = "jpg" }; contentHandler.Add(content); contentHandler.SaveChanges(); contentIds.Add(content.ID); Comment beComment = await commentHandler.AddCommentAsync(commentPerson.ID, testBlog.ID, "hey, i am be comment test.", photoContentIds: contentIds); Comment test_beComment = await commentHandler.GetByIdAsync(beComment.ID); Assert.IsNotNull(test_beComment); Assert.AreEqual(test_beComment.PersonID, commentPerson.ID); Assert.AreEqual(test_beComment.BlogID, testBlog.ID); Assert.AreEqual(test_beComment.Content, "hey, i am be comment test."); Assert.AreEqual(test_beComment.CommentXContents.Count, 1); Assert.AreEqual(test_beComment.CommentXContents.First().Content.ContentPath, "testBeCommentPath"); Assert.AreEqual(test_beComment.CommentXContents.First().Content.Type, ContentType.Photo); Assert.AreEqual(test_beComment.CommentXContents.First().Content.ContentBinary, new byte[] { 1, 3, 5 }); contentIds = new List<long>(); Content newCommentContent = new Content() { ContentPath = "testBeCommentPath", ContentBinary = new byte[] { 1, 3, 5 }, Type = ContentType.Photo, MimeType = "jpg" }; contentHandler.Add(newCommentContent); contentHandler.SaveChanges(); contentIds.Add(newCommentContent.ID); Comment newComment = await commentHandler.AddCommentAsync(commentPerson.ID, testBlog.ID, "hey, i am new comment test.", photoContentIds: contentIds, baseCommentId: test_beComment.ID); Comment test_newComment = await commentHandler.GetByIdAsync(newComment.ID); Assert.IsNotNull(test_newComment); Assert.AreEqual(test_newComment.PersonID, commentPerson.ID); Assert.AreEqual(test_newComment.BlogID, testBlog.ID); Assert.AreEqual(test_newComment.Content, "hey, i am new comment test."); Assert.AreEqual(test_newComment.CommentXContents.Count, 1); Assert.AreEqual(test_newComment.NewCommentXComments.Count, 1); Assert.AreEqual(test_newComment.CommentXContents.First().Content.ContentPath, "testBeCommentPath"); Assert.AreEqual(test_newComment.CommentXContents.First().Content.Type, ContentType.Photo); Assert.AreEqual(test_newComment.CommentXContents.First().Content.ContentBinary, new byte[] { 1, 3, 5 }); Assert.AreEqual(test_newComment.NewCommentXComments.First().BaseComment.ID, test_beComment.ID); Assert.AreEqual(test_newComment.NewCommentXComments.First().NewComment.ID, test_newComment.ID); Assert.AreEqual(test_newComment.NewCommentXComments.First().BaseComment.Content, "hey, i am be comment test."); Assert.AreEqual(test_newComment.NewCommentXComments.First().NewComment.Content, "hey, i am new comment test."); //2. delete a comment and test it. bool isChecked = false; try { long tmpCommentId = test_beComment.ID; //delete comment. //2.1 first, delete all navigation for comment. for (int i = 0; i < test_beComment.BaseCommentXComments.Count; i++) { cxcHandler.MarkAsDeleted(test_beComment.BaseCommentXComments.ElementAt(i)); } await cxcHandler.SaveChangesAsync(); for (int i = 0; i < test_beComment.CommentXContents.Count; i++) { ccHandler.MarkAsDeleted(test_beComment.CommentXContents.ElementAt(i)); } await ccHandler.SaveChangesAsync(); //2.2 then, delete comment. commentHandler.MarkAsDeleted(test_beComment); await commentHandler.SaveChangesAsync(); Comment test_notExistComment = await commentHandler.AddCommentAsync(commentPerson.ID, testBlog.ID, "hey, i am new comment test.", baseCommentId: tmpCommentId); } catch (Exception ex) { isChecked = true; Assert.AreEqual(ex.GetType(), typeof(DisplayableException)); Assert.AreEqual(ex.Message, "此评论不存在或者已经被删除"); } Assert.IsTrue(isChecked); } }
public async Task Test_02_AddCommentIncludeContent() { using(KoalaBlogDbContext dbContext = new KoalaBlogDbContext()) { BlogHandler blogHandler = new BlogHandler(dbContext); ContentHandler contentHandler = new ContentHandler(dbContext); CommentHandler commentHandler = new CommentHandler(dbContext); Person jay = CreatePerson("TestJay", "TestJay", AllowablePersonForComment.All, true); Blog testBlog = await blogHandler.CreateBlogAsync(jay.ID, "TestCommentBlog", BlogInfoAccessInfo.MyselfOnly); //1. normal test. List<long> contentIds = new List<long>(); Content content = new Content() { ContentPath = "testPath", ContentBinary = new byte[] { 1, 3, 5 }, Type = ContentType.Photo, MimeType = "jpg" }; contentHandler.Add(content); contentHandler.SaveChanges(); contentIds.Add(content.ID); Comment testComment = await commentHandler.AddCommentAsync(commentPerson.ID, testBlog.ID, "hello, i am a comment include content", photoContentIds: contentIds); Comment testNormalComment = await commentHandler.GetByIdAsync(testComment.ID); Assert.IsNotNull(testNormalComment); Assert.AreEqual(testNormalComment.PersonID, commentPerson.ID); Assert.AreEqual(testNormalComment.BlogID, testBlog.ID); Assert.AreEqual(testNormalComment.Content, "hello, i am a comment include content"); Assert.AreEqual(testNormalComment.CommentXContents.Count, 1); Assert.AreEqual(testNormalComment.CommentXContents.First().Content.ContentPath, "testPath"); Assert.AreEqual(testNormalComment.CommentXContents.First().Content.Type, ContentType.Photo); Assert.AreEqual(testNormalComment.CommentXContents.First().Content.ContentBinary, new byte[] { 1, 3, 5 }); //2. test multiple content. contentIds = new List<long>(); for (int i = 0; i < 5; i++) { Content photoContent = new Content() { ContentPath = "testMultiplePath", ContentBinary = new byte[] { 3, 6, 9 }, Type = ContentType.Photo, MimeType = "jpg" }; contentHandler.Add(photoContent); contentHandler.SaveChanges(); contentIds.Add(photoContent.ID); } Comment testComment_1 = await commentHandler.AddCommentAsync(commentPerson.ID, testBlog.ID, "hello, i am a multiple comment include content oh yes", photoContentIds: contentIds); Comment testMultipleComment = await commentHandler.GetByIdAsync(testComment_1.ID); Assert.IsNotNull(testMultipleComment); Assert.AreEqual(testMultipleComment.PersonID, commentPerson.ID); Assert.AreEqual(testMultipleComment.BlogID, testBlog.ID); Assert.AreEqual(testMultipleComment.Content, "hello, i am a multiple comment include content oh yes"); Assert.AreEqual(testMultipleComment.CommentXContents.Count, 5); Assert.AreEqual(testMultipleComment.CommentXContents.First().Content.ContentPath, "testMultiplePath"); Assert.AreEqual(testMultipleComment.CommentXContents.First().Content.Type, ContentType.Photo); Assert.AreEqual(testMultipleComment.CommentXContents.First().Content.ContentBinary, new byte[] { 3, 6, 9 }); //3. set the content type is video or music and test it. bool isChecked = false; try { contentIds = new List<long>(); for (int i = 0; i < 5; i++) { Content photoContent = new Content() { ContentPath = "testMultiplePath", ContentBinary = new byte[] { 3, 6, 9 }, Type = i % 2 == 0 ? ContentType.Music : ContentType.Video, MimeType = "jpg" }; contentHandler.Add(photoContent); contentHandler.SaveChanges(); contentIds.Add(photoContent.ID); } Comment testComment_2 = await commentHandler.AddCommentAsync(commentPerson.ID, testBlog.ID, "hello, i am a multiple comment include content but type not photo", photoContentIds: contentIds); } catch (Exception ex) { isChecked = true; Assert.AreEqual(ex.GetType(), typeof(DisplayableException)); Assert.AreEqual(ex.Message, "评论只能附件图片"); } Assert.IsTrue(isChecked); } }
/// <summary> /// 添加一条评论 /// </summary> /// <param name="personId">评论者ID</param> /// <param name="blogId">评论的BlogID</param> /// <param name="content">评论内容</param> /// <param name="photoContentIds">评论的附件ID(仅限图片)</param> /// <param name="baseCommentId">被评论的CommentID</param> /// <returns></returns> public async Task<Comment> AddCommentAsync(long personId, long blogId, string content, List<long> photoContentIds = null, long? baseCommentId = null) { BlogHandler blogHandler = new BlogHandler(_dbContext); GroupHandler groupHandler = new GroupHandler(_dbContext); PersonHandler perHandler = new PersonHandler(_dbContext); //1. 检查要评论的Blog是否存在。 Blog beCommentBlog = await blogHandler.GetByIdAsync(blogId); //2. 如果为空或者被逻辑删除,则Exception。 if (beCommentBlog == null || beCommentBlog.IsDeleted) { throw new DisplayableException("要评论的Blog不存在或者已经被删除"); } //2.1 自己评论自己的Blog永远可以,所以只需要判断不同的PersonID。 if(beCommentBlog.PersonID != personId) { //3. 检查当前用户是否被该评论Blog的用户加入了黑名单,如果是则不能进行评论。 Group beCommentBlogPersonBlackList = await groupHandler.Include(x => x.GroupMembers).SingleOrDefaultAsync(x => x.PersonID == beCommentBlog.PersonID && x.Type == GroupType.BlackList); if (beCommentBlogPersonBlackList != null && beCommentBlogPersonBlackList.GroupMembers.Count > 0) { bool isBlocked = beCommentBlogPersonBlackList.GroupMembers.Select(x => x.PersonID).Contains(personId); if (isBlocked) { throw new DisplayableException("由于用户设置,你无法回复评论。"); } } //4. 检查评论Blog的用户消息设置,是否允许评论。 Person beCommentBlogPerson = await perHandler.GetByIdAsync(beCommentBlog.PersonID); if (beCommentBlogPerson != null) { //4.1 如果评论只允许关注的人评论,则判断Blog的用户的是否关注了当前用户。 if (beCommentBlogPerson.AllowablePersonForComment == AllowablePersonForComment.FollowerOnly) { //4.2 判断关注的人集合是否已经加载。 if (!_dbContext.Entry(beCommentBlogPerson).Collection(x => x.MyFollowingPersons).IsLoaded) { _dbContext.Entry(beCommentBlogPerson).Collection(x => x.MyFollowingPersons).Load(); } bool isFollow = beCommentBlogPerson.MyFollowingPersons.Select(x => x.FollowingID).Contains(personId); if (!isFollow) { throw new DisplayableException("由于用户设置,你无法回复评论。"); } } //4.3 如果评论只允许粉丝评论,则判断当前用户是否关注了该Blog用户。 else if (beCommentBlogPerson.AllowablePersonForComment == AllowablePersonForComment.FansOnly) { //4.4 判断粉丝集合是否已经加载。 if (!_dbContext.Entry(beCommentBlogPerson).Collection(x => x.MyFans).IsLoaded) { _dbContext.Entry(beCommentBlogPerson).Collection(x => x.MyFans).Load(); } bool isFans = beCommentBlogPerson.MyFans.Select(x => x.FollowerID).Contains(personId); if (!isFans) { throw new DisplayableException("由于用户设置,你无法回复评论。"); } } } //5. 检查评论Blog的用户消息设置,是否允许评论附带图片。 if(photoContentIds != null && photoContentIds.Count > 0) { if(!beCommentBlogPerson.AllowCommentAttachContent) { throw new DisplayableException("由于用户设置,你回复评论无法添加图片。"); } } } using(var dbTransaction = _dbContext.Database.BeginTransaction()) { try { //6. 建立Comment对象并保存。 Comment comment = new Comment() { PersonID = personId, BlogID = blogId, Content = content }; this.Add(comment); await SaveChangesAsync(); //7. 判断是否有图片,有则建立与Comment的关联。 if (photoContentIds != null && photoContentIds.Count > 0) { if(photoContentIds.Count > 6) { throw new DisplayableException("评论最多附件6张图片"); } ContentHandler contentHandler = new ContentHandler(_dbContext); //7.1 判断附件是否为图片。 List<Content> photoContents = await contentHandler.Fetch(x => photoContentIds.Contains(x.ID)).ToListAsync(); if(!photoContents.Any(x => x.Type == ContentType.Photo)) { throw new DisplayableException("评论只能附件图片"); } //7.2 建立Comment与Content的关联。 CommentXContentHandler cxcHandler = new CommentXContentHandler(_dbContext); foreach (var photoContentId in photoContentIds) { CommentXContent cxc = new CommentXContent() { CommentID = comment.ID, ContentID = photoContentId }; cxcHandler.Add(cxc); } await SaveChangesAsync(); } //8. 判断当前评论是否评论Blog里的其他评论,如果是则建立关联。 if(baseCommentId != null) { //8.1 判断被评论ID是否存在。 Comment baseComment = await GetByIdAsync(baseCommentId); if(baseComment == null) { throw new DisplayableException("此评论不存在或者已经被删除"); } //8.2 判断被评论的BlogID是否与当前评论的BlogID一致。 if(baseComment.BlogID != blogId) { throw new DisplayableException("此评论的BlogID与被评论的BlogID不一致"); } //8.3 建立关联。 CommentXCommentHandler cxcHandler = new CommentXCommentHandler(_dbContext); CommentXComment cxc = new CommentXComment() { BaseCommentID = (long)baseCommentId, NewCommentID = comment.ID }; cxcHandler.Add(cxc); await SaveChangesAsync(); } dbTransaction.Commit(); return comment; } catch (Exception) { dbTransaction.Rollback(); throw; } } }
/// <summary> /// 发表一篇Blog /// </summary> /// <param name="personId">PersonID</param> /// <param name="content">Blog的内容</param> /// <param name="attachContents">Blog的附件</param> /// <param name="accessInfo">Blog的访问控制</param> /// <param name="groupId">当Blog的访问控制为群可见则需要指定GroupID</param> /// <param name="forwardBlogId">转发的BlogID</param> /// <returns></returns> public async Task<Blog> CreateBlogAsync(long personId, string content, BlogInfoAccessInfo accessInfo, long? groupId = null, List<long> attachContentIds = null, long? forwardBlogId = null) { using(var dbTransaction = _dbContext.Database.BeginTransaction()) { try { BlogAccessControlHandler bacHandler = new BlogAccessControlHandler(_dbContext); //1. 创建Blog对象并保存。 Blog blog = new Blog() { PersonID = personId, Content = content, IsDeleted = false }; this.Add(blog); await SaveChangesAsync(); //2. 判断是否有附件,有则建立与Blog的关联。 if (attachContentIds != null && attachContentIds.Count > 0) { ContentHandler contentHandler = new ContentHandler(_dbContext); BlogXContentHandler bxcHandler = new BlogXContentHandler(_dbContext); #region 检查attachContent集合。 List<Content> attachContents = await contentHandler.Fetch(x => attachContentIds.Contains(x.ID)).ToListAsync(); bool isDifferentType = attachContents.Select(x => x.Type).Distinct().Count() > 1; if(isDifferentType) { throw new DisplayableException("不能发不同类型内容的Blog"); } int photoCount = attachContents.Count(x => x.Type == ContentType.Photo); int musicCount = attachContents.Count(x => x.Type == ContentType.Music); int videoCount = attachContents.Count(x => x.Type == ContentType.Video); if(photoCount > 6) { throw new DisplayableException("发表图片不能超过6张"); } if (musicCount > 1) { throw new DisplayableException("发表音乐不能超过1首"); } if (videoCount > 1) { throw new DisplayableException("发表视频不能超过1个"); } #endregion foreach (var attachContentId in attachContentIds) { BlogXContent bxc = new BlogXContent() { BlogID = blog.ID, ContentID = attachContentId }; bxcHandler.Add(bxc); } await SaveChangesAsync(); } //3. 判断当前是否转发Blog,是则建立转发Blog与新Blog的关联。 if(forwardBlogId.HasValue) { //3.1 判断ForwardBlog是否存在。 Blog forwardBlog = await GetByIdAsync(forwardBlogId); if(forwardBlog == null || forwardBlog.IsDeleted) { throw new DisplayableException("该Blog不存在或者已经被删除"); } //3.2 判断ForwardBlog是否转发了Blog,如果是则关联2条Blog,否则只关联当前要转发的Blog。 BlogXBlogHandler bxbHandler = new BlogXBlogHandler(_dbContext); BlogXBlog blogXblog = new BlogXBlog(); blogXblog.NewBlogID = blog.ID; blogXblog.BaseBlogID = forwardBlog.ID; blogXblog.IsBase = false; //3.3 判断ForwardBlog是否有转发Blog。 Blog baseBlog = await bxbHandler.GetBaseBlogByBlogIdAsync(forwardBlog.ID); if(baseBlog == null) { blogXblog.IsBase = true; } else { BlogXBlog baseBlogXblog = new BlogXBlog(); baseBlogXblog.NewBlogID = blog.ID; baseBlogXblog.BaseBlogID = baseBlog.ID; baseBlogXblog.IsBase = true; bxbHandler.Add(baseBlogXblog); } bxbHandler.Add(blogXblog); await SaveChangesAsync(); } //4. 建立AccessControl访问控制。 BlogAccessControl blogAccessControl = new BlogAccessControl() { BlogID = blog.ID, AccessLevel = accessInfo }; bacHandler.Add(blogAccessControl); await SaveChangesAsync(); //5. 判断如果访问控制为GroupOnly,则建立AccessControlXGroup关系。 if(accessInfo == BlogInfoAccessInfo.GroupOnly) { if(groupId == null) { throw new DisplayableException("未指定组"); } BlogAccessControlXGroupHandler bacxgHandler = new BlogAccessControlXGroupHandler(_dbContext); BlogAccessControlXGroup bacxg = new BlogAccessControlXGroup() { BlogAccessControlID = blogAccessControl.ID, GroupID = (long)groupId }; bacxgHandler.Add(bacxg); await SaveChangesAsync(); } dbTransaction.Commit(); return blog; } catch (Exception) { dbTransaction.Rollback(); throw; } } }