From 3cb70f67c9bef83165da988d70261bb143b4493f Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 4 Oct 2013 16:11:51 +1000 Subject: [PATCH] TagsRepository is all working with unit tests, now to make the service and integrate the extension methods. --- src/Umbraco.Core/Models/ITag.cs | 1 + .../Interfaces/ITagsRepository.cs | 48 ++ .../Repositories/TagsRepository.cs | 228 ++++++++- .../Persistence/RepositoryFactory.cs | 6 + src/Umbraco.Core/Umbraco.Core.csproj | 1 + .../Repositories/TagRepositoryTest.cs | 462 ++++++++++++++++++ src/Umbraco.Tests/Umbraco.Tests.csproj | 1 + 7 files changed, 744 insertions(+), 3 deletions(-) create mode 100644 src/Umbraco.Core/Persistence/Repositories/Interfaces/ITagsRepository.cs create mode 100644 src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs diff --git a/src/Umbraco.Core/Models/ITag.cs b/src/Umbraco.Core/Models/ITag.cs index a9dfaaf820..05990aa6a0 100644 --- a/src/Umbraco.Core/Models/ITag.cs +++ b/src/Umbraco.Core/Models/ITag.cs @@ -10,6 +10,7 @@ namespace Umbraco.Core.Models [DataMember] string Group { get; set; } + //TODO: enable this at some stage //int ParentId { get; set; } } diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITagsRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITagsRepository.cs new file mode 100644 index 0000000000..e060b8c285 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITagsRepository.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using Umbraco.Core.Models; + +namespace Umbraco.Core.Persistence.Repositories +{ + public interface ITagsRepository : IRepository + { + + /// + /// Returns all tags that exist on the content item - Content/Media/Member + /// + /// The content item id to get tags for + /// + IEnumerable GetTagsForContent(int contentId); + + /// + /// Returns all tags that exist on the content item for the property specified - Content/Media/Member + /// + /// The content item id to get tags for + /// The property alias to get tags for + /// + IEnumerable GetTagsForProperty(int contentId, string propertyAlias); + + /// + /// Assigns the given tags to a content item's property + /// + /// + /// + /// The tags to assign + /// + /// If set to true, this will replace all tags with the given tags, + /// if false this will append the tags that already exist for the content item + /// + /// + /// + /// This can also be used to remove all tags from a property by specifying replaceTags = true and an empty tag list. + /// + void AssignTagsToProperty(int contentId, string propertyAlias, IEnumerable tags, bool replaceTags); + + /// + /// Removes any of the given tags from the property association + /// + /// + /// + /// The tags to remove from the property + void RemoveTagsFromProperty(int contentId, string propertyAlias, IEnumerable tags); + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/TagsRepository.cs b/src/Umbraco.Core/Persistence/Repositories/TagsRepository.cs index b29becd854..8c68d6cdb5 100644 --- a/src/Umbraco.Core/Persistence/Repositories/TagsRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/TagsRepository.cs @@ -1,17 +1,19 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Caching; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories { - internal class TagsRepository : PetaPocoRepositoryBase + internal class TagsRepository : PetaPocoRepositoryBase, ITagsRepository { protected TagsRepository(IDatabaseUnitOfWork work) : this(work, RuntimeCacheProvider.Current) @@ -20,7 +22,7 @@ namespace Umbraco.Core.Persistence.Repositories internal TagsRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) : base(work, cache) - { + { } protected override ITag PerformGet(int id) @@ -152,8 +154,228 @@ namespace Umbraco.Core.Persistence.Repositories var dto = factory.BuildDto(entity); Database.Update(dto); - + ((ICanBeDirty)entity).ResetDirtyProperties(); } + + //TODO: Consider caching implications. + + public IEnumerable GetTagsForContent(int contentId) + { + var sql = new Sql() + .Select("DISTINCT cmsTags.*") + .From() + .InnerJoin() + .On("cmsTagRelationship.tagId = cmsTags.id") + .Where(dto => dto.NodeId == contentId); + + var factory = new TagFactory(); + + return Database.Fetch(sql).Select(factory.BuildEntity); + } + + public IEnumerable GetTagsForProperty(int contentId, string propertyAlias) + { + var sql = new Sql() + .Select("DISTINCT cmsTags.*") + .From() + .InnerJoin() + .On(left => left.TagId, right => right.Id) + .InnerJoin() + .On(left => left.Id, right => right.PropertyTypeId) + .Where(dto => dto.NodeId == contentId) + .Where(dto => dto.Alias == propertyAlias); + + var factory = new TagFactory(); + + return Database.Fetch(sql).Select(factory.BuildEntity); + } + + /// + /// Assigns the given tags to a content item's property + /// + /// + /// + /// The tags to assign + /// + /// If set to true, this will replace all tags with the given tags, + /// if false this will append the tags that already exist for the content item + /// + /// + /// + /// This can also be used to remove all tags from a property by specifying replaceTags = true and an empty tag list. + /// + public void AssignTagsToProperty(int contentId, string propertyAlias, IEnumerable tags, bool replaceTags) + { + //First we need to ensure there are no duplicates + var asArray = tags.Distinct(new TagComparer()).ToArray(); + + //we don't have to do anything if there are no tags assigning and we're not replacing them + if (asArray.Length == 0 && replaceTags == false) + { + return; + } + + var propertyTypeId = EnsureContentProperty(contentId, propertyAlias); + + //next check if we're removing all of the tags + if (asArray.Length == 0 && replaceTags) + { + Database.Execute("DELETE FROM cmsTagRelationship WHERE nodeId=" + contentId + " AND propertyTypeId=" + propertyTypeId); + return; + } + + //ok so now we're actually assigning tags... + //NOTE: There's some very clever logic in the umbraco.cms.businesslogic.Tags.Tag to insert tags where they don't exist, + // and assign where they don't exist which we've borrowed here. The queries are pretty zany but work, otherwise we'll end up + // with quite a few additional queries. + + //do all this in one transaction + using (var trans = Database.GetTransaction()) + { + //var factory = new TagFactory(); + + var tagSetSql = GetTagSet(asArray); + + //adds any tags found in the collection that aren't in cmsTag + var insertTagsSql = string.Concat("insert into cmsTags (Tag,", + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Group"), + ") ", + " select TagSet.Tag, TagSet.", + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Group"), + " from ", + tagSetSql, + " left outer join cmsTags on (TagSet.Tag = cmsTags.Tag and TagSet.", + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Group"), + " = cmsTags.", + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Group"), + ")", + " where cmsTags.Id is null "); + //insert the tags that don't exist + Database.Execute(insertTagsSql); + + if (replaceTags) + { + //if we are replacing the tags then remove them first + Database.Execute("DELETE FROM cmsTagRelationship WHERE nodeId=" + contentId + " AND propertyTypeId=" + propertyTypeId); + } + + //adds any tags found in csv that aren't in tagrelationships + var insertTagRelationsSql = string.Concat("insert into cmsTagRelationship (tagId,nodeId,propertyTypeId) ", + "select NewTagsSet.Id, " + contentId + ", " + propertyTypeId + " from ", + "( ", + "select NewTags.Id from ", + tagSetSql, + " inner join cmsTags as NewTags on (TagSet.Tag = NewTags.Tag and TagSet.", + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Group"), + " = TagSet.", + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Group"), + ") ", + ") as NewTagsSet ", + "left outer join cmsTagRelationship ", + "on (cmsTagRelationship.TagId = NewTagsSet.Id and cmsTagRelationship.nodeId = ", + contentId, + "and cmsTagRelationship.propertyTypeId = ", + propertyTypeId, + ") ", + "where cmsTagRelationship.tagId is null "); + + //insert the tags relations that don't exist + Database.Execute(insertTagRelationsSql); + + //GO! + trans.Complete(); + } + } + + /// + /// Removes any of the given tags from the property association + /// + /// + /// + /// The tags to remove from the property + public void RemoveTagsFromProperty(int contentId, string propertyAlias, IEnumerable tags) + { + var propertyTypeId = EnsureContentProperty(contentId, propertyAlias); + + var tagSetSql = GetTagSet(tags); + + var deleteSql = string.Concat("DELETE FROM cmsTagRelationship WHERE nodeId = ", + contentId, + " AND propertyTypeId = ", + propertyTypeId, + " AND tagId IN ", + "(SELECT id FROM cmsTags INNER JOIN ", + tagSetSql, + " ON (TagSet.Tag = cmsTags.Tag and TagSet.[Group] = cmsTags.[Group]))"); + + Database.Execute(deleteSql); + } + + /// + /// This is a clever way to produce an SQL statement like this: + /// + /// (select 'Spacesdd' as Tag, 'default' as [Group] + /// union + /// select 'Cool' as Tag, 'default' as [Group] + /// ) as TagSet + /// + /// This allows us to use the tags to be inserted as a temporary in memory table. + /// + /// + /// + private static string GetTagSet(IEnumerable tagsToInsert) + { + var array = tagsToInsert.Select(tag => string.Format("select '{0}' as Tag, '{1}' as [Group]", tag.Text, tag.Group)).ToArray(); + return "(" + string.Join(" union ", array).Replace(" ", " ") + ") as TagSet"; + } + + private class TagComparer : IEqualityComparer + { + public bool Equals(ITag x, ITag y) + { + return x.Text == y.Text && x.Group == y.Group; + } + + public int GetHashCode(ITag obj) + { + unchecked + { + return (obj.Text.GetHashCode() * 397) ^ obj.Group.GetHashCode(); + } + } + } + + /// + /// Ensures the content and property alias exist, then returns the property type id for the alias + /// + /// + /// + /// + private int EnsureContentProperty(int contentId, string propertyAlias) + { + //ensure that there's content and a property to assign - NOTE: we cannot use the content repository here + // because the content repository requires one of us TagsRepository instance, then we'll have circular dependencies + // instead we'll just look it up ourselves. + + var sql = new Sql() + .Select("cmsPropertyType.id") + .From() + .InnerJoin() + .On(left => left.NodeId, right => right.ContentTypeId) + .InnerJoin() + .On(left => left.ContentTypeId, right => right.NodeId) + .Where(dto => dto.NodeId == contentId) + .Where(dto => dto.Alias == propertyAlias); + + var result = Database.Fetch(sql).ToArray(); + + if (result.Length == 0) + { + throw new InvalidOperationException("Cannot modify tags for content id " + contentId + " and property " + propertyAlias + " because the content item does not exist with this property"); + } + + return result.First(); + } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/RepositoryFactory.cs b/src/Umbraco.Core/Persistence/RepositoryFactory.cs index dc36fd1483..2b305f748d 100644 --- a/src/Umbraco.Core/Persistence/RepositoryFactory.cs +++ b/src/Umbraco.Core/Persistence/RepositoryFactory.cs @@ -33,6 +33,12 @@ namespace Umbraco.Core.Persistence } + public virtual ITagsRepository CreateTagsRepository(IDatabaseUnitOfWork uow) + { + return new TagsRepository( + uow, + _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current); + } public virtual IContentRepository CreateContentRepository(IDatabaseUnitOfWork uow) { diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index afdfc1ba91..8d441ce082 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -444,6 +444,7 @@ + diff --git a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs new file mode 100644 index 0000000000..f1bee43246 --- /dev/null +++ b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs @@ -0,0 +1,462 @@ +using System; +using System.Linq; +using NUnit.Framework; +using Umbraco.Core.Models; +using Umbraco.Core.Models.Rdbms; +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.Caching; +using Umbraco.Core.Persistence.Repositories; +using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Tests.TestHelpers; +using Umbraco.Tests.TestHelpers.Entities; + +namespace Umbraco.Tests.Persistence.Repositories +{ + [TestFixture] + public class TagRepositoryTest : BaseDatabaseFactoryTest + { + [SetUp] + public override void Initialize() + { + base.Initialize(); + } + + [TearDown] + public override void TearDown() + { + base.TearDown(); + } + + private TagsRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) + { + var tagRepository = new TagsRepository(unitOfWork, NullCacheProvider.Current); + return tagRepository; + } + + [Test] + public void Can_Instantiate_Repository_From_Resolver() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + + // Act + var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); + + // Assert + Assert.That(repository, Is.Not.Null); + } + + [Test] + public void Can_Perform_Add_On_Repository() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + var tag = new Tag() + { + Group = "Test", + Text = "Test" + }; + + // Act + repository.AddOrUpdate(tag); + unitOfWork.Commit(); + + // Assert + Assert.That(tag.HasIdentity, Is.True); + } + } + + [Test] + public void Can_Perform_Multiple_Adds_On_Repository() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + var tag = new Tag() + { + Group = "Test", + Text = "Test" + }; + + // Act + repository.AddOrUpdate(tag); + unitOfWork.Commit(); + + var tag2 = new Tag() + { + Group = "Test", + Text = "Test2" + }; + repository.AddOrUpdate(tag2); + unitOfWork.Commit(); + + // Assert + Assert.That(tag.HasIdentity, Is.True); + Assert.That(tag2.HasIdentity, Is.True); + Assert.AreNotEqual(tag.Id, tag2.Id); + } + + } + + [Test] + public void Cannot_Assign_Tags_To_Non_Existing_Property() + { + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + Assert.Throws(() => repository.AssignTagsToProperty(1234, "hello", Enumerable.Empty(), true)); + } + + } + + [Test] + public void Can_Create_Tag_Relations() + { + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + ContentTypeRepository contentTypeRepository; + using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) + { + //create data to relate to + var contentType = MockedContentTypes.CreateSimpleContentType("test", "Test"); + contentTypeRepository.AddOrUpdate(contentType); + unitOfWork.Commit(); + var content = MockedContent.CreateSimpleContent(contentType); + contentRepository.AddOrUpdate(content); + unitOfWork.Commit(); + + using (var repository = CreateRepository(unitOfWork)) + { + repository.AssignTagsToProperty( + content.Id, + contentType.PropertyTypes.First().Alias, + new[] + { + new Tag {Text = "tag1", Group = "test"}, + new Tag {Text = "tag2", Group = "test"}, + }, false); + + Assert.AreEqual(2, repository.GetTagsForContent(content.Id).Count()); + } + } + } + + [Test] + public void Can_Append_Tag_Relations() + { + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + ContentTypeRepository contentTypeRepository; + using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) + { + //create data to relate to + var contentType = MockedContentTypes.CreateSimpleContentType("test", "Test"); + contentTypeRepository.AddOrUpdate(contentType); + unitOfWork.Commit(); + var content = MockedContent.CreateSimpleContent(contentType); + contentRepository.AddOrUpdate(content); + unitOfWork.Commit(); + + using (var repository = CreateRepository(unitOfWork)) + { + repository.AssignTagsToProperty( + content.Id, + contentType.PropertyTypes.First().Alias, + new[] + { + new Tag {Text = "tag1", Group = "test"}, + new Tag {Text = "tag2", Group = "test"}, + }, false); + + repository.AssignTagsToProperty( + content.Id, + contentType.PropertyTypes.First().Alias, + new[] + { + new Tag {Text = "tag3", Group = "test"}, + new Tag {Text = "tag4", Group = "test"}, + }, false); + + Assert.AreEqual(4, repository.GetTagsForContent(content.Id).Count()); + } + } + } + + [Test] + public void Can_Replace_Tag_Relations() + { + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + ContentTypeRepository contentTypeRepository; + using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) + { + //create data to relate to + var contentType = MockedContentTypes.CreateSimpleContentType("test", "Test"); + contentTypeRepository.AddOrUpdate(contentType); + unitOfWork.Commit(); + var content = MockedContent.CreateSimpleContent(contentType); + contentRepository.AddOrUpdate(content); + unitOfWork.Commit(); + + using (var repository = CreateRepository(unitOfWork)) + { + repository.AssignTagsToProperty( + content.Id, + contentType.PropertyTypes.First().Alias, + new[] + { + new Tag {Text = "tag1", Group = "test"}, + new Tag {Text = "tag2", Group = "test"}, + }, false); + + repository.AssignTagsToProperty( + content.Id, + contentType.PropertyTypes.First().Alias, + new[] + { + new Tag {Text = "tag3", Group = "test"}, + new Tag {Text = "tag4", Group = "test"}, + }, true); + + var result = repository.GetTagsForContent(content.Id); + Assert.AreEqual(2, result.Count()); + Assert.AreEqual("tag3", result.ElementAt(0).Text); + Assert.AreEqual("tag4", result.ElementAt(1).Text); + } + } + } + + [Test] + public void Can_Merge_Tag_Relations() + { + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + ContentTypeRepository contentTypeRepository; + using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) + { + //create data to relate to + var contentType = MockedContentTypes.CreateSimpleContentType("test", "Test"); + contentTypeRepository.AddOrUpdate(contentType); + unitOfWork.Commit(); + var content = MockedContent.CreateSimpleContent(contentType); + contentRepository.AddOrUpdate(content); + unitOfWork.Commit(); + + using (var repository = CreateRepository(unitOfWork)) + { + repository.AssignTagsToProperty( + content.Id, + contentType.PropertyTypes.First().Alias, + new[] + { + new Tag {Text = "tag1", Group = "test"}, + new Tag {Text = "tag2", Group = "test"}, + }, false); + + repository.AssignTagsToProperty( + content.Id, + contentType.PropertyTypes.First().Alias, + new[] + { + new Tag {Text = "tag2", Group = "test"}, + new Tag {Text = "tag3", Group = "test"}, + }, false); + + var result = repository.GetTagsForContent(content.Id); + Assert.AreEqual(3, result.Count()); + } + } + } + + [Test] + public void Can_Clear_Tag_Relations() + { + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + ContentTypeRepository contentTypeRepository; + using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) + { + //create data to relate to + var contentType = MockedContentTypes.CreateSimpleContentType("test", "Test"); + contentTypeRepository.AddOrUpdate(contentType); + unitOfWork.Commit(); + var content = MockedContent.CreateSimpleContent(contentType); + contentRepository.AddOrUpdate(content); + unitOfWork.Commit(); + + using (var repository = CreateRepository(unitOfWork)) + { + repository.AssignTagsToProperty( + content.Id, + contentType.PropertyTypes.First().Alias, + new[] + { + new Tag {Text = "tag1", Group = "test"}, + new Tag {Text = "tag2", Group = "test"}, + }, false); + + repository.AssignTagsToProperty( + content.Id, + contentType.PropertyTypes.First().Alias, + Enumerable.Empty(), true); + + var result = repository.GetTagsForContent(content.Id); + Assert.AreEqual(0, result.Count()); + } + } + } + + [Test] + public void Can_Remove_Specific_Tags_From_Property() + { + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + ContentTypeRepository contentTypeRepository; + using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) + { + //create data to relate to + var contentType = MockedContentTypes.CreateSimpleContentType("test", "Test"); + contentTypeRepository.AddOrUpdate(contentType); + unitOfWork.Commit(); + var content = MockedContent.CreateSimpleContent(contentType); + contentRepository.AddOrUpdate(content); + unitOfWork.Commit(); + + using (var repository = CreateRepository(unitOfWork)) + { + repository.AssignTagsToProperty( + content.Id, + contentType.PropertyTypes.First().Alias, + new[] + { + new Tag {Text = "tag1", Group = "test"}, + new Tag {Text = "tag2", Group = "test"}, + new Tag {Text = "tag3", Group = "test"}, + new Tag {Text = "tag4", Group = "test"} + }, false); + + repository.RemoveTagsFromProperty( + content.Id, + contentType.PropertyTypes.First().Alias, + new[] + { + new Tag {Text = "tag2", Group = "test"}, + new Tag {Text = "tag3", Group = "test"} + }); + + var result = repository.GetTagsForContent(content.Id); + Assert.AreEqual(2, result.Count()); + Assert.AreEqual("tag1", result.ElementAt(0).Text); + Assert.AreEqual("tag4", result.ElementAt(1).Text); + } + } + } + + [Test] + public void Can_Get_Tags_For_Content() + { + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + ContentTypeRepository contentTypeRepository; + using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) + { + //create data to relate to + var contentType = MockedContentTypes.CreateSimpleContentType("test", "Test"); + contentTypeRepository.AddOrUpdate(contentType); + unitOfWork.Commit(); + var content1 = MockedContent.CreateSimpleContent(contentType); + contentRepository.AddOrUpdate(content1); + var content2 = MockedContent.CreateSimpleContent(contentType); + contentRepository.AddOrUpdate(content2); + unitOfWork.Commit(); + + using (var repository = CreateRepository(unitOfWork)) + { + repository.AssignTagsToProperty( + content1.Id, + contentType.PropertyTypes.First().Alias, + new[] + { + new Tag {Text = "tag1", Group = "test"}, + new Tag {Text = "tag2", Group = "test"}, + new Tag {Text = "tag3", Group = "test"}, + new Tag {Text = "tag4", Group = "test"} + }, false); + + repository.AssignTagsToProperty( + content2.Id, + contentType.PropertyTypes.First().Alias, + new[] + { + new Tag {Text = "tag1", Group = "test"}, + new Tag {Text = "tag2", Group = "test"} + }, false); + + var result = repository.GetTagsForContent(content2.Id); + Assert.AreEqual(2, result.Count()); + } + } + } + + [Test] + public void Can_Get_Tags_For_Property() + { + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + ContentTypeRepository contentTypeRepository; + using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepository)) + { + //create data to relate to + var contentType = MockedContentTypes.CreateSimpleContentType("test", "Test"); + contentTypeRepository.AddOrUpdate(contentType); + unitOfWork.Commit(); + var content1 = MockedContent.CreateSimpleContent(contentType); + contentRepository.AddOrUpdate(content1); + unitOfWork.Commit(); + + using (var repository = CreateRepository(unitOfWork)) + { + repository.AssignTagsToProperty( + content1.Id, + contentType.PropertyTypes.First().Alias, + new[] + { + new Tag {Text = "tag1", Group = "test"}, + new Tag {Text = "tag2", Group = "test"}, + new Tag {Text = "tag3", Group = "test"}, + new Tag {Text = "tag4", Group = "test"} + }, false); + + repository.AssignTagsToProperty( + content1.Id, + contentType.PropertyTypes.Last().Alias, + new[] + { + new Tag {Text = "tag1", Group = "test"}, + new Tag {Text = "tag2", Group = "test"} + }, false); + + var result1 = repository.GetTagsForProperty(content1.Id, contentType.PropertyTypes.First().Alias).ToArray(); + var result2 = repository.GetTagsForProperty(content1.Id, contentType.PropertyTypes.Last().Alias).ToArray(); + Assert.AreEqual(2, result2.Count()); + } + } + + } + + private ContentRepository CreateContentRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) + { + var templateRepository = new TemplateRepository(unitOfWork, NullCacheProvider.Current); + contentTypeRepository = new ContentTypeRepository(unitOfWork, NullCacheProvider.Current, templateRepository); + var repository = new ContentRepository(unitOfWork, NullCacheProvider.Current, contentTypeRepository, templateRepository); + return repository; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 5fa259be3b..a2df401ad3 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -255,6 +255,7 @@ +