diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITagRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITagRepository.cs index 993f350ce1..dae5c293e5 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITagRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITagRepository.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using Umbraco.Core.Models; @@ -25,6 +26,14 @@ namespace Umbraco.Core.Persistence.Repositories /// IEnumerable GetTagsForEntity(int contentId, string group = null); + /// + /// Returns all tags that exist on the content item - Content/Media/Member + /// + /// The content item id to get tags for + /// Optional group + /// + IEnumerable GetTagsForEntity(Guid contentId, string group = null); + /// /// Returns all tags that exist on the content item for the property specified - Content/Media/Member /// @@ -34,6 +43,15 @@ namespace Umbraco.Core.Persistence.Repositories /// IEnumerable GetTagsForProperty(int contentId, string propertyTypeAlias, string group = null); + /// + /// 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 + /// Optional group + /// + IEnumerable GetTagsForProperty(Guid contentId, string propertyTypeAlias, string group = null); + /// /// Assigns the given tags to a content item's property /// diff --git a/src/Umbraco.Core/Persistence/Repositories/TagRepository.cs b/src/Umbraco.Core/Persistence/Repositories/TagRepository.cs index 14e32d6f9c..a35e7bf06d 100644 --- a/src/Umbraco.Core/Persistence/Repositories/TagRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/TagRepository.cs @@ -96,7 +96,7 @@ namespace Umbraco.Core.Persistence.Repositories var sql = new Sql(); if (isCount) { - sql.Select("COUNT(*)").From(); + sql.Select("COUNT(*)").From(SqlSyntax); } else { @@ -105,10 +105,10 @@ namespace Umbraco.Core.Persistence.Repositories return sql; } - private static Sql GetBaseQuery() + private Sql GetBaseQuery() { var sql = new Sql(); - sql.Select("*").From(); + sql.Select("*").From(SqlSyntax); return sql; } @@ -166,15 +166,15 @@ namespace Umbraco.Core.Persistence.Repositories { var sql = new Sql() .Select("cmsTagRelationship.nodeId, cmsPropertyType.Alias, cmsPropertyType.id as propertyTypeId, cmsTags.tag, cmsTags.id as tagId, cmsTags." + SqlSyntax.GetQuotedColumnName("group")) - .From() - .InnerJoin() - .On(left => left.TagId, right => right.Id) - .InnerJoin() - .On(left => left.NodeId, right => right.NodeId) - .InnerJoin() - .On(left => left.Id, right => right.PropertyTypeId) - .InnerJoin() - .On(left => left.NodeId, right => right.NodeId) + .From(SqlSyntax) + .InnerJoin(SqlSyntax) + .On(SqlSyntax, left => left.TagId, right => right.Id) + .InnerJoin(SqlSyntax) + .On(SqlSyntax, left => left.NodeId, right => right.NodeId) + .InnerJoin(SqlSyntax) + .On(SqlSyntax, left => left.Id, right => right.PropertyTypeId) + .InnerJoin(SqlSyntax) + .On(SqlSyntax, left => left.NodeId, right => right.NodeId) .Where(dto => dto.Group == tagGroup); if (objectType != TaggableObjectTypes.All) @@ -192,15 +192,15 @@ namespace Umbraco.Core.Persistence.Repositories { var sql = new Sql() .Select("cmsTagRelationship.nodeId, cmsPropertyType.Alias, cmsPropertyType.id as propertyTypeId, cmsTags.tag, cmsTags.id as tagId, cmsTags." + SqlSyntax.GetQuotedColumnName("group")) - .From() - .InnerJoin() - .On(left => left.TagId, right => right.Id) - .InnerJoin() - .On(left => left.NodeId, right => right.NodeId) - .InnerJoin() - .On(left => left.Id, right => right.PropertyTypeId) - .InnerJoin() - .On(left => left.NodeId, right => right.NodeId) + .From(SqlSyntax) + .InnerJoin(SqlSyntax) + .On(SqlSyntax, left => left.TagId, right => right.Id) + .InnerJoin(SqlSyntax) + .On(SqlSyntax, left => left.NodeId, right => right.NodeId) + .InnerJoin(SqlSyntax) + .On(SqlSyntax, left => left.Id, right => right.PropertyTypeId) + .InnerJoin(SqlSyntax) + .On(SqlSyntax, left => left.NodeId, right => right.NodeId) .Where(dto => dto.Tag == tag); if (objectType != TaggableObjectTypes.All) @@ -240,13 +240,7 @@ namespace Umbraco.Core.Persistence.Repositories var sql = GetTagsQuerySelect(true); sql = ApplyRelationshipJoinToTagsQuery(sql); - - sql = sql - .InnerJoin() - .On(left => left.NodeId, right => right.NodeId) - .InnerJoin() - .On(left => left.NodeId, right => right.NodeId); - + if (objectType != TaggableObjectTypes.All) { var nodeObjectType = GetNodeObjectType(objectType); @@ -268,7 +262,21 @@ namespace Umbraco.Core.Persistence.Repositories sql = ApplyRelationshipJoinToTagsQuery(sql); sql = sql - .Where(dto => dto.NodeId == contentId); + .Where(dto => dto.NodeId == contentId); + + sql = ApplyGroupFilterToTagsQuery(sql, group); + + return ExecuteTagsQuery(sql); + } + + public IEnumerable GetTagsForEntity(Guid contentId, string group = null) + { + var sql = GetTagsQuerySelect(); + + sql = ApplyRelationshipJoinToTagsQuery(sql); + + sql = sql + .Where(dto => dto.UniqueId == contentId); sql = ApplyGroupFilterToTagsQuery(sql, group); @@ -282,9 +290,26 @@ namespace Umbraco.Core.Persistence.Repositories sql = ApplyRelationshipJoinToTagsQuery(sql); sql = sql - .InnerJoin() - .On(left => left.Id, right => right.PropertyTypeId) - .Where(dto => dto.NodeId == contentId) + .InnerJoin(SqlSyntax) + .On(SqlSyntax, left => left.Id, right => right.PropertyTypeId) + .Where(dto => dto.NodeId == contentId) + .Where(dto => dto.Alias == propertyTypeAlias); + + sql = ApplyGroupFilterToTagsQuery(sql, group); + + return ExecuteTagsQuery(sql); + } + + public IEnumerable GetTagsForProperty(Guid contentId, string propertyTypeAlias, string group = null) + { + var sql = GetTagsQuerySelect(); + + sql = ApplyRelationshipJoinToTagsQuery(sql); + + sql = sql + .InnerJoin(SqlSyntax) + .On(SqlSyntax, left => left.Id, right => right.PropertyTypeId) + .Where(dto => dto.UniqueId == contentId) .Where(dto => dto.Alias == propertyTypeAlias); sql = ApplyGroupFilterToTagsQuery(sql, group); @@ -298,7 +323,7 @@ namespace Umbraco.Core.Persistence.Repositories if (withGrouping) { - sql = sql.Select("cmsTags.Id, cmsTags.Tag, cmsTags." + SqlSyntax.GetQuotedColumnName("Group") + @", Count(*) NodeCount"); + sql = sql.Select("cmsTags.id, cmsTags.tag, cmsTags." + SqlSyntax.GetQuotedColumnName("group") + @", Count(*) NodeCount"); } else { @@ -311,14 +336,18 @@ namespace Umbraco.Core.Persistence.Repositories private Sql ApplyRelationshipJoinToTagsQuery(Sql sql) { return sql - .From() - .InnerJoin() - .On(left => left.TagId, right => right.Id); + .From(SqlSyntax) + .InnerJoin(SqlSyntax) + .On(SqlSyntax, left => left.TagId, right => right.Id) + .InnerJoin(SqlSyntax) + .On(SqlSyntax, left => left.NodeId, right => right.NodeId) + .InnerJoin(SqlSyntax) + .On(SqlSyntax, left => left.NodeId, right => right.NodeId); } private Sql ApplyGroupFilterToTagsQuery(Sql sql, string group) { - if (!group.IsNullOrWhiteSpace()) + if (@group.IsNullOrWhiteSpace() == false) { sql = sql.Where(dto => dto.Group == group); } @@ -328,7 +357,7 @@ namespace Umbraco.Core.Persistence.Repositories private Sql ApplyGroupByToTagsQuery(Sql sql) { - return sql.GroupBy(new string[] { "cmsTags.Id", "cmsTags.Tag", "cmsTags." + SqlSyntax.GetQuotedColumnName("Group") + @"" }); + return sql.GroupBy(new string[] { "cmsTags.id", "cmsTags.tag", "cmsTags." + SqlSyntax.GetQuotedColumnName("group") + @"" }); } private IEnumerable ExecuteTagsQuery(Sql sql) @@ -385,16 +414,16 @@ namespace Umbraco.Core.Persistence.Repositories //adds any tags found in the collection that aren't in cmsTag var insertTagsSql = string.Concat("insert into cmsTags (Tag,", - SqlSyntax.GetQuotedColumnName("Group"), + SqlSyntax.GetQuotedColumnName("group"), ") ", " select TagSet.Tag, TagSet.", - SqlSyntax.GetQuotedColumnName("Group"), + SqlSyntax.GetQuotedColumnName("group"), " from ", tagSetSql, " left outer join cmsTags on (TagSet.Tag = cmsTags.Tag and TagSet.", - SqlSyntax.GetQuotedColumnName("Group"), + SqlSyntax.GetQuotedColumnName("group"), " = cmsTags.", - SqlSyntax.GetQuotedColumnName("Group"), + SqlSyntax.GetQuotedColumnName("group"), ")", " where cmsTags.Id is null "); //insert the tags that don't exist @@ -413,9 +442,9 @@ namespace Umbraco.Core.Persistence.Repositories "select NewTags.Id from ", tagSetSql, " inner join cmsTags as NewTags on (TagSet.Tag = NewTags.Tag and TagSet.", - SqlSyntax.GetQuotedColumnName("Group"), + SqlSyntax.GetQuotedColumnName("group"), " = TagSet.", - SqlSyntax.GetQuotedColumnName("Group"), + SqlSyntax.GetQuotedColumnName("group"), ") ", ") as NewTagsSet ", "left outer join cmsTagRelationship ", @@ -451,7 +480,7 @@ namespace Umbraco.Core.Persistence.Repositories " AND tagId IN ", "(SELECT id FROM cmsTags INNER JOIN ", tagSetSql, - " ON (TagSet.Tag = cmsTags.Tag and TagSet." + SqlSyntax.GetQuotedColumnName("Group") + @" = cmsTags." + SqlSyntax.GetQuotedColumnName("Group") + @"))"); + " ON (TagSet.Tag = cmsTags.Tag and TagSet." + SqlSyntax.GetQuotedColumnName("group") + @" = cmsTags." + SqlSyntax.GetQuotedColumnName("group") + @"))"); Database.Execute(deleteSql); } @@ -503,7 +532,7 @@ namespace Umbraco.Core.Persistence.Repositories var array = tagsToInsert .Select(tag => - string.Format("select '{0}' as Tag, '{1}' as " + SqlSyntax.GetQuotedColumnName("Group") + @"", + string.Format("select '{0}' as Tag, '{1}' as " + SqlSyntax.GetQuotedColumnName("group") + @"", PetaPocoExtensions.EscapeAtSymbols(tag.Text.Replace("'", "''")), tag.Group)) .ToArray(); return "(" + string.Join(" union ", array).Replace(" ", " ") + ") as TagSet"; diff --git a/src/Umbraco.Core/Services/ITagService.cs b/src/Umbraco.Core/Services/ITagService.cs index 02ac6f79ff..10fea6d3eb 100644 --- a/src/Umbraco.Core/Services/ITagService.cs +++ b/src/Umbraco.Core/Services/ITagService.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using Umbraco.Core.Models; @@ -119,5 +120,26 @@ namespace Umbraco.Core.Services /// Optional name of the 'Tag Group' /// An enumerable list of IEnumerable GetTagsForEntity(int contentId, string tagGroup = null); + + /// + /// Gets all tags attached to a property by entity id + /// + /// Use the optional tagGroup parameter to limit the + /// result to a specific 'Tag Group'. + /// The content item id to get tags for + /// Property type alias + /// Optional name of the 'Tag Group' + /// An enumerable list of + IEnumerable GetTagsForProperty(Guid contentId, string propertyTypeAlias, string tagGroup = null); + + /// + /// Gets all tags attached to an entity (content, media or member) by entity id + /// + /// Use the optional tagGroup parameter to limit the + /// result to a specific 'Tag Group'. + /// The content item id to get tags for + /// Optional name of the 'Tag Group' + /// An enumerable list of + IEnumerable GetTagsForEntity(Guid contentId, string tagGroup = null); } } \ No newline at end of file diff --git a/src/Umbraco.Core/Services/TagService.cs b/src/Umbraco.Core/Services/TagService.cs index 6054d29323..86b9126cf7 100644 --- a/src/Umbraco.Core/Services/TagService.cs +++ b/src/Umbraco.Core/Services/TagService.cs @@ -222,5 +222,38 @@ namespace Umbraco.Core.Services return repository.GetTagsForEntity(contentId, tagGroup); } } + + /// + /// Gets all tags attached to a property by entity id + /// + /// Use the optional tagGroup parameter to limit the + /// result to a specific 'Tag Group'. + /// The content item id to get tags for + /// Property type alias + /// Optional name of the 'Tag Group' + /// An enumerable list of + public IEnumerable GetTagsForProperty(Guid contentId, string propertyTypeAlias, string tagGroup = null) + { + using (var repository = RepositoryFactory.CreateTagRepository(UowProvider.GetUnitOfWork())) + { + return repository.GetTagsForProperty(contentId, propertyTypeAlias, tagGroup); + } + } + + /// + /// Gets all tags attached to an entity (content, media or member) by entity id + /// + /// Use the optional tagGroup parameter to limit the + /// result to a specific 'Tag Group'. + /// The content item id to get tags for + /// Optional name of the 'Tag Group' + /// An enumerable list of + public IEnumerable GetTagsForEntity(Guid contentId, string tagGroup = null) + { + using (var repository = RepositoryFactory.CreateTagRepository(UowProvider.GetUnitOfWork())) + { + return repository.GetTagsForEntity(contentId, tagGroup); + } + } } } \ No newline at end of file diff --git a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs index d8232d9aaf..d79a45c2e9 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs @@ -340,7 +340,7 @@ namespace Umbraco.Tests.Persistence.Repositories } [Test] - public void Can_Get_Tags_For_Content() + public void Can_Get_Tags_For_Content_By_Id() { var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); @@ -381,6 +381,54 @@ namespace Umbraco.Tests.Persistence.Repositories var result = repository.GetTagsForEntity(content2.Id); Assert.AreEqual(2, result.Count()); + + } + } + } + + [Test] + public void Can_Get_Tags_For_Content_By_Key() + { + var provider = new PetaPocoUnitOfWorkProvider(Logger); + 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().Id, + 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().Id, + new[] + { + new Tag {Text = "tag1", Group = "test"}, + new Tag {Text = "tag2", Group = "test"} + }, false); + + //get by key + var result = repository.GetTagsForEntity(content2.Key); + Assert.AreEqual(2, result.Count()); } } } @@ -511,7 +559,7 @@ namespace Umbraco.Tests.Persistence.Repositories } [Test] - public void Can_Get_Tags_For_Property() + public void Can_Get_Tags_For_Property_By_Id() { var provider = new PetaPocoUnitOfWorkProvider(Logger); var unitOfWork = provider.GetUnitOfWork(); @@ -557,6 +605,53 @@ namespace Umbraco.Tests.Persistence.Repositories } + [Test] + public void Can_Get_Tags_For_Property_By_Key() + { + var provider = new PetaPocoUnitOfWorkProvider(Logger); + 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().Id, + 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().Id, + new[] + { + new Tag {Text = "tag1", Group = "test"}, + new Tag {Text = "tag2", Group = "test"} + }, false); + + var result1 = repository.GetTagsForProperty(content1.Key, contentType.PropertyTypes.First().Alias).ToArray(); + var result2 = repository.GetTagsForProperty(content1.Key, contentType.PropertyTypes.Last().Alias).ToArray(); + Assert.AreEqual(4, result1.Count()); + Assert.AreEqual(2, result2.Count()); + } + } + + } + [Test] public void Can_Get_Tags_For_Property_For_Group() {