diff --git a/src/Umbraco.Core/Models/UmbracoObjectTypes.cs b/src/Umbraco.Core/Models/UmbracoObjectTypes.cs index c9967c0688..37ad181682 100644 --- a/src/Umbraco.Core/Models/UmbracoObjectTypes.cs +++ b/src/Umbraco.Core/Models/UmbracoObjectTypes.cs @@ -43,7 +43,7 @@ namespace Umbraco.Core.Models /// /// Member Type /// - [UmbracoObjectTypeAttribute(Constants.ObjectTypes.MemberType)] + [UmbracoObjectTypeAttribute(Constants.ObjectTypes.MemberType, typeof(IMemberType))] [FriendlyName("Member Type")] MemberType, @@ -100,7 +100,7 @@ namespace Umbraco.Core.Models /// /// Member /// - [UmbracoObjectTypeAttribute(Constants.ObjectTypes.Member)] + [UmbracoObjectTypeAttribute(Constants.ObjectTypes.Member, typeof(IMember))] [FriendlyName("Member")] Member, diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs index 8a66937173..c07691172d 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs @@ -28,12 +28,12 @@ namespace Umbraco.Core.Persistence.Repositories { private readonly IContentTypeRepository _contentTypeRepository; private readonly ITemplateRepository _templateRepository; - private readonly ITagsRepository _tagRepository; + private readonly ITagRepository _tagRepository; private readonly CacheHelper _cacheHelper; private readonly ContentPreviewRepository _contentPreviewRepository; private readonly ContentXmlRepository _contentXmlRepository; - public ContentRepository(IDatabaseUnitOfWork work, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagsRepository tagRepository, CacheHelper cacheHelper) + public ContentRepository(IDatabaseUnitOfWork work, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagRepository tagRepository, CacheHelper cacheHelper) : base(work) { if (contentTypeRepository == null) throw new ArgumentNullException("contentTypeRepository"); @@ -49,7 +49,7 @@ namespace Umbraco.Core.Persistence.Repositories EnsureUniqueNaming = true; } - public ContentRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagsRepository tagRepository, CacheHelper cacheHelper) + public ContentRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagRepository tagRepository, CacheHelper cacheHelper) : base(work, cache) { if (contentTypeRepository == null) throw new ArgumentNullException("contentTypeRepository"); diff --git a/src/Umbraco.Core/Persistence/Repositories/EntityRepository.cs b/src/Umbraco.Core/Persistence/Repositories/EntityRepository.cs index d0b81f1b8e..a73b7fc3d7 100644 --- a/src/Umbraco.Core/Persistence/Repositories/EntityRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/EntityRepository.cs @@ -139,43 +139,64 @@ namespace Umbraco.Core.Persistence.Repositories public virtual IEnumerable GetAll(Guid objectTypeId, params int[] ids) { + //TODO: Fix the n+1 query! + if (ids.Any()) { - foreach (var id in ids) + return ids.Select(id => Get(id, objectTypeId)); + } + else + { + return PerformGetAll(objectTypeId); + } + } + + public virtual IEnumerable GetAll(Guid objectTypeId, params Guid[] keys) + { + //TODO: Fix the n+1 query! + + if (keys.Any()) + { + return keys.Select(key => GetByKey(key, objectTypeId)); + } + else + { + return PerformGetAll(objectTypeId); + } + } + + private IEnumerable PerformGetAll(Guid objectTypeId) + { + //TODO: Fix the n+1 query! + + bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document); + bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media); + var sql = GetFullSqlForEntityType(isContent, isMedia, objectTypeId, string.Empty); + + var factory = new UmbracoEntityFactory(); + + if (isMedia) + { + //for now treat media differently + //TODO: We should really use this methodology for Content/Members too!! since it includes properties and ALL of the dynamic db fields + var entities = _work.Database.Fetch( + new UmbracoEntityRelator().Map, sql); + foreach (var entity in entities) { - yield return Get(id, objectTypeId); + yield return entity; } } else { - bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document); - bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media); - var sql = GetFullSqlForEntityType(isContent, isMedia, objectTypeId, string.Empty); - - var factory = new UmbracoEntityFactory(); - - if (isMedia) + var dtos = _work.Database.Fetch(sql); + foreach (var entity in dtos.Select(dto => factory.BuildEntityFromDynamic(dto))) { - //for now treat media differently - //TODO: We should really use this methodology for Content/Members too!! since it includes properties and ALL of the dynamic db fields - var entities = _work.Database.Fetch( - new UmbracoEntityRelator().Map, sql); - foreach (var entity in entities) - { - yield return entity; - } - } - else - { - var dtos = _work.Database.Fetch(sql); - foreach (var entity in dtos.Select(dto => factory.BuildEntityFromDynamic(dto))) - { - yield return entity; - } + yield return entity; } } } + public virtual IEnumerable GetByQuery(IQuery query) { var wheres = string.Concat(" AND ", string.Join(" AND ", ((Query) query).WhereClauses())); diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IEntityRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IEntityRepository.cs index 510ef18421..3b73aabdf4 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IEntityRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IEntityRepository.cs @@ -12,6 +12,7 @@ namespace Umbraco.Core.Persistence.Repositories IUmbracoEntity Get(int id); IUmbracoEntity Get(int id, Guid objectTypeId); IEnumerable GetAll(Guid objectTypeId, params int[] ids); + IEnumerable GetAll(Guid objectTypeId, params Guid[] keys); IEnumerable GetByQuery(IQuery query); IEnumerable GetByQuery(IQuery query, Guid objectTypeId); } diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITagsRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITagRepository.cs similarity index 95% rename from src/Umbraco.Core/Persistence/Repositories/Interfaces/ITagsRepository.cs rename to src/Umbraco.Core/Persistence/Repositories/Interfaces/ITagRepository.cs index ae89c469fc..993f350ce1 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITagsRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITagRepository.cs @@ -1,74 +1,74 @@ -using System.Collections.Generic; -using Umbraco.Core.Models; - -namespace Umbraco.Core.Persistence.Repositories -{ - public interface ITagsRepository : IRepositoryQueryable - { - IEnumerable GetTaggedEntitiesByTagGroup(TaggableObjectTypes objectType, string tagGroup); - - IEnumerable GetTaggedEntitiesByTag(TaggableObjectTypes objectType, string tag, string tagGroup = null); - - /// - /// Returns all tags for an entity type (content/media/member) - /// - /// Entity type - /// Optional group - /// - IEnumerable GetTagsForEntityType(TaggableObjectTypes objectType, 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(int contentId, 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(int contentId, string propertyTypeAlias, string group = null); - - /// - /// 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, int propertyTypeId, 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, int propertyTypeId, IEnumerable tags); - - /// - /// Removes all tag associations from the property - /// - /// - /// - void ClearTagsFromProperty(int contentId, int propertyTypeId); - - /// - /// Removes all tag associations from the entity - /// - /// - void ClearTagsFromEntity(int contentId); - } +using System.Collections.Generic; +using Umbraco.Core.Models; + +namespace Umbraco.Core.Persistence.Repositories +{ + public interface ITagRepository : IRepositoryQueryable + { + IEnumerable GetTaggedEntitiesByTagGroup(TaggableObjectTypes objectType, string tagGroup); + + IEnumerable GetTaggedEntitiesByTag(TaggableObjectTypes objectType, string tag, string tagGroup = null); + + /// + /// Returns all tags for an entity type (content/media/member) + /// + /// Entity type + /// Optional group + /// + IEnumerable GetTagsForEntityType(TaggableObjectTypes objectType, 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(int contentId, 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(int contentId, string propertyTypeAlias, string group = null); + + /// + /// 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, int propertyTypeId, 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, int propertyTypeId, IEnumerable tags); + + /// + /// Removes all tag associations from the property + /// + /// + /// + void ClearTagsFromProperty(int contentId, int propertyTypeId); + + /// + /// Removes all tag associations from the entity + /// + /// + void ClearTagsFromEntity(int contentId); + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs index 49ff002f1a..166bb8e75a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs @@ -23,11 +23,11 @@ namespace Umbraco.Core.Persistence.Repositories internal class MediaRepository : VersionableRepositoryBase, IMediaRepository { private readonly IMediaTypeRepository _mediaTypeRepository; - private readonly ITagsRepository _tagRepository; + private readonly ITagRepository _tagRepository; private readonly ContentXmlRepository _contentXmlRepository; private readonly ContentPreviewRepository _contentPreviewRepository; - public MediaRepository(IDatabaseUnitOfWork work, IMediaTypeRepository mediaTypeRepository, ITagsRepository tagRepository) + public MediaRepository(IDatabaseUnitOfWork work, IMediaTypeRepository mediaTypeRepository, ITagRepository tagRepository) : base(work) { if (mediaTypeRepository == null) throw new ArgumentNullException("mediaTypeRepository"); @@ -39,7 +39,7 @@ namespace Umbraco.Core.Persistence.Repositories EnsureUniqueNaming = true; } - public MediaRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IMediaTypeRepository mediaTypeRepository, ITagsRepository tagRepository) + public MediaRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IMediaTypeRepository mediaTypeRepository, ITagRepository tagRepository) : base(work, cache) { if (mediaTypeRepository == null) throw new ArgumentNullException("mediaTypeRepository"); diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs index f84cb9c1b6..88684f9165 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs @@ -24,12 +24,12 @@ namespace Umbraco.Core.Persistence.Repositories internal class MemberRepository : VersionableRepositoryBase, IMemberRepository { private readonly IMemberTypeRepository _memberTypeRepository; - private readonly ITagsRepository _tagRepository; + private readonly ITagRepository _tagRepository; private readonly IMemberGroupRepository _memberGroupRepository; private readonly ContentXmlRepository _contentXmlRepository; private readonly ContentPreviewRepository _contentPreviewRepository; - public MemberRepository(IDatabaseUnitOfWork work, IMemberTypeRepository memberTypeRepository, IMemberGroupRepository memberGroupRepository, ITagsRepository tagRepository) + public MemberRepository(IDatabaseUnitOfWork work, IMemberTypeRepository memberTypeRepository, IMemberGroupRepository memberGroupRepository, ITagRepository tagRepository) : base(work) { if (memberTypeRepository == null) throw new ArgumentNullException("memberTypeRepository"); @@ -41,7 +41,7 @@ namespace Umbraco.Core.Persistence.Repositories _contentPreviewRepository = new ContentPreviewRepository(work, NullCacheProvider.Current); } - public MemberRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IMemberTypeRepository memberTypeRepository, IMemberGroupRepository memberGroupRepository, ITagsRepository tagRepository) + public MemberRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IMemberTypeRepository memberTypeRepository, IMemberGroupRepository memberGroupRepository, ITagRepository tagRepository) : base(work, cache) { if (memberTypeRepository == null) throw new ArgumentNullException("memberTypeRepository"); diff --git a/src/Umbraco.Core/Persistence/Repositories/TagsRepository.cs b/src/Umbraco.Core/Persistence/Repositories/TagRepository.cs similarity index 94% rename from src/Umbraco.Core/Persistence/Repositories/TagsRepository.cs rename to src/Umbraco.Core/Persistence/Repositories/TagRepository.cs index 1d687d1974..2fa7335987 100644 --- a/src/Umbraco.Core/Persistence/Repositories/TagsRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/TagRepository.cs @@ -1,512 +1,515 @@ -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, ITagsRepository - { - protected TagsRepository(IDatabaseUnitOfWork work) - : this(work, RuntimeCacheProvider.Current) - { - } - - internal TagsRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) - : base(work, cache) - { - } - - protected override ITag PerformGet(int id) - { - var sql = GetBaseQuery(false); - sql.Where(GetBaseWhereClause(), new { Id = id }); - - var tagDto = Database.Fetch(sql).FirstOrDefault(); - if (tagDto == null) - return null; - - var factory = new TagFactory(); - var entity = factory.BuildEntity(tagDto); - - //on initial construction we don't want to have dirty properties tracked - // http://issues.umbraco.org/issue/U4-1946 - ((TracksChangesEntityBase)entity).ResetDirtyProperties(false); - - return entity; - } - - protected override IEnumerable PerformGetAll(params int[] ids) - { - if (ids.Any()) - { - return PerformGetAllOnIds(ids); - } - - var sql = GetBaseQuery(false); - - return ConvertFromDtos(Database.Fetch(sql)) - .ToArray();// we don't want to re-iterate again! - } - - private IEnumerable PerformGetAllOnIds(params int[] ids) - { - if (ids.Any() == false) yield break; - foreach (var id in ids) - { - yield return Get(id); - } - } - - private IEnumerable ConvertFromDtos(IEnumerable dtos) - { - var factory = new TagFactory(); - foreach (var entity in dtos.Select(factory.BuildEntity)) - { - //on initial construction we don't want to have dirty properties tracked - // http://issues.umbraco.org/issue/U4-1946 - ((TracksChangesEntityBase)entity).ResetDirtyProperties(false); - yield return entity; - } - } - - protected override IEnumerable PerformGetByQuery(IQuery query) - { - var sqlClause = GetBaseQuery(false); - var translator = new SqlTranslator(sqlClause, query); - var sql = translator.Translate(); - - var dtos = Database.Fetch(sql); - - foreach (var dto in dtos) - { - yield return Get(dto.Id); - } - } - - protected override Sql GetBaseQuery(bool isCount) - { - var sql = new Sql(); - if (isCount) - { - sql.Select("COUNT(*)").From(); - } - else - { - return GetBaseQuery(); - } - return sql; - } - - private static Sql GetBaseQuery() - { - var sql = new Sql(); - sql.Select("*").From(); - return sql; - } - - protected override string GetBaseWhereClause() - { - return "id = @Id"; - } - - protected override IEnumerable GetDeleteClauses() - { - var list = new List - { - "DELETE FROM cmsTagRelationship WHERE tagId = @Id", - "DELETE FROM cmsTags WHERE id = @Id" - }; - return list; - } - - protected override Guid NodeObjectTypeId - { - get { throw new NotImplementedException(); } - } - - protected override void PersistNewItem(ITag entity) - { - ((Entity)entity).AddingEntity(); - - var factory = new TagFactory(); - var dto = factory.BuildDto(entity); - - var id = Convert.ToInt32(Database.Insert(dto)); - entity.Id = id; - - ((ICanBeDirty)entity).ResetDirtyProperties(); - } - - protected override void PersistUpdatedItem(ITag entity) - { - ((Entity)entity).UpdatingEntity(); - - var factory = new TagFactory(); - var dto = factory.BuildDto(entity); - - Database.Update(dto); - - ((ICanBeDirty)entity).ResetDirtyProperties(); - } - - //TODO: Consider caching implications. - - - public IEnumerable GetTaggedEntitiesByTagGroup(TaggableObjectTypes objectType, string tagGroup) - { - var nodeObjectType = GetNodeObjectType(objectType); - - var sql = new Sql() - .Select("cmsTagRelationship.nodeId, cmsPropertyType.Alias, cmsPropertyType.id as propertyTypeId, cmsTags.tag, cmsTags.id as tagId, cmsTags." + SqlSyntaxContext.SqlSyntaxProvider.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) - .Where(dto => dto.NodeObjectType == nodeObjectType) - .Where(dto => dto.Group == tagGroup); - - return CreateTaggedEntityCollection( - ApplicationContext.Current.DatabaseContext.Database.Fetch(sql)); - } - - public IEnumerable GetTaggedEntitiesByTag(TaggableObjectTypes objectType, string tag, string tagGroup = null) - { - var nodeObjectType = GetNodeObjectType(objectType); - - var sql = new Sql() - .Select("cmsTagRelationship.nodeId, cmsPropertyType.Alias, cmsPropertyType.id as propertyTypeId, cmsTags.tag, cmsTags.id as tagId, cmsTags." + SqlSyntaxContext.SqlSyntaxProvider.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) - .Where(dto => dto.NodeObjectType == nodeObjectType) - .Where(dto => dto.Tag == tag); - - if (tagGroup.IsNullOrWhiteSpace() == false) - { - sql = sql.Where(dto => dto.Group == tagGroup); - } - - return CreateTaggedEntityCollection( - ApplicationContext.Current.DatabaseContext.Database.Fetch(sql)); - } - - private IEnumerable CreateTaggedEntityCollection(IEnumerable dbResult) - { - var list = new List(); - foreach (var node in dbResult.GroupBy(x => (int)x.nodeId)) - { - var properties = new List(); - foreach (var propertyType in node.GroupBy(x => new { id = (int)x.propertyTypeId, alias = (string)x.Alias })) - { - var tags = propertyType.Select(x => new Tag((int)x.tagId, (string)x.tag, (string)x.group)); - properties.Add(new TaggedProperty(propertyType.Key.id, propertyType.Key.alias, tags)); - } - list.Add(new TaggedEntity(node.Key, properties)); - } - return list; - } - - public IEnumerable GetTagsForEntityType(TaggableObjectTypes objectType, string group = null) - { - var nodeObjectType = GetNodeObjectType(objectType); - - 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) - .Where(dto => dto.NodeObjectType == nodeObjectType); - - sql = ApplyGroupFilterToTagsQuery(sql, group); - - sql = ApplyGroupByToTagsQuery(sql); - - return ExecuteTagsQuery(sql); - } - - public IEnumerable GetTagsForEntity(int contentId, string group = null) - { - var sql = GetTagsQuerySelect(); - - sql = ApplyRelationshipJoinToTagsQuery(sql); - - sql = sql - .Where(dto => dto.NodeId == contentId); - - sql = ApplyGroupFilterToTagsQuery(sql, group); - - return ExecuteTagsQuery(sql); - } - - public IEnumerable GetTagsForProperty(int contentId, string propertyTypeAlias, string group = null) - { - var sql = GetTagsQuerySelect(); - - sql = ApplyRelationshipJoinToTagsQuery(sql); - - sql = sql - .InnerJoin() - .On(left => left.Id, right => right.PropertyTypeId) - .Where(dto => dto.NodeId == contentId) - .Where(dto => dto.Alias == propertyTypeAlias); - - sql = ApplyGroupFilterToTagsQuery(sql, group); - - return ExecuteTagsQuery(sql); - } - - private Sql GetTagsQuerySelect(bool withGrouping = false) - { - var sql = new Sql(); - - if (withGrouping) - { - sql = sql.Select("cmsTags.Id, cmsTags.Tag, cmsTags.[Group], Count(*) NodeCount"); - } - else - { - sql = sql.Select("DISTINCT cmsTags.*"); - } - - return sql; - } - - private Sql ApplyRelationshipJoinToTagsQuery(Sql sql) - { - return sql - .From() - .InnerJoin() - .On(left => left.TagId, right => right.Id); - } - - private Sql ApplyGroupFilterToTagsQuery(Sql sql, string group) - { - if (!group.IsNullOrWhiteSpace()) - { - sql = sql.Where(dto => dto.Group == group); - } - - return sql; - } - - private Sql ApplyGroupByToTagsQuery(Sql sql) - { - return sql.GroupBy(new string[] { "cmsTags.Id", "cmsTags.Tag", "cmsTags.[Group]" }); - } - - private IEnumerable ExecuteTagsQuery(Sql sql) - { - 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 propertyTypeAlias, IEnumerable tags, bool replaceTags) - public void AssignTagsToProperty(int contentId, int propertyTypeId, 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; - } - - //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, int propertyTypeId, IEnumerable tags) - { - 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); - } - - public void ClearTagsFromProperty(int contentId, int propertyTypeId) - { - Database.Execute("DELETE FROM cmsTagRelationship WHERE nodeId = @nodeId AND propertyTypeId = @propertyTypeId", - new { nodeId = contentId, propertyTypeId = propertyTypeId }); - } - - public void ClearTagsFromEntity(int contentId) - { - Database.Execute("DELETE FROM cmsTagRelationship WHERE nodeId = @nodeId", - new { nodeId = contentId }); - } - - private Guid GetNodeObjectType(TaggableObjectTypes type) - { - switch (type) - { - case TaggableObjectTypes.Content: - return new Guid(Constants.ObjectTypes.Document); - case TaggableObjectTypes.Media: - return new Guid(Constants.ObjectTypes.Media); - case TaggableObjectTypes.Member: - return new Guid(Constants.ObjectTypes.Member); - default: - throw new ArgumentOutOfRangeException("type"); - } - } - - /// - /// 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]", - PetaPocoExtensions.EscapeAtSymbols(tag.Text.Replace("'", "''")), 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(); - } - } - } - - } +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 TagRepository : PetaPocoRepositoryBase, ITagRepository + { + protected TagRepository(IDatabaseUnitOfWork work) + : this(work, RuntimeCacheProvider.Current) + { + } + + internal TagRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) + : base(work, cache) + { + } + + protected override ITag PerformGet(int id) + { + var sql = GetBaseQuery(false); + sql.Where(GetBaseWhereClause(), new { Id = id }); + + var tagDto = Database.Fetch(sql).FirstOrDefault(); + if (tagDto == null) + return null; + + var factory = new TagFactory(); + var entity = factory.BuildEntity(tagDto); + + //on initial construction we don't want to have dirty properties tracked + // http://issues.umbraco.org/issue/U4-1946 + ((TracksChangesEntityBase)entity).ResetDirtyProperties(false); + + return entity; + } + + protected override IEnumerable PerformGetAll(params int[] ids) + { + var sql = GetBaseQuery(false); + + if (ids.Any()) + { + sql.Where("id in (@ids)", new {ids = ids}); + + //return PerformGetAllOnIds(ids); + } + + return ConvertFromDtos(Database.Fetch(sql)) + .ToArray();// we don't want to re-iterate again! + } + + //private IEnumerable PerformGetAllOnIds(params int[] ids) + //{ + // //TODO: Fix the n+1 query! This one is particularly bad!!!!!!!! + + // if (ids.Any() == false) yield break; + // foreach (var id in ids) + // { + // yield return Get(id); + // } + //} + + private IEnumerable ConvertFromDtos(IEnumerable dtos) + { + var factory = new TagFactory(); + foreach (var entity in dtos.Select(factory.BuildEntity)) + { + //on initial construction we don't want to have dirty properties tracked + // http://issues.umbraco.org/issue/U4-1946 + ((TracksChangesEntityBase)entity).ResetDirtyProperties(false); + yield return entity; + } + } + + protected override IEnumerable PerformGetByQuery(IQuery query) + { + var sqlClause = GetBaseQuery(false); + var translator = new SqlTranslator(sqlClause, query); + var sql = translator.Translate(); + + var dtos = Database.Fetch(sql); + + return ConvertFromDtos(dtos) + .ToArray();// we don't want to re-iterate again! + + } + + protected override Sql GetBaseQuery(bool isCount) + { + var sql = new Sql(); + if (isCount) + { + sql.Select("COUNT(*)").From(); + } + else + { + return GetBaseQuery(); + } + return sql; + } + + private static Sql GetBaseQuery() + { + var sql = new Sql(); + sql.Select("*").From(); + return sql; + } + + protected override string GetBaseWhereClause() + { + return "id = @Id"; + } + + protected override IEnumerable GetDeleteClauses() + { + var list = new List + { + "DELETE FROM cmsTagRelationship WHERE tagId = @Id", + "DELETE FROM cmsTags WHERE id = @Id" + }; + return list; + } + + protected override Guid NodeObjectTypeId + { + get { throw new NotImplementedException(); } + } + + protected override void PersistNewItem(ITag entity) + { + ((Entity)entity).AddingEntity(); + + var factory = new TagFactory(); + var dto = factory.BuildDto(entity); + + var id = Convert.ToInt32(Database.Insert(dto)); + entity.Id = id; + + ((ICanBeDirty)entity).ResetDirtyProperties(); + } + + protected override void PersistUpdatedItem(ITag entity) + { + ((Entity)entity).UpdatingEntity(); + + var factory = new TagFactory(); + var dto = factory.BuildDto(entity); + + Database.Update(dto); + + ((ICanBeDirty)entity).ResetDirtyProperties(); + } + + //TODO: Consider caching implications. + + + public IEnumerable GetTaggedEntitiesByTagGroup(TaggableObjectTypes objectType, string tagGroup) + { + var nodeObjectType = GetNodeObjectType(objectType); + + var sql = new Sql() + .Select("cmsTagRelationship.nodeId, cmsPropertyType.Alias, cmsPropertyType.id as propertyTypeId, cmsTags.tag, cmsTags.id as tagId, cmsTags." + SqlSyntaxContext.SqlSyntaxProvider.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) + .Where(dto => dto.NodeObjectType == nodeObjectType) + .Where(dto => dto.Group == tagGroup); + + return CreateTaggedEntityCollection( + ApplicationContext.Current.DatabaseContext.Database.Fetch(sql)); + } + + public IEnumerable GetTaggedEntitiesByTag(TaggableObjectTypes objectType, string tag, string tagGroup = null) + { + var nodeObjectType = GetNodeObjectType(objectType); + + var sql = new Sql() + .Select("cmsTagRelationship.nodeId, cmsPropertyType.Alias, cmsPropertyType.id as propertyTypeId, cmsTags.tag, cmsTags.id as tagId, cmsTags." + SqlSyntaxContext.SqlSyntaxProvider.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) + .Where(dto => dto.NodeObjectType == nodeObjectType) + .Where(dto => dto.Tag == tag); + + if (tagGroup.IsNullOrWhiteSpace() == false) + { + sql = sql.Where(dto => dto.Group == tagGroup); + } + + return CreateTaggedEntityCollection( + ApplicationContext.Current.DatabaseContext.Database.Fetch(sql)); + } + + private IEnumerable CreateTaggedEntityCollection(IEnumerable dbResult) + { + var list = new List(); + foreach (var node in dbResult.GroupBy(x => (int)x.nodeId)) + { + var properties = new List(); + foreach (var propertyType in node.GroupBy(x => new { id = (int)x.propertyTypeId, alias = (string)x.Alias })) + { + var tags = propertyType.Select(x => new Tag((int)x.tagId, (string)x.tag, (string)x.group)); + properties.Add(new TaggedProperty(propertyType.Key.id, propertyType.Key.alias, tags)); + } + list.Add(new TaggedEntity(node.Key, properties)); + } + return list; + } + + public IEnumerable GetTagsForEntityType(TaggableObjectTypes objectType, string group = null) + { + var nodeObjectType = GetNodeObjectType(objectType); + + 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) + .Where(dto => dto.NodeObjectType == nodeObjectType); + + sql = ApplyGroupFilterToTagsQuery(sql, group); + + sql = ApplyGroupByToTagsQuery(sql); + + return ExecuteTagsQuery(sql); + } + + public IEnumerable GetTagsForEntity(int contentId, string group = null) + { + var sql = GetTagsQuerySelect(); + + sql = ApplyRelationshipJoinToTagsQuery(sql); + + sql = sql + .Where(dto => dto.NodeId == contentId); + + sql = ApplyGroupFilterToTagsQuery(sql, group); + + return ExecuteTagsQuery(sql); + } + + public IEnumerable GetTagsForProperty(int contentId, string propertyTypeAlias, string group = null) + { + var sql = GetTagsQuerySelect(); + + sql = ApplyRelationshipJoinToTagsQuery(sql); + + sql = sql + .InnerJoin() + .On(left => left.Id, right => right.PropertyTypeId) + .Where(dto => dto.NodeId == contentId) + .Where(dto => dto.Alias == propertyTypeAlias); + + sql = ApplyGroupFilterToTagsQuery(sql, group); + + return ExecuteTagsQuery(sql); + } + + private Sql GetTagsQuerySelect(bool withGrouping = false) + { + var sql = new Sql(); + + if (withGrouping) + { + sql = sql.Select("cmsTags.Id, cmsTags.Tag, cmsTags.[Group], Count(*) NodeCount"); + } + else + { + sql = sql.Select("DISTINCT cmsTags.*"); + } + + return sql; + } + + private Sql ApplyRelationshipJoinToTagsQuery(Sql sql) + { + return sql + .From() + .InnerJoin() + .On(left => left.TagId, right => right.Id); + } + + private Sql ApplyGroupFilterToTagsQuery(Sql sql, string group) + { + if (!group.IsNullOrWhiteSpace()) + { + sql = sql.Where(dto => dto.Group == group); + } + + return sql; + } + + private Sql ApplyGroupByToTagsQuery(Sql sql) + { + return sql.GroupBy(new string[] { "cmsTags.Id", "cmsTags.Tag", "cmsTags.[Group]" }); + } + + private IEnumerable ExecuteTagsQuery(Sql sql) + { + 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 propertyTypeAlias, IEnumerable tags, bool replaceTags) + public void AssignTagsToProperty(int contentId, int propertyTypeId, 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; + } + + //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, int propertyTypeId, IEnumerable tags) + { + 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); + } + + public void ClearTagsFromProperty(int contentId, int propertyTypeId) + { + Database.Execute("DELETE FROM cmsTagRelationship WHERE nodeId = @nodeId AND propertyTypeId = @propertyTypeId", + new { nodeId = contentId, propertyTypeId = propertyTypeId }); + } + + public void ClearTagsFromEntity(int contentId) + { + Database.Execute("DELETE FROM cmsTagRelationship WHERE nodeId = @nodeId", + new { nodeId = contentId }); + } + + private Guid GetNodeObjectType(TaggableObjectTypes type) + { + switch (type) + { + case TaggableObjectTypes.Content: + return new Guid(Constants.ObjectTypes.Document); + case TaggableObjectTypes.Media: + return new Guid(Constants.ObjectTypes.Media); + case TaggableObjectTypes.Member: + return new Guid(Constants.ObjectTypes.Member); + default: + throw new ArgumentOutOfRangeException("type"); + } + } + + /// + /// 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]", + PetaPocoExtensions.EscapeAtSymbols(tag.Text.Replace("'", "''")), 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(); + } + } + } + + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs index 1c75759f5b..c031df1637 100644 --- a/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs @@ -185,7 +185,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// /// - protected void ClearEntityTags(IContentBase entity, ITagsRepository tagRepo) + protected void ClearEntityTags(IContentBase entity, ITagRepository tagRepo) { tagRepo.ClearTagsFromEntity(entity.Id); } @@ -195,7 +195,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// /// - protected void UpdatePropertyTags(IContentBase entity, ITagsRepository tagRepo) + protected void UpdatePropertyTags(IContentBase entity, ITagRepository tagRepo) { foreach (var tagProp in entity.Properties.Where(x => x.TagSupport.Enable)) { diff --git a/src/Umbraco.Core/Persistence/RepositoryFactory.cs b/src/Umbraco.Core/Persistence/RepositoryFactory.cs index de5f136567..8a02ac8c3b 100644 --- a/src/Umbraco.Core/Persistence/RepositoryFactory.cs +++ b/src/Umbraco.Core/Persistence/RepositoryFactory.cs @@ -58,9 +58,9 @@ namespace Umbraco.Core.Persistence } #endregion - public virtual ITagsRepository CreateTagsRepository(IDatabaseUnitOfWork uow) + public virtual ITagRepository CreateTagRepository(IDatabaseUnitOfWork uow) { - return new TagsRepository( + return new TagRepository( uow, _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current); } @@ -72,7 +72,7 @@ namespace Umbraco.Core.Persistence _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current, CreateContentTypeRepository(uow), CreateTemplateRepository(uow), - CreateTagsRepository(uow), + CreateTagRepository(uow), _cacheHelper) { EnsureUniqueNaming = _settings.Content.EnsureUniqueNaming }; } @@ -114,7 +114,7 @@ namespace Umbraco.Core.Persistence uow, _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current, CreateMediaTypeRepository(uow), - CreateTagsRepository(uow)) { EnsureUniqueNaming = _settings.Content.EnsureUniqueNaming }; + CreateTagRepository(uow)) { EnsureUniqueNaming = _settings.Content.EnsureUniqueNaming }; } public virtual IMediaTypeRepository CreateMediaTypeRepository(IDatabaseUnitOfWork uow) @@ -191,7 +191,7 @@ namespace Umbraco.Core.Persistence _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current, CreateMemberTypeRepository(uow), CreateMemberGroupRepository(uow), - CreateTagsRepository(uow)); + CreateTagRepository(uow)); } public virtual IMemberTypeRepository CreateMemberTypeRepository(IDatabaseUnitOfWork uow) diff --git a/src/Umbraco.Core/Services/EntityService.cs b/src/Umbraco.Core/Services/EntityService.cs index c78a55d6eb..38b22bf26c 100644 --- a/src/Umbraco.Core/Services/EntityService.cs +++ b/src/Umbraco.Core/Services/EntityService.cs @@ -17,10 +17,14 @@ namespace Umbraco.Core.Services private readonly IContentService _contentService; private readonly IContentTypeService _contentTypeService; private readonly IMediaService _mediaService; + private readonly IMemberService _memberService; + private readonly IMemberTypeService _memberTypeService; private readonly IDataTypeService _dataTypeService; private readonly Dictionary>> _supportedObjectTypes; - public EntityService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, IContentService contentService, IContentTypeService contentTypeService, IMediaService mediaService, IDataTypeService dataTypeService) + public EntityService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, + IContentService contentService, IContentTypeService contentTypeService, IMediaService mediaService, IDataTypeService dataTypeService, + IMemberService memberService, IMemberTypeService memberTypeService) { _uowProvider = provider; _repositoryFactory = repositoryFactory; @@ -28,15 +32,19 @@ namespace Umbraco.Core.Services _contentTypeService = contentTypeService; _mediaService = mediaService; _dataTypeService = dataTypeService; + _memberService = memberService; + _memberTypeService = memberTypeService; _supportedObjectTypes = new Dictionary>> - { - {typeof(IDataTypeDefinition).FullName, new Tuple>(UmbracoObjectTypes.DataType, _dataTypeService.GetDataTypeDefinitionById)}, - {typeof(IContent).FullName, new Tuple>(UmbracoObjectTypes.Document, _contentService.GetById)}, - {typeof(IContentType).FullName, new Tuple>(UmbracoObjectTypes.DocumentType, _contentTypeService.GetContentType)}, - {typeof(IMedia).FullName, new Tuple>(UmbracoObjectTypes.Media, _mediaService.GetById)}, - {typeof(IMediaType).FullName, new Tuple>(UmbracoObjectTypes.MediaType, _contentTypeService.GetMediaType)} - }; + { + {typeof (IDataTypeDefinition).FullName, new Tuple>(UmbracoObjectTypes.DataType, _dataTypeService.GetDataTypeDefinitionById)}, + {typeof (IContent).FullName, new Tuple>(UmbracoObjectTypes.Document, _contentService.GetById)}, + {typeof (IContentType).FullName, new Tuple>(UmbracoObjectTypes.DocumentType, _contentTypeService.GetContentType)}, + {typeof (IMedia).FullName, new Tuple>(UmbracoObjectTypes.Media, _mediaService.GetById)}, + {typeof (IMediaType).FullName, new Tuple>(UmbracoObjectTypes.MediaType, _contentTypeService.GetMediaType)}, + {typeof (IMember).FullName, new Tuple>(UmbracoObjectTypes.Member, _memberService.GetById)}, + {typeof (IMemberType).FullName, new Tuple>(UmbracoObjectTypes.MemberType, _memberTypeService.Get)} + }; } public IUmbracoEntity GetByKey(Guid key, bool loadBaseType = true) @@ -300,7 +308,7 @@ namespace Umbraco.Core.Services /// /// Type of the entities to retrieve /// An enumerable list of objects - public virtual IEnumerable GetAll() where T : IUmbracoEntity + public virtual IEnumerable GetAll(params int[] ids) where T : IUmbracoEntity { var typeFullName = typeof(T).FullName; Mandate.That(_supportedObjectTypes.ContainsKey(typeFullName), () => @@ -310,15 +318,16 @@ namespace Umbraco.Core.Services }); var objectType = _supportedObjectTypes[typeFullName].Item1; - return GetAll(objectType); + return GetAll(objectType, ids); } /// /// Gets a collection of all of a given type. /// /// UmbracoObjectType of the entities to return + /// /// An enumerable list of objects - public virtual IEnumerable GetAll(UmbracoObjectTypes umbracoObjectType) + public virtual IEnumerable GetAll(UmbracoObjectTypes umbracoObjectType, params int[] ids) { var entityType = GetEntityType(umbracoObjectType); var typeFullName = entityType.FullName; @@ -331,7 +340,24 @@ namespace Umbraco.Core.Services var objectTypeId = umbracoObjectType.GetGuid(); using (var repository = _repositoryFactory.CreateEntityRepository(_uowProvider.GetUnitOfWork())) { - return repository.GetAll(objectTypeId); + return repository.GetAll(objectTypeId, ids); + } + } + + public IEnumerable GetAll(UmbracoObjectTypes umbracoObjectType, Guid[] keys) + { + var entityType = GetEntityType(umbracoObjectType); + var typeFullName = entityType.FullName; + Mandate.That(_supportedObjectTypes.ContainsKey(typeFullName), () => + { + throw new NotSupportedException + ("The passed in type is not supported"); + }); + + var objectTypeId = umbracoObjectType.GetGuid(); + using (var repository = _repositoryFactory.CreateEntityRepository(_uowProvider.GetUnitOfWork())) + { + return repository.GetAll(objectTypeId, keys); } } @@ -339,8 +365,9 @@ namespace Umbraco.Core.Services /// Gets a collection of /// /// Guid id of the UmbracoObjectType + /// /// An enumerable list of objects - public virtual IEnumerable GetAll(Guid objectTypeId) + public virtual IEnumerable GetAll(Guid objectTypeId, params int[] ids) { var umbracoObjectType = UmbracoObjectTypesExtensions.GetUmbracoObjectType(objectTypeId); var entityType = GetEntityType(umbracoObjectType); @@ -353,7 +380,7 @@ namespace Umbraco.Core.Services using (var repository = _repositoryFactory.CreateEntityRepository(_uowProvider.GetUnitOfWork())) { - return repository.GetAll(objectTypeId); + return repository.GetAll(objectTypeId, ids); } } diff --git a/src/Umbraco.Core/Services/IEntityService.cs b/src/Umbraco.Core/Services/IEntityService.cs index fdce1751bf..24247197de 100644 --- a/src/Umbraco.Core/Services/IEntityService.cs +++ b/src/Umbraco.Core/Services/IEntityService.cs @@ -135,21 +135,31 @@ namespace Umbraco.Core.Services /// /// Type of the entities to retrieve /// An enumerable list of objects - IEnumerable GetAll() where T : IUmbracoEntity; + IEnumerable GetAll(params int[] ids) where T : IUmbracoEntity; /// /// Gets a collection of all of a given type. /// /// UmbracoObjectType of the entities to return + /// /// An enumerable list of objects - IEnumerable GetAll(UmbracoObjectTypes umbracoObjectType); + IEnumerable GetAll(UmbracoObjectTypes umbracoObjectType, params int[] ids); + + /// + /// Gets a collection of all of a given type. + /// + /// UmbracoObjectType of the entities to return + /// + /// An enumerable list of objects + IEnumerable GetAll(UmbracoObjectTypes umbracoObjectType, Guid[] keys); /// /// Gets a collection of /// /// Guid id of the UmbracoObjectType + /// /// An enumerable list of objects - IEnumerable GetAll(Guid objectTypeId); + IEnumerable GetAll(Guid objectTypeId, params int[] ids); /// /// Gets the UmbracoObjectType from the integer id of an IUmbracoEntity. diff --git a/src/Umbraco.Core/Services/ServiceContext.cs b/src/Umbraco.Core/Services/ServiceContext.cs index 375e1ca1ba..5f253e65bc 100644 --- a/src/Umbraco.Core/Services/ServiceContext.cs +++ b/src/Umbraco.Core/Services/ServiceContext.cs @@ -153,7 +153,9 @@ namespace Umbraco.Core.Services _packagingService = new Lazy(() => new PackagingService(_contentService.Value, _contentTypeService.Value, _mediaService.Value, _macroService.Value, _dataTypeService.Value, _fileService.Value, _localizationService.Value, repositoryFactory.Value, provider)); if (_entityService == null) - _entityService = new Lazy(() => new EntityService(provider, repositoryFactory.Value, _contentService.Value, _contentTypeService.Value, _mediaService.Value, _dataTypeService.Value)); + _entityService = new Lazy(() => new EntityService( + provider, repositoryFactory.Value, + _contentService.Value, _contentTypeService.Value, _mediaService.Value, _dataTypeService.Value, _memberService.Value, _memberTypeService.Value)); if (_relationService == null) _relationService = new Lazy(() => new RelationService(provider, repositoryFactory.Value, _entityService.Value)); diff --git a/src/Umbraco.Core/Services/TagService.cs b/src/Umbraco.Core/Services/TagService.cs index ebe39377ad..cf477a125b 100644 --- a/src/Umbraco.Core/Services/TagService.cs +++ b/src/Umbraco.Core/Services/TagService.cs @@ -45,7 +45,7 @@ namespace Umbraco.Core.Services /// An enumerable list of public IEnumerable GetTaggedContentByTagGroup(string tagGroup) { - using (var repository = _repositoryFactory.CreateTagsRepository(_uowProvider.GetUnitOfWork())) + using (var repository = _repositoryFactory.CreateTagRepository(_uowProvider.GetUnitOfWork())) { return repository.GetTaggedEntitiesByTagGroup(TaggableObjectTypes.Content, tagGroup); } @@ -60,7 +60,7 @@ namespace Umbraco.Core.Services /// An enumerable list of public IEnumerable GetTaggedContentByTag(string tag, string tagGroup = null) { - using (var repository = _repositoryFactory.CreateTagsRepository(_uowProvider.GetUnitOfWork())) + using (var repository = _repositoryFactory.CreateTagRepository(_uowProvider.GetUnitOfWork())) { return repository.GetTaggedEntitiesByTag(TaggableObjectTypes.Content, tag, tagGroup); } @@ -74,7 +74,7 @@ namespace Umbraco.Core.Services /// An enumerable list of public IEnumerable GetTaggedMediaByTagGroup(string tagGroup) { - using (var repository = _repositoryFactory.CreateTagsRepository(_uowProvider.GetUnitOfWork())) + using (var repository = _repositoryFactory.CreateTagRepository(_uowProvider.GetUnitOfWork())) { return repository.GetTaggedEntitiesByTagGroup(TaggableObjectTypes.Media, tagGroup); } @@ -89,7 +89,7 @@ namespace Umbraco.Core.Services /// An enumerable list of public IEnumerable GetTaggedMediaByTag(string tag, string tagGroup = null) { - using (var repository = _repositoryFactory.CreateTagsRepository(_uowProvider.GetUnitOfWork())) + using (var repository = _repositoryFactory.CreateTagRepository(_uowProvider.GetUnitOfWork())) { return repository.GetTaggedEntitiesByTag(TaggableObjectTypes.Media, tag, tagGroup); } @@ -103,7 +103,7 @@ namespace Umbraco.Core.Services /// An enumerable list of public IEnumerable GetTaggedMembersByTagGroup(string tagGroup) { - using (var repository = _repositoryFactory.CreateTagsRepository(_uowProvider.GetUnitOfWork())) + using (var repository = _repositoryFactory.CreateTagRepository(_uowProvider.GetUnitOfWork())) { return repository.GetTaggedEntitiesByTagGroup(TaggableObjectTypes.Member, tagGroup); } @@ -118,7 +118,7 @@ namespace Umbraco.Core.Services /// An enumerable list of public IEnumerable GetTaggedMembersByTag(string tag, string tagGroup = null) { - using (var repository = _repositoryFactory.CreateTagsRepository(_uowProvider.GetUnitOfWork())) + using (var repository = _repositoryFactory.CreateTagRepository(_uowProvider.GetUnitOfWork())) { return repository.GetTaggedEntitiesByTag(TaggableObjectTypes.Member, tag, tagGroup); } @@ -131,7 +131,7 @@ namespace Umbraco.Core.Services /// An enumerable list of public IEnumerable GetAllTags(string tagGroup = null) { - using (var repository = _repositoryFactory.CreateTagsRepository(_uowProvider.GetUnitOfWork())) + using (var repository = _repositoryFactory.CreateTagRepository(_uowProvider.GetUnitOfWork())) { if (tagGroup.IsNullOrWhiteSpace()) { @@ -153,7 +153,7 @@ namespace Umbraco.Core.Services /// An enumerable list of public IEnumerable GetAllContentTags(string tagGroup = null) { - using (var repository = _repositoryFactory.CreateTagsRepository(_uowProvider.GetUnitOfWork())) + using (var repository = _repositoryFactory.CreateTagRepository(_uowProvider.GetUnitOfWork())) { return repository.GetTagsForEntityType(TaggableObjectTypes.Content, tagGroup); } @@ -168,7 +168,7 @@ namespace Umbraco.Core.Services /// An enumerable list of public IEnumerable GetAllMediaTags(string tagGroup = null) { - using (var repository = _repositoryFactory.CreateTagsRepository(_uowProvider.GetUnitOfWork())) + using (var repository = _repositoryFactory.CreateTagRepository(_uowProvider.GetUnitOfWork())) { return repository.GetTagsForEntityType(TaggableObjectTypes.Media, tagGroup); } @@ -183,7 +183,7 @@ namespace Umbraco.Core.Services /// An enumerable list of public IEnumerable GetAllMemberTags(string tagGroup = null) { - using (var repository = _repositoryFactory.CreateTagsRepository(_uowProvider.GetUnitOfWork())) + using (var repository = _repositoryFactory.CreateTagRepository(_uowProvider.GetUnitOfWork())) { return repository.GetTagsForEntityType(TaggableObjectTypes.Member, tagGroup); } @@ -200,7 +200,7 @@ namespace Umbraco.Core.Services /// An enumerable list of public IEnumerable GetTagsForProperty(int contentId, string propertyTypeAlias, string tagGroup = null) { - using (var repository = _repositoryFactory.CreateTagsRepository(_uowProvider.GetUnitOfWork())) + using (var repository = _repositoryFactory.CreateTagRepository(_uowProvider.GetUnitOfWork())) { return repository.GetTagsForProperty(contentId, propertyTypeAlias, tagGroup); } @@ -216,7 +216,7 @@ namespace Umbraco.Core.Services /// An enumerable list of public IEnumerable GetTagsForEntity(int contentId, string tagGroup = null) { - using (var repository = _repositoryFactory.CreateTagsRepository(_uowProvider.GetUnitOfWork())) + using (var repository = _repositoryFactory.CreateTagRepository(_uowProvider.GetUnitOfWork())) { return repository.GetTagsForEntity(contentId, tagGroup); } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index c317594937..d4c1e9097d 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -558,9 +558,9 @@ - + - + diff --git a/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7TagsUpgradeTest.cs b/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7TagsUpgradeTest.cs index ea4d1aa213..880a44c82e 100644 --- a/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7TagsUpgradeTest.cs +++ b/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7TagsUpgradeTest.cs @@ -22,7 +22,7 @@ namespace Umbraco.Tests.Migrations.Upgrades private ContentRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) { var templateRepository = new TemplateRepository(unitOfWork, NullCacheProvider.Current); - var tagRepository = new TagsRepository(unitOfWork, NullCacheProvider.Current); + var tagRepository = new TagRepository(unitOfWork, NullCacheProvider.Current); contentTypeRepository = new ContentTypeRepository(unitOfWork, NullCacheProvider.Current, templateRepository); var repository = new ContentRepository(unitOfWork, NullCacheProvider.Current, contentTypeRepository, templateRepository, tagRepository, CacheHelper.CreateDisabledCacheHelper()); return repository; diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs index 26510f3b5d..f966e87f17 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs @@ -40,7 +40,7 @@ namespace Umbraco.Tests.Persistence.Repositories private ContentRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) { var templateRepository = new TemplateRepository(unitOfWork, NullCacheProvider.Current); - var tagRepository = new TagsRepository(unitOfWork, NullCacheProvider.Current); + var tagRepository = new TagRepository(unitOfWork, NullCacheProvider.Current); contentTypeRepository = new ContentTypeRepository(unitOfWork, NullCacheProvider.Current, templateRepository); var repository = new ContentRepository(unitOfWork, NullCacheProvider.Current, contentTypeRepository, templateRepository, tagRepository, CacheHelper.CreateDisabledCacheHelper()); return repository; diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs index 3f5a7ba401..615d0dfdb3 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs @@ -36,7 +36,7 @@ namespace Umbraco.Tests.Persistence.Repositories private ContentRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) { var templateRepository = new TemplateRepository(unitOfWork, NullCacheProvider.Current); - var tagRepository = new TagsRepository(unitOfWork, NullCacheProvider.Current); + var tagRepository = new TagRepository(unitOfWork, NullCacheProvider.Current); contentTypeRepository = new ContentTypeRepository(unitOfWork, NullCacheProvider.Current, templateRepository); var repository = new ContentRepository(unitOfWork, NullCacheProvider.Current, contentTypeRepository, templateRepository, tagRepository, CacheHelper.CreateDisabledCacheHelper()); return repository; diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs index 95890bdf8b..bd61eea4c7 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs @@ -33,7 +33,7 @@ namespace Umbraco.Tests.Persistence.Repositories private MediaRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out MediaTypeRepository mediaTypeRepository) { mediaTypeRepository = new MediaTypeRepository(unitOfWork, NullCacheProvider.Current); - var tagRepository = new TagsRepository(unitOfWork, NullCacheProvider.Current); + var tagRepository = new TagRepository(unitOfWork, NullCacheProvider.Current); var repository = new MediaRepository(unitOfWork, NullCacheProvider.Current, mediaTypeRepository, tagRepository); return repository; } diff --git a/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs index 13e730a5d6..aaf4abfdbc 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs @@ -34,7 +34,7 @@ namespace Umbraco.Tests.Persistence.Repositories { memberTypeRepository = new MemberTypeRepository(unitOfWork, NullCacheProvider.Current); memberGroupRepository = new MemberGroupRepository(unitOfWork, NullCacheProvider.Current, CacheHelper.CreateDisabledCacheHelper()); - var tagRepo = new TagsRepository(unitOfWork, NullCacheProvider.Current); + var tagRepo = new TagRepository(unitOfWork, NullCacheProvider.Current); var repository = new MemberRepository(unitOfWork, NullCacheProvider.Current, memberTypeRepository, memberGroupRepository, tagRepo); return repository; } diff --git a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs index b7310308bc..bd35197193 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs @@ -29,9 +29,9 @@ namespace Umbraco.Tests.Persistence.Repositories base.TearDown(); } - private TagsRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) + private TagRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) { - var tagRepository = new TagsRepository(unitOfWork, NullCacheProvider.Current); + var tagRepository = new TagRepository(unitOfWork, NullCacheProvider.Current); return tagRepository; } @@ -43,7 +43,7 @@ namespace Umbraco.Tests.Persistence.Repositories var unitOfWork = provider.GetUnitOfWork(); // Act - var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); + var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); // Assert Assert.That(repository, Is.Not.Null); @@ -395,6 +395,85 @@ namespace Umbraco.Tests.Persistence.Repositories } } + [Test] + public void Can_Get_All() + { + 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().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); + + var result = repository.GetAll(); + Assert.AreEqual(4, result.Count()); + } + } + } + + [Test] + public void Can_Get_All_With_Ids() + { + 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)) + { + var tags = 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"} + }; + repository.AssignTagsToProperty( + content1.Id, + contentType.PropertyTypes.First().Id, + tags, false); + + //TODO: This would be nice to be able to map the ids back but unfortunately we are not doing this + //var result = repository.GetAll(new[] {tags[0].Id, tags[1].Id, tags[2].Id}); + var all = repository.GetAll().ToArray(); + + var result = repository.GetAll(new[] { all[0].Id, all[1].Id, all[2].Id }); + Assert.AreEqual(3, result.Count()); + } + } + } + [Test] public void Can_Get_Tags_For_Content_For_Group() { @@ -865,7 +944,7 @@ namespace Umbraco.Tests.Persistence.Repositories private ContentRepository CreateContentRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) { var templateRepository = new TemplateRepository(unitOfWork, NullCacheProvider.Current); - var tagRepository = new TagsRepository(unitOfWork, NullCacheProvider.Current); + var tagRepository = new TagRepository(unitOfWork, NullCacheProvider.Current); contentTypeRepository = new ContentTypeRepository(unitOfWork, NullCacheProvider.Current, templateRepository); var repository = new ContentRepository(unitOfWork, NullCacheProvider.Current, contentTypeRepository, templateRepository, tagRepository, CacheHelper.CreateDisabledCacheHelper()); return repository; @@ -873,7 +952,7 @@ namespace Umbraco.Tests.Persistence.Repositories private MediaRepository CreateMediaRepository(IDatabaseUnitOfWork unitOfWork, out MediaTypeRepository mediaTypeRepository) { - var tagRepository = new TagsRepository(unitOfWork, NullCacheProvider.Current); + var tagRepository = new TagRepository(unitOfWork, NullCacheProvider.Current); mediaTypeRepository = new MediaTypeRepository(unitOfWork, NullCacheProvider.Current); var repository = new MediaRepository(unitOfWork, NullCacheProvider.Current, mediaTypeRepository, tagRepository); return repository; diff --git a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs index a78ca65d58..a3955538cf 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs @@ -144,7 +144,7 @@ namespace Umbraco.Tests.Persistence.Repositories var unitOfWork = provider.GetUnitOfWork(); var templateRepository = new TemplateRepository(unitOfWork, NullCacheProvider.Current); - var tagRepository = new TagsRepository(unitOfWork, NullCacheProvider.Current); + var tagRepository = new TagRepository(unitOfWork, NullCacheProvider.Current); var contentTypeRepository = new ContentTypeRepository(unitOfWork, NullCacheProvider.Current, templateRepository); var contentRepo = new ContentRepository(unitOfWork, NullCacheProvider.Current, contentTypeRepository, templateRepository, tagRepository, CacheHelper.CreateDisabledCacheHelper()); diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index e16bd18712..3b2c36f4dc 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -459,7 +459,7 @@ namespace Umbraco.Web.Editors var objectType = ConvertToObjectType(entityType); if (objectType.HasValue) { - //TODO: Need to check for Object types that support heirarchy here, some might not. + //TODO: Need to check for Object types that support hierarchic here, some might not. return Services.EntityService.GetChildren(id, objectType.Value).Select(Mapper.Map) .WhereNotNull(); @@ -481,7 +481,7 @@ namespace Umbraco.Web.Editors var objectType = ConvertToObjectType(entityType); if (objectType.HasValue) { - //TODO: Need to check for Object types that support heirarchy here, some might not. + //TODO: Need to check for Object types that support hierarchic here, some might not. var ids = Services.EntityService.Get(id).Path.Split(',').Select(int.Parse); return ids.Select(m => Mapper.Map(Services.EntityService.Get(m, objectType.Value))) @@ -569,8 +569,11 @@ namespace Umbraco.Web.Editors var objectType = ConvertToObjectType(entityType); if (objectType.HasValue) { - return keys.Select(id => Mapper.Map(Services.EntityService.GetByKey(id, objectType.Value))) - .WhereNotNull(); + var result = Services.EntityService.GetAll(objectType.Value, keys.ToArray()) + .WhereNotNull() + .Select(Mapper.Map); + + return result; } //now we need to convert the unknown ones switch (entityType) @@ -591,8 +594,10 @@ namespace Umbraco.Web.Editors var objectType = ConvertToObjectType(entityType); if (objectType.HasValue) { - var result = ids.Select(id => Mapper.Map(Services.EntityService.Get(id, objectType.Value))) - .WhereNotNull(); + var result = Services.EntityService.GetAll(objectType.Value, ids.ToArray()) + .WhereNotNull() + .Select(Mapper.Map); + return result; } //now we need to convert the unknown ones