From dffc6ca1a0b0945c5100f4d9ae38a419c7975207 Mon Sep 17 00:00:00 2001 From: Morten Christensen Date: Sun, 11 Nov 2012 06:53:02 -0100 Subject: [PATCH] Refactoring entities with Users to only add Id to minimize the object graph. Moved getting an IProfile to an extension method, as its not commonly used. Removing dependencies in ContentService, so the Services and context can be moved to Core proj. Implementing Template repository to use both filesystem and db. --- src/Umbraco.Core/Models/Content.cs | 8 +- src/Umbraco.Core/Models/ContentBase.cs | 22 +- src/Umbraco.Core/Models/ContentExtensions.cs | 55 +--- src/Umbraco.Core/Models/ContentType.cs | 6 +- src/Umbraco.Core/Models/ContentTypeBase.cs | 14 +- src/Umbraco.Core/Models/EntityBase/Entity.cs | 1 - src/Umbraco.Core/Models/IContent.cs | 4 +- src/Umbraco.Core/Models/IContentBase.cs | 9 +- src/Umbraco.Core/Models/IContentTypeBase.cs | 4 +- src/Umbraco.Core/Models/IFile.cs | 2 +- src/Umbraco.Core/Models/ITemplate.cs | 14 + src/Umbraco.Core/Models/Membership/Profile.cs | 7 + src/Umbraco.Core/Models/Membership/User.cs | 27 +- .../Models/Membership/UserProfile.cs | 10 +- .../Models/Membership/UserType.cs | 9 +- src/Umbraco.Core/Models/Rdbms/TemplateDto.cs | 8 +- src/Umbraco.Core/Models/Template.cs | 40 ++- .../Persistence/Factories/ContentFactory.cs | 15 +- .../Factories/ContentTypeFactory.cs | 11 +- .../Persistence/Factories/MediaFactory.cs | 9 +- .../Persistence/Factories/MediaTypeFactory.cs | 12 +- .../Persistence/Mappers/ContentMapper.cs | 2 +- .../Persistence/Mappers/ContentTypeMapper.cs | 2 +- .../Persistence/Mappers/MediaMapper.cs | 2 +- .../Repositories/ContentRepository.cs | 21 +- .../Repositories/ContentTypeRepository.cs | 4 +- .../Interfaces/ITemplateFileOnlyRepository.cs | 8 + .../Interfaces/ITemplateRepository.cs | 5 +- .../Repositories/MediaRepository.cs | 4 +- .../Repositories/MediaTypeRepository.cs | 4 +- .../TemplateFileOnlyFileOnlyRepository.cs | 171 ++++++++++++ .../Repositories/TemplateRepository.cs | 264 ++++++++++++------ src/Umbraco.Core/Services/IUserService.cs | 9 +- src/Umbraco.Core/Umbraco.Core.csproj | 3 + src/Umbraco.Tests/Models/ContentXmlTest.cs | 1 + .../Repositories/ContentRepositoryTest.cs | 4 +- .../Persistence/RepositoryResolverTests.cs | 2 +- .../Services/ContentServiceTests.cs | 3 +- .../TestHelpers/Entities/MockedContent.cs | 8 +- .../Entities/MockedContentTypes.cs | 14 +- .../TestHelpers/Entities/MockedMedia.cs | 6 +- src/Umbraco.Web/ContentExtensions.cs | 69 +++++ src/Umbraco.Web/Services/ContentService.cs | 46 +-- src/Umbraco.Web/Services/FileService.cs | 10 +- src/Umbraco.Web/Services/ServiceContext.cs | 11 +- src/Umbraco.Web/Services/UserService.cs | 17 +- .../Services/UserServiceExtesions.cs | 13 - src/Umbraco.Web/Strategies/DeletedTemplate.cs | 14 + src/Umbraco.Web/Strategies/TrashedContent.cs | 6 +- src/Umbraco.Web/Umbraco.Web.csproj | 3 +- 50 files changed, 676 insertions(+), 337 deletions(-) create mode 100644 src/Umbraco.Core/Models/ITemplate.cs create mode 100644 src/Umbraco.Core/Persistence/Repositories/Interfaces/ITemplateFileOnlyRepository.cs create mode 100644 src/Umbraco.Core/Persistence/Repositories/TemplateFileOnlyFileOnlyRepository.cs create mode 100644 src/Umbraco.Web/ContentExtensions.cs delete mode 100644 src/Umbraco.Web/Services/UserServiceExtesions.cs create mode 100644 src/Umbraco.Web/Strategies/DeletedTemplate.cs diff --git a/src/Umbraco.Core/Models/Content.cs b/src/Umbraco.Core/Models/Content.cs index ba72f6d099..6efa64e866 100644 --- a/src/Umbraco.Core/Models/Content.cs +++ b/src/Umbraco.Core/Models/Content.cs @@ -19,7 +19,7 @@ namespace Umbraco.Core.Models private string _language; private DateTime? _releaseDate; private DateTime? _expireDate; - private IProfile _writer; + private int _writer; /// /// Constructor for creating a Content object @@ -48,7 +48,7 @@ namespace Umbraco.Core.Models private static readonly PropertyInfo LanguageSelector = ExpressionHelper.GetPropertyInfo(x => x.Language); private static readonly PropertyInfo ReleaseDateSelector = ExpressionHelper.GetPropertyInfo(x => x.ReleaseDate); private static readonly PropertyInfo ExpireDateSelector = ExpressionHelper.GetPropertyInfo(x => x.ExpireDate); - private static readonly PropertyInfo WriterSelector = ExpressionHelper.GetPropertyInfo(x => x.Writer); + private static readonly PropertyInfo WriterSelector = ExpressionHelper.GetPropertyInfo(x => x.WriterId); /// /// Path to the template used by this Content @@ -163,10 +163,10 @@ namespace Umbraco.Core.Models } /// - /// IProfile of the user who wrote/updated this Content + /// Id of the user who wrote/updated this Content /// [DataMember] - public virtual IProfile Writer + public virtual int WriterId { get { return _writer; } set diff --git a/src/Umbraco.Core/Models/ContentBase.cs b/src/Umbraco.Core/Models/ContentBase.cs index d1802cb82a..118cd5f538 100644 --- a/src/Umbraco.Core/Models/ContentBase.cs +++ b/src/Umbraco.Core/Models/ContentBase.cs @@ -21,7 +21,7 @@ namespace Umbraco.Core.Models private int _sortOrder; private int _level; private string _path; - private IProfile _creator; + private int _creatorId; private bool _trashed; private int _contentTypeId; private PropertyCollection _properties; @@ -45,7 +45,7 @@ namespace Umbraco.Core.Models private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo(x => x.SortOrder); private static readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo(x => x.Level); private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo(x => x.Path); - private static readonly PropertyInfo CreatorSelector = ExpressionHelper.GetPropertyInfo(x => x.Creator); + private static readonly PropertyInfo CreatorIdSelector = ExpressionHelper.GetPropertyInfo(x => x.CreatorId); private static readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo(x => x.Trashed); private static readonly PropertyInfo DefaultContentTypeIdSelector = ExpressionHelper.GetPropertyInfo(x => x.ContentTypeId); private readonly static PropertyInfo PropertyCollectionSelector = ExpressionHelper.GetPropertyInfo(x => x.Properties); @@ -84,16 +84,6 @@ namespace Umbraco.Core.Models } } - /// - /// Gets the Url name of the entity - /// - [IgnoreDataMember] - public virtual string UrlName - { - //TODO Needs to implement proper url casing/syntax - get { return Name.ToLower().Replace(" ", "-"); } - } - /// /// Gets or sets the sort order of the content entity /// @@ -140,13 +130,13 @@ namespace Umbraco.Core.Models /// Profile of the user who created this Content /// [DataMember] - public virtual IProfile Creator + public virtual int CreatorId { - get { return _creator; } + get { return _creatorId; } set { - _creator = value; - OnPropertyChanged(CreatorSelector); + _creatorId = value; + OnPropertyChanged(CreatorIdSelector); } } diff --git a/src/Umbraco.Core/Models/ContentExtensions.cs b/src/Umbraco.Core/Models/ContentExtensions.cs index d589b90d74..4f68bd994e 100644 --- a/src/Umbraco.Core/Models/ContentExtensions.cs +++ b/src/Umbraco.Core/Models/ContentExtensions.cs @@ -1,7 +1,8 @@ using System; using System.Linq; -using System.Xml; -using System.Xml.Linq; +using Umbraco.Core.Models.Membership; +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.Repositories; namespace Umbraco.Core.Models { @@ -44,55 +45,21 @@ namespace Umbraco.Core.Models } /// - /// Creates the xml representation for the object + /// Gets the for the Creator of this content. /// - /// to generate xml for - /// Xml representation of the passed in - public static XElement ToXml(this IContent content) + public static IProfile GetCreatorProfile(this IContent content) { - //nodeName should match Casing.SafeAliasWithForcingCheck(content.ContentType.Alias); - var nodeName = content.ContentType.Alias.ToUmbracoAlias(StringAliasCaseType.CamelCase, true); - - var xml = new XElement(nodeName, - new XAttribute("id", content.Id), - new XAttribute("parentID", content.Level > 1 ? content.ParentId : -1), - new XAttribute("level", content.Level), - new XAttribute("writerID", content.Writer.Id), - new XAttribute("creatorID", content.Creator.Id), - new XAttribute("nodeType", content.ContentType.Id), - new XAttribute("template", content.Template ?? string.Empty),//Template name versus Id - note that the template name/alias isn't saved in the db. - new XAttribute("sortOrder", content.SortOrder), - new XAttribute("createDate", content.CreateDate), - new XAttribute("updateDate", content.UpdateDate), - new XAttribute("nodeName", content.Name), - new XAttribute("urlName", content.UrlName),//Format Url ? - new XAttribute("writerName", content.Writer.Name), - new XAttribute("creatorName", content.Creator.Name), - new XAttribute("path", content.Path)); - - foreach (var property in content.Properties) - { - if (property == null) continue; - - xml.Add(property.ToXml()); - - if (property.Alias == "umbracoUrlName" && property.Value.ToString().Trim() != string.Empty) - xml.SetAttributeValue("urlName", property.Value); - } - - return xml; + var repository = RepositoryResolver.ResolveByType(null); + return repository.GetProfileById(content.CreatorId); } /// - /// Creates the xml representation for the object + /// Gets the for the Writer of this content. /// - /// to generate xml for - /// Boolean indicating whether the xml should be generated for preview - /// Xml representation of the passed in - public static XElement ToXml(this IContent content, bool isPreview) + public static IProfile GetWriterProfile(this IContent content) { - //TODO Do a proper implementation of this - return content.ToXml(); + var repository = RepositoryResolver.ResolveByType(null); + return repository.GetProfileById(content.WriterId); } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/ContentType.cs b/src/Umbraco.Core/Models/ContentType.cs index 1fd133bae7..5207cf585d 100644 --- a/src/Umbraco.Core/Models/ContentType.cs +++ b/src/Umbraco.Core/Models/ContentType.cs @@ -25,10 +25,10 @@ namespace Umbraco.Core.Models private static readonly PropertyInfo AllowedTemplatesSelector = ExpressionHelper.GetPropertyInfo>(x => x.AllowedTemplates); /// - /// Gets or sets the Path to default Template + /// Gets or sets the alias of the default Template. /// [DataMember] - public string DefaultTemplate + public string DefaultTemplate//NOTE Use internal extension method to get Id of the Template { get { return _defaultTemplate; } set @@ -41,7 +41,7 @@ namespace Umbraco.Core.Models /// /// Gets or sets a list of aliases for allowed Templates /// - public IEnumerable AllowedTemplates + public IEnumerable AllowedTemplates//NOTE Use internal extension method to get Ids of the Templates { get { return _allowedTemplates; } set diff --git a/src/Umbraco.Core/Models/ContentTypeBase.cs b/src/Umbraco.Core/Models/ContentTypeBase.cs index def56489a5..957cad098c 100644 --- a/src/Umbraco.Core/Models/ContentTypeBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeBase.cs @@ -22,7 +22,7 @@ namespace Umbraco.Core.Models private int _sortOrder; private string _icon; private string _thumbnail; - private IProfile _creator; + private int _creatorId; private bool _allowedAsRoot; private bool _isContainer; private bool _trashed; @@ -45,7 +45,7 @@ namespace Umbraco.Core.Models private static readonly PropertyInfo DescriptionSelector = ExpressionHelper.GetPropertyInfo(x => x.Description); private static readonly PropertyInfo IconSelector = ExpressionHelper.GetPropertyInfo(x => x.Icon); private static readonly PropertyInfo ThumbnailSelector = ExpressionHelper.GetPropertyInfo(x => x.Thumbnail); - private static readonly PropertyInfo CreatorSelector = ExpressionHelper.GetPropertyInfo(x => x.Creator); + private static readonly PropertyInfo CreatorIdSelector = ExpressionHelper.GetPropertyInfo(x => x.CreatorId); private static readonly PropertyInfo AllowedAsRootSelector = ExpressionHelper.GetPropertyInfo(x => x.AllowedAsRoot); private static readonly PropertyInfo IsContainerSelector = ExpressionHelper.GetPropertyInfo(x => x.IsContainer); private static readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo(x => x.Trashed); @@ -185,16 +185,16 @@ namespace Umbraco.Core.Models } /// - /// Gets or sets the Profile of the user who created this ContentType + /// Gets or sets the Id of the user who created this ContentType /// [DataMember] - public virtual IProfile Creator + public virtual int CreatorId { - get { return _creator; } + get { return _creatorId; } set { - _creator = value; - OnPropertyChanged(CreatorSelector); + _creatorId = value; + OnPropertyChanged(CreatorIdSelector); } } diff --git a/src/Umbraco.Core/Models/EntityBase/Entity.cs b/src/Umbraco.Core/Models/EntityBase/Entity.cs index 0a788ee12f..17d320a9d6 100644 --- a/src/Umbraco.Core/Models/EntityBase/Entity.cs +++ b/src/Umbraco.Core/Models/EntityBase/Entity.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.Serialization; diff --git a/src/Umbraco.Core/Models/IContent.cs b/src/Umbraco.Core/Models/IContent.cs index 0c661d6610..f7a7be72ad 100644 --- a/src/Umbraco.Core/Models/IContent.cs +++ b/src/Umbraco.Core/Models/IContent.cs @@ -35,9 +35,9 @@ namespace Umbraco.Core.Models DateTime? ExpireDate { get; set; } /// - /// Profile of the user who wrote the Content + /// Id of the user who wrote/updated the Content /// - IProfile Writer { get; set; } + int WriterId { get; set; } /// /// Gets the ContentType used by this content object diff --git a/src/Umbraco.Core/Models/IContentBase.cs b/src/Umbraco.Core/Models/IContentBase.cs index adcd9f9d9b..384aa325d8 100644 --- a/src/Umbraco.Core/Models/IContentBase.cs +++ b/src/Umbraco.Core/Models/IContentBase.cs @@ -21,11 +21,6 @@ namespace Umbraco.Core.Models /// string Name { get; set; } - /// - /// Gets the Url name of the Content - /// - string UrlName { get; } - /// /// Gets or Sets the Sort Order of the Content /// @@ -42,9 +37,9 @@ namespace Umbraco.Core.Models string Path { get; set; } /// - /// Profile of the user who created the Content + /// Id of the user who created the Content /// - IProfile Creator { get; set; } + int CreatorId { get; set; } /// /// Boolean indicating whether this Content is Trashed or not. diff --git a/src/Umbraco.Core/Models/IContentTypeBase.cs b/src/Umbraco.Core/Models/IContentTypeBase.cs index 805165360e..7d8f3a97ff 100644 --- a/src/Umbraco.Core/Models/IContentTypeBase.cs +++ b/src/Umbraco.Core/Models/IContentTypeBase.cs @@ -56,9 +56,9 @@ namespace Umbraco.Core.Models string Thumbnail { get; set; } /// - /// Gets or Sets the Profile of the User who created the ContentType + /// Gets or Sets the Id of the User who created the ContentType /// - IProfile Creator { get; set; } + int CreatorId { get; set; } /// /// Gets or Sets a boolean indicating whether this ContentType is allowed at the root diff --git a/src/Umbraco.Core/Models/IFile.cs b/src/Umbraco.Core/Models/IFile.cs index 64706e4bef..b0cc96b56d 100644 --- a/src/Umbraco.Core/Models/IFile.cs +++ b/src/Umbraco.Core/Models/IFile.cs @@ -6,7 +6,7 @@ namespace Umbraco.Core.Models /// Defines a File /// /// Used for Scripts, Stylesheets and Templates - public interface IFile : IEntity + public interface IFile : IAggregateRoot { /// /// Gets the Name of the File including extension diff --git a/src/Umbraco.Core/Models/ITemplate.cs b/src/Umbraco.Core/Models/ITemplate.cs new file mode 100644 index 0000000000..2014ac9837 --- /dev/null +++ b/src/Umbraco.Core/Models/ITemplate.cs @@ -0,0 +1,14 @@ +namespace Umbraco.Core.Models +{ + /// + /// Defines a Template File (Masterpage or Mvc View) + /// + public interface ITemplate : IFile + { + /// + /// Returns the that corresponds to the template file + /// + /// + RenderingEngine GetTypeOfRenderingEngine(); + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Membership/Profile.cs b/src/Umbraco.Core/Models/Membership/Profile.cs index 972ce92d48..d77e5c1a6e 100644 --- a/src/Umbraco.Core/Models/Membership/Profile.cs +++ b/src/Umbraco.Core/Models/Membership/Profile.cs @@ -1,10 +1,13 @@ using System; +using System.Runtime.Serialization; namespace Umbraco.Core.Models.Membership { /// /// Represents a Profile which is shared between Members and Users /// + [Serializable] + [DataContract(IsReference = true)] public class Profile : IProfile { /// @@ -22,10 +25,13 @@ namespace Umbraco.Core.Models.Membership Name = name; } + [DataMember] public object Id { get; set; } + [DataMember] public string Name { get; set; } + [IgnoreDataMember] public virtual object ProviderUserKey { get { throw new System.NotImplementedException(); } @@ -38,6 +44,7 @@ namespace Umbraco.Core.Models.Membership /// /// The type of the provider user key. /// + [IgnoreDataMember] internal Type ProviderUserKeyType { get; private set; } /// diff --git a/src/Umbraco.Core/Models/Membership/User.cs b/src/Umbraco.Core/Models/Membership/User.cs index 3018a8b409..36b6330c68 100644 --- a/src/Umbraco.Core/Models/Membership/User.cs +++ b/src/Umbraco.Core/Models/Membership/User.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.Serialization; using Umbraco.Core.Models.EntityBase; namespace Umbraco.Core.Models.Membership @@ -12,10 +13,11 @@ namespace Umbraco.Core.Models.Membership /// Should be internal until a proper user/membership implementation /// is part of the roadmap. /// + [Serializable] + [DataContract(IsReference = true)] internal class User : UserProfile, IUser { private bool _hasIdentity; - private int _id; public User(IUserType userType) { @@ -24,8 +26,10 @@ namespace Umbraco.Core.Models.Membership #region Implementation of IEntity + [IgnoreDataMember] public bool HasIdentity { get { return Id != null || _hasIdentity; } } + [IgnoreDataMember] int IEntity.Id { get @@ -45,33 +49,54 @@ namespace Umbraco.Core.Models.Membership #region Implementation of IMembershipUser + [DataMember] public string Username { get; set; } + [DataMember] public string Email { get; set; } + [DataMember] public string Password { get; set; } + [DataMember] public string PasswordQuestion { get; set; } + [DataMember] public string PasswordAnswer { get; set; } + [DataMember] public string Comments { get; set; } + [DataMember] public bool IsApproved { get; set; } + [DataMember] public bool IsOnline { get; set; } + [DataMember] public bool IsLockedOut { get; set; } + [DataMember] public DateTime CreateDate { get; set; } + [DataMember] public DateTime UpdateDate { get; set; } + [DataMember] public DateTime LastLoginDate { get; set; } + [DataMember] public DateTime LastPasswordChangeDate { get; set; } + [DataMember] public DateTime LastLockoutDate { get; set; } + [DataMember] public object ProfileId { get; set; } + [DataMember] public IEnumerable Groups { get; set; } #endregion #region Implementation of IUser + [DataMember] public string Lanuguage { get; set; } + [DataMember] public string Permissions { get; set; } + [DataMember] public bool DefaultToLiveEditing { get; set; } + [DataMember] public bool NoConsole { get; set; } + [IgnoreDataMember] public IUserType UserType { get diff --git a/src/Umbraco.Core/Models/Membership/UserProfile.cs b/src/Umbraco.Core/Models/Membership/UserProfile.cs index dcb7eb5ddb..b3bb4838e9 100644 --- a/src/Umbraco.Core/Models/Membership/UserProfile.cs +++ b/src/Umbraco.Core/Models/Membership/UserProfile.cs @@ -1,5 +1,7 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; +using System.Runtime.Serialization; namespace Umbraco.Core.Models.Membership { @@ -10,6 +12,8 @@ namespace Umbraco.Core.Models.Membership /// Should be internal until a proper user/membership implementation /// is part of the roadmap. /// + [Serializable] + [DataContract(IsReference = true)] internal class UserProfile : Profile { public UserProfile() @@ -24,6 +28,7 @@ namespace Umbraco.Core.Models.Membership /// /// The session timeout. /// + [DataMember] public int SessionTimeout { get; set; } /// @@ -32,6 +37,7 @@ namespace Umbraco.Core.Models.Membership /// /// The start content id. /// + [DataMember] public int StartContentId { get; set; } /// @@ -40,6 +46,7 @@ namespace Umbraco.Core.Models.Membership /// /// The start media id. /// + [DataMember] public int StartMediaId { get; set; } /// @@ -48,6 +55,7 @@ namespace Umbraco.Core.Models.Membership /// /// The applications. /// + [DataMember] public IEnumerable Applications { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Membership/UserType.cs b/src/Umbraco.Core/Models/Membership/UserType.cs index a466e51d0d..d424fad5e7 100644 --- a/src/Umbraco.Core/Models/Membership/UserType.cs +++ b/src/Umbraco.Core/Models/Membership/UserType.cs @@ -1,4 +1,6 @@ -using Umbraco.Core.Models.EntityBase; +using System; +using System.Runtime.Serialization; +using Umbraco.Core.Models.EntityBase; namespace Umbraco.Core.Models.Membership { @@ -9,10 +11,15 @@ namespace Umbraco.Core.Models.Membership /// Should be internal until a proper user/membership implementation /// is part of the roadmap. /// + [Serializable] + [DataContract(IsReference = true)] internal class UserType : Entity, IUserType { + [DataMember] public string Alias { get; set; } + [DataMember] public string Name { get; set; } + [DataMember] public string Permissions { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Rdbms/TemplateDto.cs b/src/Umbraco.Core/Models/Rdbms/TemplateDto.cs index 84efe570b0..a68704c361 100644 --- a/src/Umbraco.Core/Models/Rdbms/TemplateDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/TemplateDto.cs @@ -14,12 +14,13 @@ namespace Umbraco.Core.Models.Rdbms [Column("nodeId")] [Index(IndexTypes.UniqueNonClustered)] - [ForeignKey(typeof(NodeDto))] + [ForeignKey(typeof(NodeDto), Name = "FK_cmsTemplate_umbracoNode")] public int NodeId { get; set; } [Column("master")] [NullSetting(NullSetting = NullSettings.Null)] - [ForeignKey(typeof(TemplateDto))] + /*[ForeignKey(typeof(TemplateDto), Column = "nodeId")]*/ + [ForeignKey(typeof(NodeDto), Name = "FK_cmsTemplate_cmsTemplate")] public int? Master { get; set; } [Column("alias")] @@ -30,5 +31,8 @@ namespace Umbraco.Core.Models.Rdbms [Column("design")] [SpecialDbType(SpecialDbTypes.NTEXT)] public string Design { get; set; } + + [ResultColumn] + public NodeDto NodeDto { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Template.cs b/src/Umbraco.Core/Models/Template.cs index 68e53a3244..569dfdd103 100644 --- a/src/Umbraco.Core/Models/Template.cs +++ b/src/Umbraco.Core/Models/Template.cs @@ -11,14 +11,52 @@ namespace Umbraco.Core.Models /// [Serializable] [DataContract(IsReference = true)] - public class Template : File + public class Template : File, ITemplate { + private readonly string _alias; + private readonly string _name; + public Template(string path) : base(path) { base.Path = path; } + public Template(string path, string name, string alias) + : base(path) + { + base.Path = path; + _name = name; + _alias = alias; + } + + [DataMember] + internal int CreatorId { get; set; } + + [DataMember] + internal int MasterTemplateId { get; set; } + + [DataMember] + internal string MasterTemplateAlias { get; set; } + + [DataMember] + public override string Alias + { + get + { + return _alias; + } + } + + [DataMember] + public override string Name + { + get + { + return _name; + } + } + /// /// Returns the that corresponds to the template file /// diff --git a/src/Umbraco.Core/Persistence/Factories/ContentFactory.cs b/src/Umbraco.Core/Persistence/Factories/ContentFactory.cs index 18ebe6e2a1..5115c619d5 100644 --- a/src/Umbraco.Core/Persistence/Factories/ContentFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/ContentFactory.cs @@ -1,7 +1,6 @@ using System; using System.Globalization; using Umbraco.Core.Models; -using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories @@ -12,16 +11,12 @@ namespace Umbraco.Core.Persistence.Factories private readonly Guid _nodeObjectTypeId; private readonly int _id; private int _primaryKey; - private readonly IProfile _user; - private readonly IProfile _writer; - public ContentFactory(IContentType contentType, Guid nodeObjectTypeId, int id, IProfile user, IProfile writer) + public ContentFactory(IContentType contentType, Guid nodeObjectTypeId, int id) { _contentType = contentType; _nodeObjectTypeId = nodeObjectTypeId; _id = id; - _user = user; - _writer = writer; } public ContentFactory(Guid nodeObjectTypeId, int id) @@ -43,8 +38,8 @@ namespace Umbraco.Core.Persistence.Factories : _id.ToGuid(), Name = dto.ContentVersionDto.ContentDto.NodeDto.Text, Path = dto.ContentVersionDto.ContentDto.NodeDto.Path, - Creator = _user, - Writer = _writer, + CreatorId = dto.ContentVersionDto.ContentDto.NodeDto.UserId.Value, + WriterId = dto.WriterUserId, Level = dto.ContentVersionDto.ContentDto.NodeDto.Level, ParentId = dto.ContentVersionDto.ContentDto.NodeDto.ParentId, SortOrder = dto.ContentVersionDto.ContentDto.NodeDto.SortOrder, @@ -70,7 +65,7 @@ namespace Umbraco.Core.Persistence.Factories ReleaseDate = entity.ReleaseDate, Text = entity.Name, UpdateDate = entity.UpdateDate, - WriterUserId = entity.Writer.Id.SafeCast(), + WriterUserId = entity.WriterId, VersionId = entity.Version, ContentVersionDto = BuildContentVersionDto(entity) }; @@ -127,7 +122,7 @@ namespace Umbraco.Core.Persistence.Factories Text = entity.Name, Trashed = entity.Trashed, UniqueId = entity.Key, - UserId = entity.Creator.Id.SafeCast() + UserId = entity.CreatorId }; return nodeDto; diff --git a/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs b/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs index ffb0679b9d..87dfae4653 100644 --- a/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs @@ -9,19 +9,12 @@ namespace Umbraco.Core.Persistence.Factories internal class ContentTypeFactory : IEntityFactory { private readonly Guid _nodeObjectType; - private readonly IProfile _creator; public ContentTypeFactory(Guid nodeObjectType) { _nodeObjectType = nodeObjectType; } - public ContentTypeFactory(Guid nodeObjectType, IProfile creator) - { - _nodeObjectType = nodeObjectType; - _creator = creator; - } - #region Implementation of IEntityFactory public IContentType BuildEntity(DocumentTypeDto dto) @@ -42,7 +35,7 @@ namespace Umbraco.Core.Persistence.Factories CreateDate = dto.ContentTypeDto.NodeDto.CreateDate, Path = dto.ContentTypeDto.NodeDto.Path, Level = dto.ContentTypeDto.NodeDto.Level, - Creator = _creator, + CreatorId = dto.ContentTypeDto.NodeDto.UserId.Value, AllowedAsRoot = dto.ContentTypeDto.AllowAtRoot, IsContainer = dto.ContentTypeDto.IsContainer, Trashed = dto.ContentTypeDto.NodeDto.Trashed @@ -90,7 +83,7 @@ namespace Umbraco.Core.Persistence.Factories Text = entity.Name, Trashed = false, UniqueId = entity.Key, - UserId = entity.Creator.Id.SafeCast() + UserId = entity.CreatorId }; return nodeDto; } diff --git a/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs b/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs index 8ae70dfba6..16fe38492b 100644 --- a/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs @@ -1,7 +1,6 @@ using System; using System.Globalization; using Umbraco.Core.Models; -using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories @@ -12,14 +11,12 @@ namespace Umbraco.Core.Persistence.Factories private readonly Guid _nodeObjectTypeId; private readonly int _id; private int _primaryKey; - private readonly IProfile _user; - public MediaFactory(IMediaType contentType, Guid nodeObjectTypeId, int id, IProfile user) + public MediaFactory(IMediaType contentType, Guid nodeObjectTypeId, int id) { _contentType = contentType; _nodeObjectTypeId = nodeObjectTypeId; _id = id; - _user = user; } public MediaFactory(Guid nodeObjectTypeId, int id) @@ -41,7 +38,7 @@ namespace Umbraco.Core.Persistence.Factories : _id.ToGuid(), Name = dto.ContentDto.NodeDto.Text, Path = dto.ContentDto.NodeDto.Path, - Creator = _user, + CreatorId = dto.ContentDto.NodeDto.UserId.Value, Level = dto.ContentDto.NodeDto.Level, ParentId = dto.ContentDto.NodeDto.ParentId, SortOrder = dto.ContentDto.NodeDto.SortOrder, @@ -102,7 +99,7 @@ namespace Umbraco.Core.Persistence.Factories Text = entity.Name, Trashed = entity.Trashed, UniqueId = entity.Key, - UserId = entity.Creator.Id.SafeCast() + UserId = entity.CreatorId }; return nodeDto; diff --git a/src/Umbraco.Core/Persistence/Factories/MediaTypeFactory.cs b/src/Umbraco.Core/Persistence/Factories/MediaTypeFactory.cs index 1b4a989627..b181351b4f 100644 --- a/src/Umbraco.Core/Persistence/Factories/MediaTypeFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MediaTypeFactory.cs @@ -1,7 +1,6 @@ using System; using System.Globalization; using Umbraco.Core.Models; -using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories @@ -9,19 +8,12 @@ namespace Umbraco.Core.Persistence.Factories internal class MediaTypeFactory : IEntityFactory { private readonly Guid _nodeObjectType; - private readonly IProfile _creator; public MediaTypeFactory(Guid nodeObjectType) { _nodeObjectType = nodeObjectType; } - public MediaTypeFactory(Guid nodeObjectType, IProfile creator) - { - _nodeObjectType = nodeObjectType; - _creator = creator; - } - #region Implementation of IEntityFactory public IMediaType BuildEntity(ContentTypeDto dto) @@ -42,7 +34,7 @@ namespace Umbraco.Core.Persistence.Factories CreateDate = dto.NodeDto.CreateDate, Path = dto.NodeDto.Path, Level = dto.NodeDto.Level, - Creator = _creator, + CreatorId = dto.NodeDto.UserId.Value, AllowedAsRoot = dto.AllowAtRoot, IsContainer = dto.IsContainer, Trashed = dto.NodeDto.Trashed @@ -82,7 +74,7 @@ namespace Umbraco.Core.Persistence.Factories Text = entity.Name, Trashed = false, UniqueId = entity.Key, - UserId = entity.Creator.Id.SafeCast() + UserId = entity.CreatorId }; return nodeDto; } diff --git a/src/Umbraco.Core/Persistence/Mappers/ContentMapper.cs b/src/Umbraco.Core/Persistence/Mappers/ContentMapper.cs index e334976c36..4624aef9cf 100644 --- a/src/Umbraco.Core/Persistence/Mappers/ContentMapper.cs +++ b/src/Umbraco.Core/Persistence/Mappers/ContentMapper.cs @@ -36,7 +36,7 @@ namespace Umbraco.Core.Persistence.Mappers CacheMap(src => src.Name, dto => dto.Text); CacheMap(src => src.Trashed, dto => dto.Trashed); CacheMap(src => src.Key, dto => dto.UniqueId); - CacheMap(src => src.Creator, dto => dto.UserId); + CacheMap(src => src.CreatorId, dto => dto.UserId); CacheMap(src => src.ContentTypeId, dto => dto.ContentTypeId); CacheMap(src => src.UpdateDate, dto => dto.VersionDate); CacheMap(src => src.Version, dto => dto.VersionId); diff --git a/src/Umbraco.Core/Persistence/Mappers/ContentTypeMapper.cs b/src/Umbraco.Core/Persistence/Mappers/ContentTypeMapper.cs index b54b0c8af1..bf212e9745 100644 --- a/src/Umbraco.Core/Persistence/Mappers/ContentTypeMapper.cs +++ b/src/Umbraco.Core/Persistence/Mappers/ContentTypeMapper.cs @@ -36,7 +36,7 @@ namespace Umbraco.Core.Persistence.Mappers CacheMap(src => src.Name, dto => dto.Text); CacheMap(src => src.Trashed, dto => dto.Trashed); CacheMap(src => src.Key, dto => dto.UniqueId); - CacheMap(src => src.Creator, dto => dto.UserId); + CacheMap(src => src.CreatorId, dto => dto.UserId); CacheMap(src => src.Alias, dto => dto.Alias); CacheMap(src => src.AllowedAsRoot, dto => dto.AllowAtRoot); CacheMap(src => src.Description, dto => dto.Description); diff --git a/src/Umbraco.Core/Persistence/Mappers/MediaMapper.cs b/src/Umbraco.Core/Persistence/Mappers/MediaMapper.cs index bb914f2970..a6d3f29ac6 100644 --- a/src/Umbraco.Core/Persistence/Mappers/MediaMapper.cs +++ b/src/Umbraco.Core/Persistence/Mappers/MediaMapper.cs @@ -35,7 +35,7 @@ namespace Umbraco.Core.Persistence.Mappers CacheMap(src => src.Name, dto => dto.Text); CacheMap(src => src.Trashed, dto => dto.Trashed); CacheMap(src => src.Key, dto => dto.UniqueId); - CacheMap(src => src.Creator, dto => dto.UserId); + CacheMap(src => src.CreatorId, dto => dto.UserId); CacheMap(src => src.ContentTypeId, dto => dto.ContentTypeId); CacheMap(src => src.UpdateDate, dto => dto.VersionDate); CacheMap(src => src.Version, dto => dto.VersionId); diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs index c956d4fc1a..8f1f4a9c3b 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs @@ -4,7 +4,6 @@ using System.Globalization; using System.Linq; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; -using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Caching; using Umbraco.Core.Persistence.Factories; @@ -19,20 +18,17 @@ namespace Umbraco.Core.Persistence.Repositories internal class ContentRepository : PetaPocoRepositoryBase, IContentRepository { private readonly IContentTypeRepository _contentTypeRepository; - private readonly IUserRepository _userRepository; - public ContentRepository(IUnitOfWork work, IContentTypeRepository contentTypeRepository, IUserRepository userRepository) + public ContentRepository(IUnitOfWork work, IContentTypeRepository contentTypeRepository) : base(work) { _contentTypeRepository = contentTypeRepository; - _userRepository = userRepository; } - public ContentRepository(IUnitOfWork work, IRepositoryCacheProvider cache, IContentTypeRepository contentTypeRepository, IUserRepository userRepository) + public ContentRepository(IUnitOfWork work, IRepositoryCacheProvider cache, IContentTypeRepository contentTypeRepository) : base(work, cache) { _contentTypeRepository = contentTypeRepository; - _userRepository = userRepository; } #region Overrides of RepositoryBase @@ -50,10 +46,7 @@ namespace Umbraco.Core.Persistence.Repositories var contentType = _contentTypeRepository.Get(dto.ContentVersionDto.ContentDto.ContentTypeId); - var user = _userRepository.GetProfileById(dto.ContentVersionDto.ContentDto.NodeDto.UserId.Value); - var writer = _userRepository.GetProfileById(dto.WriterUserId); - - var factory = new ContentFactory(contentType, NodeObjectTypeId, id, user, writer); + var factory = new ContentFactory(contentType, NodeObjectTypeId, id); var content = factory.BuildEntity(dto); content.Properties = GetPropertyCollection(id, dto.ContentVersionDto.VersionId, contentType); @@ -299,13 +292,7 @@ namespace Umbraco.Core.Persistence.Repositories var contentType = _contentTypeRepository.Get(dto.ContentVersionDto.ContentDto.ContentTypeId); - //NOTE: Should eventually be moved to a UserRepository like is the case with ContentType - var userDto = Database.FirstOrDefault("WHERE id = @Id", new { Id = dto.ContentVersionDto.ContentDto.NodeDto.UserId }); - var user = new Profile(userDto.Id, userDto.UserName); - var writerDto = Database.FirstOrDefault("WHERE id = @Id", new { Id = dto.WriterUserId }); - var writer = new Profile(writerDto.Id, writerDto.UserName); - - var factory = new ContentFactory(contentType, NodeObjectTypeId, id, user, writer); + var factory = new ContentFactory(contentType, NodeObjectTypeId, id); var content = factory.BuildEntity(dto); content.Properties = GetPropertyCollection(id, versionId, contentType); diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs index 286de164f9..2250829f2c 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs @@ -42,9 +42,7 @@ namespace Umbraco.Core.Persistence.Repositories if (dto == null) return null; - var creator = _userRepository.GetProfileById(dto.ContentTypeDto.NodeDto.UserId.Value); - - var factory = new ContentTypeFactory(NodeObjectTypeId, creator); + var factory = new ContentTypeFactory(NodeObjectTypeId); var contentType = factory.BuildEntity(dto); contentType.AllowedContentTypes = GetAllowedContentTypeIds(id); diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITemplateFileOnlyRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITemplateFileOnlyRepository.cs new file mode 100644 index 0000000000..711c09fbd1 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITemplateFileOnlyRepository.cs @@ -0,0 +1,8 @@ +using Umbraco.Core.Models; + +namespace Umbraco.Core.Persistence.Repositories +{ + public interface ITemplateFileOnlyRepository : IRepository + { + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITemplateRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITemplateRepository.cs index ab3a1def12..c51462af3c 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITemplateRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITemplateRepository.cs @@ -1,8 +1,9 @@ -using Umbraco.Core.Models; +using Umbraco.Core.Models; namespace Umbraco.Core.Persistence.Repositories { - public interface ITemplateRepository : IRepository + public interface ITemplateRepository : IRepositoryQueryable { + } } \ 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 5831194279..696415f3db 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs @@ -50,9 +50,7 @@ namespace Umbraco.Core.Persistence.Repositories var contentType = _mediaTypeRepository.Get(dto.ContentDto.ContentTypeId); - var user = _userRepository.GetProfileById(dto.ContentDto.NodeDto.UserId.Value); - - var factory = new MediaFactory(contentType, NodeObjectTypeId, id, user); + var factory = new MediaFactory(contentType, NodeObjectTypeId, id); var content = factory.BuildEntity(dto); content.Properties = GetPropertyCollection(id, dto.VersionId, contentType); diff --git a/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs index a9e26e62d3..4eaafbc797 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs @@ -42,9 +42,7 @@ namespace Umbraco.Core.Persistence.Repositories if (dto == null) return null; - var creator = _userRepository.GetProfileById(dto.NodeDto.UserId.Value); - - var factory = new MediaTypeFactory(NodeObjectTypeId, creator); + var factory = new MediaTypeFactory(NodeObjectTypeId); var contentType = factory.BuildEntity(dto); contentType.AllowedContentTypes = GetAllowedContentTypeIds(id); diff --git a/src/Umbraco.Core/Persistence/Repositories/TemplateFileOnlyFileOnlyRepository.cs b/src/Umbraco.Core/Persistence/Repositories/TemplateFileOnlyFileOnlyRepository.cs new file mode 100644 index 0000000000..183fbf9e3d --- /dev/null +++ b/src/Umbraco.Core/Persistence/Repositories/TemplateFileOnlyFileOnlyRepository.cs @@ -0,0 +1,171 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using Umbraco.Core.Configuration; +using Umbraco.Core.IO; +using Umbraco.Core.Models; +using Umbraco.Core.Persistence.UnitOfWork; + +namespace Umbraco.Core.Persistence.Repositories +{ + /// + /// Represents the Template Repository + /// + internal class TemplateFileOnlyFileOnlyRepository : FileRepository, ITemplateFileOnlyRepository + { + private readonly IFileSystem _viewsFileSystem; + + public TemplateFileOnlyFileOnlyRepository(IUnitOfWork work) + : base(work, FileSystemProviderManager.Current.GetFileSystemProvider("masterpages")) + { + _viewsFileSystem = FileSystemProviderManager.Current.GetFileSystemProvider("views"); + } + + #region Overrides of FileRepository + + public override Template Get(string id) + { + string masterpageName = string.Concat(id, ".master"); + string viewName = string.Concat(id, ".cshtml"); + if (!FileSystem.FileExists(masterpageName) && !_viewsFileSystem.FileExists(viewName)) + { + throw new Exception(string.Format("The file with alias: '{0}' was not found", id)); + } + + string content = string.Empty; + string path = string.Empty; + DateTime created = new DateTime(); + DateTime updated = new DateTime(); + string name = string.Empty; + + if (FileSystem.FileExists(masterpageName)) + { + using (var stream = FileSystem.OpenFile(masterpageName)) + { + byte[] bytes = new byte[stream.Length]; + stream.Position = 0; + stream.Read(bytes, 0, (int) stream.Length); + content = Encoding.UTF8.GetString(bytes); + } + + path = FileSystem.GetRelativePath(masterpageName); + created = FileSystem.GetCreated(path).UtcDateTime; + updated = FileSystem.GetLastModified(path).UtcDateTime; + name = new FileInfo(path).Name; + } + else + { + using (var stream = _viewsFileSystem.OpenFile(viewName)) + { + byte[] bytes = new byte[stream.Length]; + stream.Position = 0; + stream.Read(bytes, 0, (int) stream.Length); + content = Encoding.UTF8.GetString(bytes); + } + + path = _viewsFileSystem.GetRelativePath(viewName); + created = FileSystem.GetCreated(path).UtcDateTime; + updated = FileSystem.GetLastModified(path).UtcDateTime; + name = new FileInfo(path).Name; + } + + var template = new Template(path) + { + Content = content, + Key = name.EncodeAsGuid(), + CreateDate = created, + UpdateDate = updated + }; + + template.ResetDirtyProperties(); + + return template; + } + + public override IEnumerable