diff --git a/src/Orchard.Tests.Modules/DatabaseEnabledTestsBase.cs b/src/Orchard.Tests.Modules/DatabaseEnabledTestsBase.cs index ad264956d..b981fdb2b 100644 --- a/src/Orchard.Tests.Modules/DatabaseEnabledTestsBase.cs +++ b/src/Orchard.Tests.Modules/DatabaseEnabledTestsBase.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using Autofac; @@ -64,8 +65,10 @@ namespace Orchard.Tests.Modules { } protected void ClearSession() { + Trace.WriteLine("Flush and clear session"); _session.Flush(); _session.Clear(); + Trace.WriteLine("Flushed and cleared session"); } } } \ No newline at end of file diff --git a/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj b/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj index 48695f518..04182d1a9 100644 --- a/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj +++ b/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj @@ -146,6 +146,7 @@ + @@ -199,6 +200,10 @@ {8C7FCBC2-E6E1-405E-BFB5-D8D9E67A09C4} Orchard.Setup + + {5D0F00F0-26C9-4785-AD61-B85710C60EB0} + Orchard.Tags + {CDE24A24-01D3-403C-84B9-37722E18DFB7} Orchard.Themes diff --git a/src/Orchard.Tests.Modules/Tags/Services/TagsServiceTests.cs b/src/Orchard.Tests.Modules/Tags/Services/TagsServiceTests.cs new file mode 100644 index 000000000..575ebab14 --- /dev/null +++ b/src/Orchard.Tests.Modules/Tags/Services/TagsServiceTests.cs @@ -0,0 +1,260 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using Autofac; +using Moq; +using NUnit.Framework; +using Orchard.ContentManagement; +using Orchard.ContentManagement.Handlers; +using Orchard.ContentManagement.Records; +using Orchard.Data; +using Orchard.Environment; +using Orchard.Security; +using Orchard.Tags.Handlers; +using Orchard.Tags.Models; +using Orchard.Tags.Services; +using Orchard.Tests.Stubs; +using Orchard.Tests.Utility; +using Orchard.UI.Notify; + +namespace Orchard.Tests.Modules.Tags.Services { + [TestFixture] + public class TagsServiceTests : DatabaseEnabledTestsBase { + private Mock _authz; + private ITagService _tagService; + private IContentManager _contentManager; + + public override void Register(ContainerBuilder builder) { + _authz = new Mock(); + + builder.RegisterAutoMocking(MockBehavior.Loose); + builder.RegisterInstance(_authz.Object).As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)); + } + + public override void Init() { + base.Init(); + + _tagService = _container.Resolve(); + _contentManager = _container.Resolve(); + } + + + protected override IEnumerable DatabaseTypes { + get { + return new[] { + typeof(ContentItemRecord), + typeof(ContentItemVersionRecord), + typeof(ContentTypeRecord), + typeof(TagsPartRecord), + typeof(TagRecord), + typeof(ContentTagRecord) + }; + } + } + + [Test] + public void TagServiceShouldResolve() { + } + + [Test] + public void CreateTagShouldBePersistent() { + for (int i = 0; i < 10; i++) { + _tagService.CreateTag("tag" + i); + } + + ClearSession(); + + var tag5 = _tagService.GetTagByName("tag5"); + Assert.That(tag5, Is.Not.Null); + Assert.That(tag5.TagName, Is.EqualTo("tag5")); + + var tag50 = _tagService.GetTagByName("tag50"); + Assert.That(tag50, Is.Null); + } + + + [Test] + public void TagsShouldBeAvailableWhenGettingContentItem() { + var thing = _contentManager.New("thing"); + _contentManager.Create(thing); + _tagService.UpdateTagsForContentItem(thing, new string[] { "tag1", "tag2", "tag3" }); + + ClearSession(); + + var thing2 = _contentManager.Get(thing.Id); + Assert.That(thing2.As().CurrentTags.Any(tagRecord => tagRecord.TagName == "tag1"), Is.True); + Assert.That(thing2.As().CurrentTags.Any(tagRecord => tagRecord.TagName == "tag2"), Is.True); + Assert.That(thing2.As().CurrentTags.Any(tagRecord => tagRecord.TagName == "tag3"), Is.True); + } + + [Test] + public void ContentItemsShouldBeReturnedFromTagService() { + var thing1 = _contentManager.New("thing"); + _contentManager.Create(thing1); + _tagService.UpdateTagsForContentItem(thing1, new string[] { "tag1", "tag2", "tag3" }); + + var thing2 = _contentManager.New("thing"); + _contentManager.Create(thing2); + _tagService.UpdateTagsForContentItem(thing2, new string[] { "tag4", "tag3" }); + + ClearSession(); + + Assert.That(_tagService.GetTaggedContentItems(25), Is.Empty); + + Assert.That(_tagService.GetTaggedContentItems(_tagService.GetTagByName("tag1").Id).Count(), Is.EqualTo(1)); + Assert.That(_tagService.GetTaggedContentItems(_tagService.GetTagByName("tag1").Id).Any(c => c.Id == thing1.Id), Is.True); + + Assert.That(_tagService.GetTaggedContentItems(_tagService.GetTagByName("tag2").Id).Count(), Is.EqualTo(1)); + Assert.That(_tagService.GetTaggedContentItems(_tagService.GetTagByName("tag2").Id).Any(c => c.Id == thing1.Id), Is.True); + + Assert.That(_tagService.GetTaggedContentItems(_tagService.GetTagByName("tag3").Id).Count(), Is.EqualTo(2)); + Assert.That(_tagService.GetTaggedContentItems(_tagService.GetTagByName("tag3").Id).Any(c => c.Id == thing1.Id), Is.True); + Assert.That(_tagService.GetTaggedContentItems(_tagService.GetTagByName("tag3").Id).Any(c => c.Id == thing2.Id), Is.True); + + Assert.That(_tagService.GetTaggedContentItems(_tagService.GetTagByName("tag4").Id).Count(), Is.EqualTo(1)); + Assert.That(_tagService.GetTaggedContentItems(_tagService.GetTagByName("tag4").Id).Any(c => c.Id == thing2.Id), Is.True); + } + + [Test] + public void TagsDeletionShouldDeleteTagsAndAssociations() { + var thing1 = _contentManager.New("thing"); + _contentManager.Create(thing1); + _tagService.UpdateTagsForContentItem(thing1, new string[] {"tag1", "tag2", "tag3"}); + + var thing2 = _contentManager.New("thing"); + _contentManager.Create(thing2); + _tagService.UpdateTagsForContentItem(thing2, new string[] {"tag2", "tag3", "tag4"}); + + ClearSession(); + + Trace.WriteLine(string.Format("Delete tag \"{0}\"", "tag1")); + _tagService.DeleteTag(_tagService.GetTagByName("tag1").Id); + ClearSession(); + + Assert.That(_tagService.GetTagByName("tag1"), Is.Null); + + var test = _contentManager.Get(thing1.Id); + Assert.That(test.As().Record.Tags.Count, Is.EqualTo(2)); + Assert.That(test.As().Record.Tags.Any(t => t.TagRecord.TagName == "tag2"), Is.True); + Assert.That(test.As().Record.Tags.Any(t => t.TagRecord.TagName == "tag3"), Is.True); + + + Trace.WriteLine(string.Format("Delete tag \"{0}\"", "tag2")); + _tagService.DeleteTag(_tagService.GetTagByName("tag2").Id); + ClearSession(); + + Assert.That(_tagService.GetTagByName("tag2"), Is.Null); + + test = _contentManager.Get(thing1.Id); + Assert.That(test.As().Record.Tags.Count, Is.EqualTo(1)); + Assert.That(test.As().Record.Tags.Any(t => t.TagRecord.TagName == "tag3"), Is.True); + + test = _contentManager.Get(thing2.Id); + Assert.That(test.As().Record.Tags.Count, Is.EqualTo(2)); + Assert.That(test.As().Record.Tags.Any(t => t.TagRecord.TagName == "tag3"), Is.True); + Assert.That(test.As().Record.Tags.Any(t => t.TagRecord.TagName == "tag4"), Is.True); + + Trace.WriteLine(string.Format("Delete tag \"{0}\"", "tag3")); + _tagService.DeleteTag(_tagService.GetTagByName("tag3").Id); + + Trace.WriteLine(string.Format("Delete tag \"{0}\"", "tag4")); + _tagService.DeleteTag(_tagService.GetTagByName("tag4").Id); + ClearSession(); + + Assert.That(_tagService.GetTags(), Is.Empty); + } + + + [Test] + public void TagsAssociationsShouldBeCreatedCorrectly() { + var thing1 = _contentManager.New("thing"); + _contentManager.Create(thing1); + _tagService.UpdateTagsForContentItem(thing1, new string[] { "tag1", "tag2", "tag3" }); + + var thing2 = _contentManager.New("thing"); + _contentManager.Create(thing2); + _tagService.UpdateTagsForContentItem(thing2, new string[] { "tag2", "tag3", "tag4" }); + + ClearSession(); + + var test = _contentManager.Get(thing1.Id); + Assert.That(test.As().Record.Tags.Count, Is.EqualTo(3)); + Assert.That(test.As().Record.Tags.Any(t => t.TagRecord.TagName == "tag1"), Is.True); + Assert.That(test.As().Record.Tags.Any(t => t.TagRecord.TagName == "tag2"), Is.True); + Assert.That(test.As().Record.Tags.Any(t => t.TagRecord.TagName == "tag3"), Is.True); + + test = _contentManager.Get(thing2.Id); + Assert.That(test.As().Record.Tags.Count, Is.EqualTo(3)); + Assert.That(test.As().Record.Tags.Any(t => t.TagRecord.TagName == "tag2"), Is.True); + Assert.That(test.As().Record.Tags.Any(t => t.TagRecord.TagName == "tag3"), Is.True); + Assert.That(test.As().Record.Tags.Any(t => t.TagRecord.TagName == "tag4"), Is.True); + + Assert.That(_tagService.GetTagByName("tag1").ContentTags.Count, Is.EqualTo(1)); + Assert.That(_tagService.GetTagByName("tag1").ContentTags.Any(t => t.TagsPartRecord.Id == thing1.Id), Is.True); + + Assert.That(_tagService.GetTagByName("tag2").ContentTags.Count, Is.EqualTo(2)); + Assert.That(_tagService.GetTagByName("tag2").ContentTags.Any(t => t.TagsPartRecord.Id == thing1.Id), Is.True); + Assert.That(_tagService.GetTagByName("tag2").ContentTags.Any(t => t.TagsPartRecord.Id == thing2.Id), Is.True); + + Assert.That(_tagService.GetTagByName("tag3").ContentTags.Count, Is.EqualTo(2)); + Assert.That(_tagService.GetTagByName("tag3").ContentTags.Any(t => t.TagsPartRecord.Id == thing1.Id), Is.True); + Assert.That(_tagService.GetTagByName("tag3").ContentTags.Any(t => t.TagsPartRecord.Id == thing2.Id), Is.True); + + Assert.That(_tagService.GetTagByName("tag4").ContentTags.Count, Is.EqualTo(1)); + Assert.That(_tagService.GetTagByName("tag4").ContentTags.Any(t => t.TagsPartRecord.Id == thing2.Id), Is.True); + } + + [Test] + public void RenamingATagShouldMergeTaggedItems() { + var thing1 = _contentManager.New("thing"); + _contentManager.Create(thing1); + _tagService.UpdateTagsForContentItem(thing1, new string[] { "tag1", "tag2", "tag3" }); + + var thing2 = _contentManager.New("thing"); + _contentManager.Create(thing2); + _tagService.UpdateTagsForContentItem(thing2, new string[] { "tag2" }); + + var thing3 = _contentManager.New("thing"); + _contentManager.Create(thing3); + _tagService.UpdateTagsForContentItem(thing3, new string[] { "tag3" }); + + // Renamed and merge "tag2" to "tag3" + var tag = _tagService.GetTagByName("tag2"); + _tagService.UpdateTag(tag.Id, "tag3"); + + ClearSession(); + + Assert.That(_tagService.GetTags().Count(), Is.EqualTo(2)); + Assert.That(_tagService.GetTags().Any(tagRecord => tagRecord.TagName == "tag1"), Is.True); + Assert.That(_tagService.GetTags().Any(tagRecord => tagRecord.TagName == "tag2"), Is.False); + Assert.That(_tagService.GetTags().Any(tagRecord => tagRecord.TagName == "tag3"), Is.True); + + Assert.That(_contentManager.Get(thing1.Id).As().CurrentTags.Any(tagRecord => tagRecord.TagName == "tag1"), Is.True); + Assert.That(_contentManager.Get(thing1.Id).As().CurrentTags.Any(tagRecord => tagRecord.TagName == "tag2"), Is.False); + Assert.That(_contentManager.Get(thing1.Id).As().CurrentTags.Any(tagRecord => tagRecord.TagName == "tag3"), Is.True); + + Assert.That(_contentManager.Get(thing2.Id).As().CurrentTags.Any(tagRecord => tagRecord.TagName == "tag3"), Is.True); + + Assert.That(_contentManager.Get(thing3.Id).As().CurrentTags.Any(tagRecord => tagRecord.TagName == "tag3"), Is.True); + } + + public class ThingHandler : ContentHandler { + public ThingHandler() { + Filters.Add(new ActivatingFilter("thing")); + Filters.Add(new ActivatingFilter("thing")); + } + } + + public class Thing : ContentPart { + } + } +} diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Tags/Controllers/AdminController.cs index c7c1272c2..5d8aa12bc 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Tags/Controllers/AdminController.cs @@ -50,7 +50,7 @@ namespace Orchard.Tags.Controllers { return new HttpUnauthorizedResult(); foreach (TagEntry entry in checkedEntries) { - _tagService.DeleteTag(entry.TagRecord.Id); + _tagService.DeleteTag(entry.Tag.Id); } break; @@ -131,7 +131,7 @@ namespace Orchard.Tags.Controllers { private static TagEntry CreateTagEntry(TagRecord tagRecord) { return new TagEntry { - TagRecord = tagRecord, + Tag = tagRecord, IsChecked = false, }; } diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Handlers/TagsPartHandler.cs b/src/Orchard.Web/Modules/Orchard.Tags/Handlers/TagsPartHandler.cs index 855b452ae..cff6ba8bf 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Handlers/TagsPartHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.Tags/Handlers/TagsPartHandler.cs @@ -9,13 +9,14 @@ using Orchard.Tags.Models; namespace Orchard.Tags.Handlers { [UsedImplicitly] public class TagsPartHandler : ContentHandler { - public TagsPartHandler(IRepository tagsRepository, IRepository tagsContentItemsRepository) { + public TagsPartHandler(IRepository repository, IRepository tagsRepository, IRepository tagsContentItemsRepository) { + Filters.Add(StorageFilter.For(repository)); OnLoading((context, tags) => { // populate list of attached tags on demand tags._currentTags.Loader(list => { - foreach(var tag in tagsContentItemsRepository.Fetch(x => x.ContentItem == context.ContentItem.Record)) - list.Add(tag.Tag); + foreach(var tag in tagsContentItemsRepository.Fetch(x => x.TagsPartRecord.Id == context.ContentItem.Id)) + list.Add(tag.TagRecord); return list; }); @@ -28,13 +29,13 @@ namespace Orchard.Tags.Handlers { // delete orphan tags (for each tag, if there is no other contentItem than the one being deleted, it's an orphan) foreach ( var tag in tagsPart.CurrentTags ) { - if ( tagsContentItemsRepository.Fetch(x => x.ContentItem != context.ContentItem.Record).Count() == 0 ) { + if ( tagsContentItemsRepository.Fetch(x => x.TagsPartRecord.Id != context.ContentItem.Id).Count() == 0 ) { tagsRepository.Delete(tag); } } // delete tag links with this contentItem (tagsContentItems) - foreach ( var tagsContentItem in tagsContentItemsRepository.Fetch(x => x.ContentItem == context.ContentItem.Record) ) { + foreach ( var tagsContentItem in tagsContentItemsRepository.Fetch(x => x.TagsPartRecord.Id == context.ContentItem.Id) ) { tagsContentItemsRepository.Delete(tagsContentItem); } diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Models/ContentTagRecord.cs b/src/Orchard.Web/Modules/Orchard.Tags/Models/ContentTagRecord.cs new file mode 100644 index 000000000..5a7d1652e --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Tags/Models/ContentTagRecord.cs @@ -0,0 +1,7 @@ +namespace Orchard.Tags.Models { + public class ContentTagRecord { + public virtual int Id { get; set; } + public virtual TagRecord TagRecord { get; set; } + public virtual TagsPartRecord TagsPartRecord { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Models/TagRecord.cs b/src/Orchard.Web/Modules/Orchard.Tags/Models/TagRecord.cs index 953217b2e..08f8699fc 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Models/TagRecord.cs +++ b/src/Orchard.Web/Modules/Orchard.Tags/Models/TagRecord.cs @@ -1,6 +1,9 @@ -namespace Orchard.Tags.Models { +using System.Collections.Generic; + +namespace Orchard.Tags.Models { public class TagRecord { public virtual int Id { get; set; } public virtual string TagName { get; set; } + public virtual IList ContentTags { get; set; } } } diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Models/TagsContentItems.cs b/src/Orchard.Web/Modules/Orchard.Tags/Models/TagsContentItems.cs deleted file mode 100644 index 079156744..000000000 --- a/src/Orchard.Web/Modules/Orchard.Tags/Models/TagsContentItems.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Orchard.ContentManagement.Records; - -namespace Orchard.Tags.Models { - public class TagsContentItems { - public virtual int Id { get; set; } - public virtual TagRecord Tag { get; set; } - public virtual ContentItemRecord ContentItem { get; set; } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Models/TagsPartRecord.cs b/src/Orchard.Web/Modules/Orchard.Tags/Models/TagsPartRecord.cs index ba36eb2de..4687757be 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Models/TagsPartRecord.cs +++ b/src/Orchard.Web/Modules/Orchard.Tags/Models/TagsPartRecord.cs @@ -1,6 +1,11 @@ -using Orchard.ContentManagement.Records; +using System.Collections.Generic; +using Orchard.ContentManagement.Records; namespace Orchard.Tags.Models { public class TagsPartRecord : ContentPartRecord { + public TagsPartRecord() { + Tags = new List(); + } + public virtual IList Tags { get; set; } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Orchard.Tags.csproj b/src/Orchard.Web/Modules/Orchard.Tags/Orchard.Tags.csproj index 58783065e..37464d641 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Orchard.Tags.csproj +++ b/src/Orchard.Web/Modules/Orchard.Tags/Orchard.Tags.csproj @@ -54,7 +54,7 @@ - + diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Services/ITagService.cs b/src/Orchard.Web/Modules/Orchard.Tags/Services/ITagService.cs index 47512c66a..25b2e8502 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Services/ITagService.cs +++ b/src/Orchard.Web/Modules/Orchard.Tags/Services/ITagService.cs @@ -9,7 +9,7 @@ namespace Orchard.Tags.Services { TagRecord GetTagByName(string tagName); IEnumerable GetTaggedContentItems(int tagId); - void CreateTag(string tagName); + TagRecord CreateTag(string tagName); void DeleteTag(int tagId); diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Services/TagService.cs b/src/Orchard.Web/Modules/Orchard.Tags/Services/TagService.cs index 13768b5b5..f1595fb61 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Services/TagService.cs +++ b/src/Orchard.Web/Modules/Orchard.Tags/Services/TagService.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; -using Orchard.ContentManagement.Records; using Orchard.Data; using Orchard.Localization; using Orchard.Logging; @@ -15,18 +14,18 @@ namespace Orchard.Tags.Services { [UsedImplicitly] public class TagService : ITagService { private readonly IRepository _tagRepository; - private readonly IRepository _tagsContentItemsRepository; + private readonly IRepository _contentTagRepository; private readonly INotifier _notifier; private readonly IAuthorizationService _authorizationService; private readonly IOrchardServices _orchardServices; public TagService(IRepository tagRepository, - IRepository tagsContentItemsRepository, + IRepository contentTagRepository, INotifier notifier, IAuthorizationService authorizationService, IOrchardServices orchardServices) { _tagRepository = tagRepository; - _tagsContentItemsRepository = tagsContentItemsRepository; + _contentTagRepository = contentTagRepository; _notifier = notifier; _authorizationService = authorizationService; _orchardServices = orchardServices; @@ -49,27 +48,36 @@ namespace Orchard.Tags.Services { return _tagRepository.Get(x => x.TagName == tagName); } - public void CreateTag(string tagName) { - if (_tagRepository.Get(x => x.TagName == tagName) == null) { + public TagRecord CreateTag(string tagName) { + var result = _tagRepository.Get(x => x.TagName == tagName); + if (result == null) { _authorizationService.CheckAccess(Permissions.CreateTag, _orchardServices.WorkContext.CurrentUser, null); + result = new TagRecord { TagName = tagName }; + _tagRepository.Create(result); + } - TagRecord tagRecord = new TagRecord { TagName = tagName }; - _tagRepository.Create(tagRecord); - } - else { - _notifier.Warning(T("The tag {0} already exists", tagName)); - } + return result; } public void DeleteTag(int tagId) { - _tagRepository.Delete(GetTag(tagId)); - IEnumerable tagsContentItems = _tagsContentItemsRepository.Fetch(x => x.Tag.Id == tagId); - foreach (var tagContentItem in tagsContentItems) { - _tagsContentItemsRepository.Delete(tagContentItem); + _authorizationService.CheckAccess(Permissions.ManageTags, _orchardServices.WorkContext.CurrentUser, null); + + var tag = GetTag(tagId); + if (tag == null) + return; + + // Delete associations to content items + foreach (var tagContentItem in _contentTagRepository.Fetch(x => x.TagRecord == tag)) { + _contentTagRepository.Delete(tagContentItem); } + + // Delete tag entity + _tagRepository.Delete(tag); } public void UpdateTag(int tagId, string tagName) { + _authorizationService.CheckAccess(Permissions.ManageTags, _orchardServices.WorkContext.CurrentUser, null); + if (String.IsNullOrEmpty(tagName)) { _notifier.Warning(T("Couldn't rename tag: name was empty")); return; @@ -79,16 +87,16 @@ namespace Orchard.Tags.Services { // new tag name already existing => merge if (tagRecord != null) { - var tagsContentItems = _tagsContentItemsRepository.Fetch(x => x.Tag.Id == tagId); + var tagsContentItems = _contentTagRepository.Fetch(x => x.TagRecord.Id == tagId); // get contentItems already tagged with the existing one var taggedContentItems = GetTaggedContentItems(tagRecord.Id); foreach (var tagContentItem in tagsContentItems) { - if (!taggedContentItems.Any(c => c.ContentItem.Record == tagContentItem.ContentItem)) { - TagContentItem(tagContentItem.ContentItem, tagName); + if (!taggedContentItems.Any(c => c.ContentItem.Id == tagContentItem.TagsPartRecord.Id)) { + TagContentItem(tagContentItem.TagsPartRecord, tagName); } - _tagsContentItemsRepository.Delete(tagContentItem); + _contentTagRepository.Delete(tagContentItem); } _tagRepository.Delete(GetTag(tagId)); @@ -101,50 +109,41 @@ namespace Orchard.Tags.Services { } public IEnumerable GetTaggedContentItems(int tagId) { - return _tagsContentItemsRepository - .Fetch(x => x.Tag.Id == tagId) - .Select(t => _orchardServices.ContentManager.Get(t.ContentItem.Id)) + return _contentTagRepository + .Fetch(x => x.TagRecord.Id == tagId) + .Select(t => _orchardServices.ContentManager.Get(t.TagsPartRecord.Id)) .Where(c => c != null); } - private void TagContentItem(ContentItemRecord contentItem, string tagName) { + private void TagContentItem(TagsPartRecord tagsPartRecord, string tagName) { var tagRecord = GetTagByName(tagName); - var tagsContentItems = new TagsContentItems { ContentItem = contentItem, Tag = tagRecord }; - _tagsContentItemsRepository.Create(tagsContentItems); + var tagsContentItems = new ContentTagRecord { TagsPartRecord = tagsPartRecord, TagRecord = tagRecord }; + _contentTagRepository.Create(tagsContentItems); } public void UpdateTagsForContentItem(ContentItem contentItem, IEnumerable tagNamesForContentItem) { - var tags = new List(); - foreach (var tagName in tagNamesForContentItem) { - TagRecord tagRecord = GetTagByName(tagName); - if (tagRecord == null) { - CreateTag(tagName); - tagRecord = GetTagByName(tagName); - } - tags.Add(tagRecord); - } - ModifyTagsForContentItem(contentItem, tags); - } + if (contentItem.Id == 0) + throw new OrchardException(T("Error adding tag to content item: the content item has not been created yet.")); - private void ModifyTagsForContentItem(ContentItem contentItem, IEnumerable tagsForContentItem) { - var newTagsForContentItem = new List(tagsForContentItem); - var currentTagsForContentItem = _tagsContentItemsRepository.Fetch(x => x.ContentItem == contentItem.Record); + var tags = tagNamesForContentItem.Select(name => CreateTag(name)); + var newTagsForContentItem = new List(tags); + var currentTagsForContentItem = _contentTagRepository.Fetch(x => x.TagsPartRecord.Id == contentItem.Id); foreach (var tagContentItem in currentTagsForContentItem) { - if (!newTagsForContentItem.Contains(tagContentItem.Tag)) { + if (!newTagsForContentItem.Contains(tagContentItem.TagRecord)) { _authorizationService.CheckAccess(Permissions.ApplyTag, _orchardServices.WorkContext.CurrentUser, null); - _tagsContentItemsRepository.Delete(tagContentItem); + _contentTagRepository.Delete(tagContentItem); } else { - newTagsForContentItem.Remove(tagContentItem.Tag); + newTagsForContentItem.Remove(tagContentItem.TagRecord); } } foreach (var newTagForContentItem in newTagsForContentItem) { _authorizationService.CheckAccess(Permissions.ApplyTag, _orchardServices.WorkContext.CurrentUser, null); - _tagsContentItemsRepository.Create(new TagsContentItems { ContentItem = contentItem.Record, Tag = newTagForContentItem }); + _contentTagRepository.Create(new ContentTagRecord { TagsPartRecord = contentItem.As().Record, TagRecord = newTagForContentItem }); } } } diff --git a/src/Orchard.Web/Modules/Orchard.Tags/ViewModels/TagsAdminIndexViewModel.cs b/src/Orchard.Web/Modules/Orchard.Tags/ViewModels/TagsAdminIndexViewModel.cs index 39b836846..493bce8db 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/ViewModels/TagsAdminIndexViewModel.cs +++ b/src/Orchard.Web/Modules/Orchard.Tags/ViewModels/TagsAdminIndexViewModel.cs @@ -8,7 +8,7 @@ namespace Orchard.Tags.ViewModels { } public class TagEntry { - public TagRecord TagRecord { get; set; } + public TagRecord Tag { get; set; } public bool IsChecked { get; set; } }