using System; using System.Collections.Generic; using Umbraco.Core.CodeAnnotations; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Services { public class EntityService : IService, IEntityService { private readonly IDatabaseUnitOfWorkProvider _uowProvider; private readonly RepositoryFactory _repositoryFactory; private readonly IContentService _contentService; private readonly IContentTypeService _contentTypeService; private readonly IMediaService _mediaService; private readonly IDataTypeService _dataTypeService; private readonly Dictionary>> _supportedObjectTypes; public EntityService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, IContentService contentService, IContentTypeService contentTypeService, IMediaService mediaService, IDataTypeService dataTypeService) { _uowProvider = provider; _repositoryFactory = repositoryFactory; _contentService = contentService; _contentTypeService = contentTypeService; _mediaService = mediaService; _dataTypeService = dataTypeService; _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)} }; } public IUmbracoEntity GetByKey(Guid key, bool loadBaseType = true) { if (loadBaseType) { using (var repository = _repositoryFactory.CreateEntityRepository(_uowProvider.GetUnitOfWork())) { return repository.GetByKey(key); } } //SD: TODO: Need to enable this at some stage ... just need to ask Morten what the deal is with what this does. throw new NotSupportedException(); //var objectType = GetObjectType(key); //var entityType = GetEntityType(objectType); //var typeFullName = entityType.FullName; //var entity = _supportedObjectTypes[typeFullName].Item2(id); //return entity; } /// /// Gets an UmbracoEntity by its Id, and optionally loads the complete object graph. /// /// /// By default this will load the base type with a minimum set of properties. /// /// Id of the object to retrieve /// Optional bool to load the complete object graph when set to False. /// An public virtual IUmbracoEntity Get(int id, bool loadBaseType = true) { if (loadBaseType) { using (var repository = _repositoryFactory.CreateEntityRepository(_uowProvider.GetUnitOfWork())) { return repository.Get(id); } } var objectType = GetObjectType(id); var entityType = GetEntityType(objectType); var typeFullName = entityType.FullName; var entity = _supportedObjectTypes[typeFullName].Item2(id); return entity; } public IUmbracoEntity GetByKey(Guid key, UmbracoObjectTypes umbracoObjectType, bool loadBaseType = true) { if (loadBaseType) { var objectTypeId = umbracoObjectType.GetGuid(); using (var repository = _repositoryFactory.CreateEntityRepository(_uowProvider.GetUnitOfWork())) { return repository.GetByKey(key, objectTypeId); } } //SD: TODO: Need to enable this at some stage ... just need to ask Morten what the deal is with what this does. throw new NotSupportedException(); //var entityType = GetEntityType(umbracoObjectType); //var typeFullName = entityType.FullName; //var entity = _supportedObjectTypes[typeFullName].Item2(id); //return entity; } /// /// Gets an UmbracoEntity by its Id and UmbracoObjectType, and optionally loads the complete object graph. /// /// /// By default this will load the base type with a minimum set of properties. /// /// Id of the object to retrieve /// UmbracoObjectType of the entity to retrieve /// Optional bool to load the complete object graph when set to False. /// An public virtual IUmbracoEntity Get(int id, UmbracoObjectTypes umbracoObjectType, bool loadBaseType = true) { if (loadBaseType) { var objectTypeId = umbracoObjectType.GetGuid(); using (var repository = _repositoryFactory.CreateEntityRepository(_uowProvider.GetUnitOfWork())) { return repository.Get(id, objectTypeId); } } var entityType = GetEntityType(umbracoObjectType); var typeFullName = entityType.FullName; var entity = _supportedObjectTypes[typeFullName].Item2(id); return entity; } public IUmbracoEntity GetByKey(Guid key, bool loadBaseType = true) where T : IUmbracoEntity { throw new NotImplementedException(); } /// /// Gets an UmbracoEntity by its Id and specified Type. Optionally loads the complete object graph. /// /// /// By default this will load the base type with a minimum set of properties. /// /// Type of the model to retrieve. Must be based on an /// Id of the object to retrieve /// Optional bool to load the complete object graph when set to False. /// An public virtual IUmbracoEntity Get(int id, bool loadBaseType = true) where T : IUmbracoEntity { if (loadBaseType) { using (var repository = _repositoryFactory.CreateEntityRepository(_uowProvider.GetUnitOfWork())) { return repository.Get(id); } } var typeFullName = typeof(T).FullName; Mandate.That(_supportedObjectTypes.ContainsKey(typeFullName), () => { throw new NotSupportedException ("The passed in type is not supported"); }); var entity = _supportedObjectTypes[typeFullName].Item2(id); return entity; } /// /// Gets the parent of entity by its id /// /// Id of the entity to retrieve the Parent for /// An public virtual IUmbracoEntity GetParent(int id) { using (var repository = _repositoryFactory.CreateEntityRepository(_uowProvider.GetUnitOfWork())) { var entity = repository.Get(id); if (entity.ParentId == -1 || entity.ParentId == -20 || entity.ParentId == -21) return null; return repository.Get(entity.ParentId); } } /// /// Gets the parent of entity by its id and UmbracoObjectType /// /// Id of the entity to retrieve the Parent for /// UmbracoObjectType of the parent to retrieve /// An public virtual IUmbracoEntity GetParent(int id, UmbracoObjectTypes umbracoObjectType) { using (var repository = _repositoryFactory.CreateEntityRepository(_uowProvider.GetUnitOfWork())) { var entity = repository.Get(id); if (entity.ParentId == -1 || entity.ParentId == -20 || entity.ParentId == -21) return null; var objectTypeId = umbracoObjectType.GetGuid(); return repository.Get(entity.ParentId, objectTypeId); } } /// /// Gets a collection of children by the parents Id /// /// Id of the parent to retrieve children for /// An enumerable list of objects public virtual IEnumerable GetChildren(int parentId) { using (var repository = _repositoryFactory.CreateEntityRepository(_uowProvider.GetUnitOfWork())) { var query = Query.Builder.Where(x => x.ParentId == parentId); var contents = repository.GetByQuery(query); return contents; } } /// /// Gets a collection of children by the parents Id and UmbracoObjectType /// /// Id of the parent to retrieve children for /// UmbracoObjectType of the children to retrieve /// An enumerable list of objects public virtual IEnumerable GetChildren(int parentId, UmbracoObjectTypes umbracoObjectType) { var objectTypeId = umbracoObjectType.GetGuid(); using (var repository = _repositoryFactory.CreateEntityRepository(_uowProvider.GetUnitOfWork())) { var query = Query.Builder.Where(x => x.ParentId == parentId); var contents = repository.GetByQuery(query, objectTypeId); return contents; } } /// /// Gets a collection of descendents by the parents Id /// /// Id of entity to retrieve descendents for /// An enumerable list of objects public virtual IEnumerable GetDescendents(int id) { using (var repository = _repositoryFactory.CreateEntityRepository(_uowProvider.GetUnitOfWork())) { var entity = repository.Get(id); var query = Query.Builder.Where(x => x.Path.StartsWith(entity.Path) && x.Id != id); var entities = repository.GetByQuery(query); return entities; } } /// /// Gets a collection of descendents by the parents Id /// /// Id of entity to retrieve descendents for /// UmbracoObjectType of the descendents to retrieve /// An enumerable list of objects public virtual IEnumerable GetDescendents(int id, UmbracoObjectTypes umbracoObjectType) { var objectTypeId = umbracoObjectType.GetGuid(); using (var repository = _repositoryFactory.CreateEntityRepository(_uowProvider.GetUnitOfWork())) { var entity = repository.Get(id); var query = Query.Builder.Where(x => x.Path.StartsWith(entity.Path) && x.Id != id); var entities = repository.GetByQuery(query, objectTypeId); return entities; } } /// /// Gets a collection of the entities at the root, which corresponds to the entities with a Parent Id of -1. /// /// UmbracoObjectType of the root entities to retrieve /// An enumerable list of objects public virtual IEnumerable GetRootEntities(UmbracoObjectTypes umbracoObjectType) { var objectTypeId = umbracoObjectType.GetGuid(); using (var repository = _repositoryFactory.CreateEntityRepository(_uowProvider.GetUnitOfWork())) { var query = Query.Builder.Where(x => x.ParentId == -1); var entities = repository.GetByQuery(query, objectTypeId); return entities; } } /// /// Gets a collection of all of a given type. /// /// Type of the entities to retrieve /// An enumerable list of objects public virtual IEnumerable GetAll() where T : IUmbracoEntity { var typeFullName = typeof(T).FullName; Mandate.That(_supportedObjectTypes.ContainsKey(typeFullName), () => { throw new NotSupportedException ("The passed in type is not supported"); }); var objectType = _supportedObjectTypes[typeFullName].Item1; return GetAll(objectType); } /// /// 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) { 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); } } /// /// Gets a collection of /// /// Guid id of the UmbracoObjectType /// An enumerable list of objects public virtual IEnumerable GetAll(Guid objectTypeId) { var umbracoObjectType = UmbracoObjectTypesExtensions.GetUmbracoObjectType(objectTypeId); var entityType = GetEntityType(umbracoObjectType); var typeFullName = entityType.FullName; Mandate.That(_supportedObjectTypes.ContainsKey(typeFullName), () => { throw new NotSupportedException ("The passed in type is not supported"); }); using (var repository = _repositoryFactory.CreateEntityRepository(_uowProvider.GetUnitOfWork())) { return repository.GetAll(objectTypeId); } } /// /// Gets the UmbracoObjectType from the integer id of an IUmbracoEntity. /// /// Id of the entity /// public virtual UmbracoObjectTypes GetObjectType(int id) { using (var uow = _uowProvider.GetUnitOfWork()) { var sql = new Sql().Select("nodeObjectType").From().Where(x => x.NodeId == id); var nodeObjectTypeId = uow.Database.ExecuteScalar(sql); var objectTypeId = new Guid(nodeObjectTypeId); return UmbracoObjectTypesExtensions.GetUmbracoObjectType(objectTypeId); } } /// /// Gets the UmbracoObjectType from the integer id of an IUmbracoEntity. /// /// Unique Id of the entity /// public virtual UmbracoObjectTypes GetObjectType(Guid key) { using (var uow = _uowProvider.GetUnitOfWork()) { var sql = new Sql().Select("nodeObjectType").From().Where(x => x.UniqueId == key); var nodeObjectTypeId = uow.Database.ExecuteScalar(sql); var objectTypeId = new Guid(nodeObjectTypeId); return UmbracoObjectTypesExtensions.GetUmbracoObjectType(objectTypeId); } } /// /// Gets the UmbracoObjectType from an IUmbracoEntity. /// /// /// public virtual UmbracoObjectTypes GetObjectType(IUmbracoEntity entity) { var entityImpl = entity as UmbracoEntity; if (entityImpl == null) return GetObjectType(entity.Id); return UmbracoObjectTypesExtensions.GetUmbracoObjectType(entityImpl.NodeObjectTypeId); } /// /// Gets the Type of an entity by its Id /// /// Id of the entity /// Type of the entity public virtual Type GetEntityType(int id) { var objectType = GetObjectType(id); return GetEntityType(objectType); } /// /// Gets the Type of an entity by its /// /// /// Type of the entity public virtual Type GetEntityType(UmbracoObjectTypes umbracoObjectType) { var type = typeof(UmbracoObjectTypes); var memInfo = type.GetMember(umbracoObjectType.ToString()); var attributes = memInfo[0].GetCustomAttributes(typeof(UmbracoObjectTypeAttribute), false); var attribute = ((UmbracoObjectTypeAttribute)attributes[0]); if (attribute == null) throw new NullReferenceException("The passed in UmbracoObjectType does not contain an UmbracoObjectTypeAttribute, which is used to retrieve the Type."); if (attribute.ModelType == null) throw new NullReferenceException("The passed in UmbracoObjectType does not contain a Type definition"); return attribute.ModelType; } } }