Adds ContentType factory implementations U4-980

Adds ContentType repository implementation U4-956
This commit is contained in:
Morten@Thinkpad-X220
2012-10-08 12:12:41 -02:00
parent eb35d712bb
commit 60508a2327
4 changed files with 470 additions and 0 deletions

View File

@@ -0,0 +1,90 @@
using System;
using System.Globalization;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Factories
{
internal class ContentTypeFactory : IEntityFactory<IContentType, DocumentTypeDto>
{
private readonly Guid _nodeObjectType;
#region Implementation of IEntityFactory<IContentType,DocumentTypeDto>
public ContentTypeFactory(Guid nodeObjectType)
{
_nodeObjectType = nodeObjectType;
}
public IContentType BuildEntity(DocumentTypeDto dto)
{
var contentType = new ContentType
{
Id = dto.ContentTypeDto.NodeDto.NodeId,
Key =
dto.ContentTypeDto.NodeDto.UniqueId.HasValue
? dto.ContentTypeDto.NodeDto.UniqueId.Value
: dto.ContentTypeDto.NodeDto.NodeId.ToGuid(),
Alias = dto.ContentTypeDto.Alias,
Name = dto.ContentTypeDto.NodeDto.Text,
Icon = dto.ContentTypeDto.Icon,
Thumbnail = dto.ContentTypeDto.Thumbnail,
SortOrder = dto.ContentTypeDto.NodeDto.SortOrder,
Description = dto.ContentTypeDto.Description,
CreateDate = dto.ContentTypeDto.NodeDto.CreateDate,
Path = dto.ContentTypeDto.NodeDto.Path,
Level = dto.ContentTypeDto.NodeDto.Level,
ParentId = dto.ContentTypeDto.NodeDto.ParentId,
UserId =
dto.ContentTypeDto.NodeDto.UserId.HasValue
? dto.ContentTypeDto.NodeDto.UserId.Value
: 0,
Trashed = dto.ContentTypeDto.NodeDto.Trashed
};
return contentType;
}
public DocumentTypeDto BuildDto(IContentType entity)
{
var documentTypeDto = new DocumentTypeDto
{ContentTypeDto = BuildContentTypeDto(entity), ContentTypeNodeId = entity.Id};
//NOTE TemplateId and IsDefault currently not added
return documentTypeDto;
}
#endregion
private ContentTypeDto BuildContentTypeDto(IContentType entity)
{
var contentTypeDto = new ContentTypeDto
{
Alias = entity.Alias,
Description = entity.Description,
Icon = entity.Icon,
Thumbnail = entity.Thumbnail,
NodeId = entity.Id,
NodeDto = BuildNodeDto(entity)
};
return contentTypeDto;
}
private NodeDto BuildNodeDto(IContentType entity)
{
var nodeDto = new NodeDto
{
CreateDate = entity.CreateDate,
NodeId = entity.Id,
Level = short.Parse(entity.Level.ToString(CultureInfo.InvariantCulture)),
NodeObjectType = _nodeObjectType,
ParentId = entity.ParentId,
Path = entity.Path,
SortOrder = entity.SortOrder,
Text = entity.Name,
Trashed = false,
UniqueId = entity.Key,
UserId = entity.UserId
};
return nodeDto;
}
}
}

View File

@@ -0,0 +1,98 @@
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Factories
{
internal class PropertyGroupFactory : IEntityFactory<IEnumerable<PropertyGroup>, IEnumerable<TabDto>>
{
private int _id;
public PropertyGroupFactory(int id)
{
_id = id;
}
#region Implementation of IEntityFactory<IEnumerable<PropertyGroup>,IEnumerable<TabDto>>
public IEnumerable<PropertyGroup> BuildEntity(IEnumerable<TabDto> dto)
{
var propertyGroups = new PropertyGroupCollection();
foreach (var tabDto in dto)
{
var group = new PropertyGroup();
group.Id = tabDto.Id;
group.Name = tabDto.Text;
group.SortOrder = tabDto.SortOrder;
group.PropertyTypes = new PropertyTypeCollection();
foreach (var typeDto in tabDto.PropertyTypeDtos)
{
group.PropertyTypes.Add(new PropertyType(typeDto.DataTypeDto.ControlId,
typeDto.DataTypeDto.DbType.EnumParse<DataTypeDatabaseType>(true))
{
Alias = typeDto.Alias,
DataTypeId = typeDto.DataTypeId,
Description = typeDto.Description,
Id = typeDto.Id,
Name = typeDto.Name,
HelpText = typeDto.HelpText,
Mandatory = typeDto.Mandatory,
SortOrder = typeDto.SortOrder
});
}
group.ResetDirtyProperties();
propertyGroups.Add(group);
}
return propertyGroups;
}
public IEnumerable<TabDto> BuildDto(IEnumerable<PropertyGroup> entity)
{
return entity.Select(propertyGroup => BuildTabDto(propertyGroup)).ToList();
}
#endregion
internal TabDto BuildTabDto(PropertyGroup propertyGroup)
{
var tabDto = new TabDto
{
ContentTypeNodeId = _id,
SortOrder = propertyGroup.SortOrder,
Text = propertyGroup.Name
};
if (propertyGroup.HasIdentity)
tabDto.Id = propertyGroup.Id;
tabDto.PropertyTypeDtos = propertyGroup.PropertyTypes.Select(propertyType => BuildPropertyTypeDto(propertyGroup.Id, propertyType)).ToList();
return tabDto;
}
internal PropertyTypeDto BuildPropertyTypeDto(int tabId, PropertyType propertyType)
{
var propertyTypeDto = new PropertyTypeDto
{
Alias = propertyType.Alias,
ContentTypeId = _id,
DataTypeId = propertyType.DataTypeId,
Description = propertyType.Description,
HelpText = propertyType.HelpText,
Mandatory = propertyType.Mandatory,
Name = propertyType.Name,
SortOrder = propertyType.SortOrder,
TabId = tabId
};
if (propertyType.HasIdentity)
propertyTypeDto.Id = propertyType.Id;
return propertyTypeDto;
}
}
}

View File

@@ -0,0 +1,279 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
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.Relators;
using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Persistence.Repositories
{
/// <summary>
/// Represents a repository for doing CRUD operations for <see cref="IContentType"/>
/// </summary>
internal class ContentTypeRepository : PetaPocoRepositoryBase<int, IContentType>, IContentTypeRepository
{
public ContentTypeRepository(IUnitOfWork work) : base(work)
{
}
public ContentTypeRepository(IUnitOfWork work, IRepositoryCacheProvider cache) : base(work, cache)
{
}
#region Overrides of RepositoryBase<int,IContentType>
protected override IContentType PerformGet(int id)
{
var contentTypeSql = GetBaseQuery(false);
contentTypeSql.Append(GetBaseWhereClause(id));
var documentTypeDto = Database.Query<DocumentTypeDto, ContentTypeDto, NodeDto>(contentTypeSql).FirstOrDefault();
if (documentTypeDto == null)
return null;
//TODO Get ContentType composition according to new table
var propertySql = new Sql();
propertySql.Select("*");
propertySql.From("cmsTab");
propertySql.RightJoin("cmsPropertyType ON [cmsTab].[id] = [cmsPropertyType].[tabId]");
propertySql.InnerJoin("cmsDataType ON [cmsPropertyType].[dataTypeId] = [cmsDataType].[nodeId]");
propertySql.Where("[cmsPropertyType].[contentTypeId] = @Id", new { Id = id });
var tabDtos = Database.Fetch<TabDto, PropertyTypeDto, DataTypeDto, TabDto>(new TabPropertyTypeRelator().Map, propertySql);
var factory = new ContentTypeFactory(NodeObjectTypeId);
var contentType = factory.BuildEntity(documentTypeDto);
var propertyFactory = new PropertyGroupFactory(id);
var propertyGroups = propertyFactory.BuildEntity(tabDtos);
contentType.PropertyGroups = new PropertyGroupCollection(propertyGroups);
((ContentType)contentType).ResetDirtyProperties();
return contentType;
}
protected override IEnumerable<IContentType> PerformGetAll(params int[] ids)
{
if (ids.Any())
{
foreach (var id in ids)
{
yield return Get(id);
}
}
else
{
var nodeDtos = Database.Fetch<NodeDto>("WHERE nodeObjectType = @NodeObjectType", new { NodeObjectType = NodeObjectTypeId });
foreach (var nodeDto in nodeDtos)
{
yield return Get(nodeDto.NodeId);
}
}
}
protected override IEnumerable<IContentType> PerformGetByQuery(IQuery<IContentType> query)
{
var sqlClause = GetBaseQuery(false);
var translator = new SqlTranslator<IContentType>(sqlClause, query);
var sql = translator.Translate();
var documentTypeDtos = Database.Fetch<DocumentTypeDto, ContentTypeDto, NodeDto>(sql);
foreach (var dto in documentTypeDtos)
{
yield return Get(dto.ContentTypeNodeId);
}
}
#endregion
#region Overrides of PetaPocoRepositoryBase<int,IContentType>
protected override Sql GetBaseQuery(bool isCount)
{
var sql = new Sql();
//NOTE: If IsDefault=true we won't get ContentTypes like File, Folder etc. but only DocumentTypes.
//Which is why "AND cmsDocumentType.IsDefault = @IsDefault" has been removed from sql below.
//But might need to add it if we create a MediaTypeRepository
sql.Select(isCount ? "COUNT(*)" : "*");
sql.From("cmsDocumentType");
sql.RightJoin("cmsContentType ON ([cmsContentType].[nodeId] = [cmsDocumentType].[contentTypeNodeId])");
sql.InnerJoin("umbracoNode ON ([cmsContentType].[nodeId] = [umbracoNode].[id])");
sql.Where("[umbracoNode].[nodeObjectType] = @NodeObjectType", new { NodeObjectType = NodeObjectTypeId });
return sql;
}
protected override Sql GetBaseWhereClause(object id)
{
var sql = new Sql();
sql.Where("[umbracoNode].[id] = @Id", new { Id = id });
return sql;
}
protected override IEnumerable<string> GetDeleteClauses()
{
var list = new List<string>
{
string.Format("DELETE FROM umbracoUser2NodeNotify WHERE nodeId = @Id"),
string.Format("DELETE FROM umbracoUser2NodePermission WHERE nodeId = @Id"),
string.Format("DELETE FROM cmsTagRelationship WHERE nodeId = @Id"),
string.Format("DELETE FROM cmsContentTypeAllowedContentType WHERE Id = @Id"),
string.Format("DELETE FROM cmsPropertyType WHERE contentTypeId = @Id"),
string.Format("DELETE FROM cmsTab WHERE contenttypeNodeId = @Id"),
string.Format("DELETE FROM cmsDocumentType WHERE contentTypeNodeId = @Id"),
string.Format("DELETE FROM cmsContentType WHERE NodeId = @Id"),
string.Format("DELETE FROM umbracoNode WHERE id = @Id")
};
return list;
}
protected override Guid NodeObjectTypeId
{
get { return new Guid("A2CB7800-F571-4787-9638-BC48539A0EFB"); }
}
#endregion
#region Unit of Work Implementation
protected override void PersistNewItem(IContentType entity)
{
((ContentType)entity).AddingEntity();
var factory = new ContentTypeFactory(NodeObjectTypeId);
var dto = factory.BuildDto(entity);
//Logic for setting Path, Level and SortOrder
var parent = Database.First<NodeDto>("WHERE id = @ParentId", new { ParentId = entity.ParentId });
int level = parent.Level + 1;
int sortOrder =
Database.ExecuteScalar<int>("SELECT COUNT(*) FROM umbracoNode WHERE parentID = @ParentId AND nodeObjectType = @NodeObjectType",
new { ParentId = entity.ParentId, NodeObjectType = NodeObjectTypeId });
//Create the (base) node data - umbracoNode
var nodeDto = dto.ContentTypeDto.NodeDto;
nodeDto.Path = parent.Path;
nodeDto.Level = short.Parse(level.ToString(CultureInfo.InvariantCulture));
nodeDto.SortOrder = sortOrder;
var o = Database.IsNew(nodeDto) ? Convert.ToInt32(Database.Insert(nodeDto)) : Database.Update(nodeDto);
//Update with new correct path
nodeDto.Path = string.Concat(parent.Path, ",", nodeDto.NodeId);
Database.Update(nodeDto);
//Update entity with correct values
entity.Id = nodeDto.NodeId; //Set Id on entity to ensure an Id is set
entity.Path = nodeDto.Path;
entity.SortOrder = sortOrder;
entity.Level = level;
//Insert new ContentType entry
var contentTypeDto = dto.ContentTypeDto;
Database.Insert(contentTypeDto);
//TODO Insert new DocumentType entries - NOTE only seems relevant as long as Templates resides in the DB
//TODO Insert allowed Templates and DocumentTypes
//TODO Insert ContentType composition in new table
var propertyFactory = new PropertyGroupFactory(nodeDto.NodeId);
//Insert Tabs
foreach (var propertyGroup in entity.PropertyGroups)
{
var tabDto = propertyFactory.BuildTabDto(propertyGroup);
var primaryKey = Convert.ToInt32(Database.Insert(tabDto));
propertyGroup.Id = primaryKey;//Set Id on PropertyGroup
}
//Insert PropertyTypes
foreach (var propertyGroup in entity.PropertyGroups)
{
foreach (var propertyType in propertyGroup.PropertyTypes)
{
var propertyTypeDto = propertyFactory.BuildPropertyTypeDto(propertyGroup.Id, propertyType);
var primaryKey = Convert.ToInt32(Database.Insert(propertyTypeDto));
propertyType.Id = primaryKey;//Set Id on PropertyType
}
}
((ContentType)entity).ResetDirtyProperties();
}
protected override void PersistUpdatedItem(IContentType entity)
{
//Updates Modified date
((ContentType)entity).UpdatingEntity();
var propertyFactory = new PropertyGroupFactory(entity.Id);
var factory = new ContentTypeFactory(NodeObjectTypeId);
var dto = factory.BuildDto(entity);
var nodeDto = dto.ContentTypeDto.NodeDto;
var o = Database.Update(nodeDto);
//Look up ContentType entry to get PrimaryKey for updating the DTO
var dtoPk = Database.First<ContentTypeDto>("WHERE nodeId = @Id", new { Id = entity.Id });
var contentTypeDto = dto.ContentTypeDto;
contentTypeDto.PrimaryKey = dtoPk.PrimaryKey;
Database.Update(contentTypeDto);
//Look up DocumentType entries for updating - this could possibly be a "remove all, insert all"-approach
//Check Dirty properties for Tabs/Groups and PropertyTypes - insert and delete accordingly
if (((ICanBeDirty)entity).IsPropertyDirty("PropertyGroups") || entity.PropertyGroups.Any(x => x.IsDirty()))
{
//Delete PropertyTypes by excepting entries from db with entries from collections
var dbPropertyTypes = Database.Fetch<PropertyTypeDto>("WHERE contentTypeId = @Id", new { Id = entity.Id }).Select(x => x.Alias);
var entityPropertyTypes = entity.PropertyTypes.Select(x => x.Alias);
var aliases = dbPropertyTypes.Except(entityPropertyTypes);
foreach (var alias in aliases)
{
Database.Delete<PropertyTypeDto>("WHERE contentTypeId = @Id AND Alias = @Alias", new { Id = entity.Id, Alias = alias });
}
//Delete Tabs/Groups by excepting entries from db with entries from collections
var dbPropertyGroups = Database.Fetch<TabDto>("WHERE contenttypeNodeId = @Id", new { Id = entity.Id }).Select(x => x.Text);
var entityPropertyGroups = entity.PropertyGroups.Select(x => x.Name);
var tabs = dbPropertyGroups.Except(entityPropertyGroups);
foreach (var tabName in tabs)
{
Database.Delete<TabDto>("WHERE contenttypeNodeId = @Id AND text = @Name", new { Id = entity.Id, Name = tabName });
}
//Run through all groups and types to insert or update entries
foreach (var propertyGroup in entity.PropertyGroups)
{
var tabDto = propertyFactory.BuildTabDto(propertyGroup);
int groupPrimaryKey = propertyGroup.HasIdentity
? Database.Update(tabDto)
: Convert.ToInt32(Database.Insert(tabDto));
if (!propertyGroup.HasIdentity)
propertyGroup.Id = groupPrimaryKey;//Set Id on new PropertyGroup
//This should indicate that neither group nor property types has been touched, but this implies a deeper 'Dirty'-lookup
//if(!propertyGroup.IsDirty()) continue;
foreach (var propertyType in propertyGroup.PropertyTypes)
{
var propertyTypeDto = propertyFactory.BuildPropertyTypeDto(propertyGroup.Id, propertyType);
int typePrimaryKey = propertyType.HasIdentity
? Database.Update(propertyTypeDto)
: Convert.ToInt32(Database.Insert(propertyTypeDto));
if (!propertyType.HasIdentity)
propertyType.Id = typePrimaryKey;//Set Id on new PropertyType
}
}
}
((ContentType)entity).ResetDirtyProperties();
}
#endregion
}
}

View File

@@ -99,15 +99,18 @@
<Compile Include="Persistence\Caching\RuntimeCacheProvider.cs" />
<Compile Include="Persistence\DatabaseFactory.cs" />
<Compile Include="Persistence\Factories\ContentFactory.cs" />
<Compile Include="Persistence\Factories\ContentTypeFactory.cs" />
<Compile Include="Persistence\Factories\DataTypeDefinitionFactory.cs" />
<Compile Include="Persistence\Factories\IEntityFactory.cs" />
<Compile Include="Persistence\Factories\PropertyFactory.cs" />
<Compile Include="Persistence\Factories\PropertyGroupFactory.cs" />
<Compile Include="Persistence\Mappers\ModelDtoMapper.cs" />
<Compile Include="Persistence\Querying\ExpressionHelper.cs" />
<Compile Include="Persistence\Querying\IQuery.cs" />
<Compile Include="Persistence\Querying\Query.cs" />
<Compile Include="Persistence\Querying\SqlTranslator.cs" />
<Compile Include="Persistence\Repositories\ContentRepository.cs" />
<Compile Include="Persistence\Repositories\ContentTypeRepository.cs" />
<Compile Include="Persistence\Repositories\DataTypeDefinitionRepository.cs" />
<Compile Include="Persistence\Repositories\IContentRepository.cs" />
<Compile Include="Persistence\Repositories\IContentTypeRepository.cs" />