diff --git a/src/Umbraco.Core/Models/Content.cs b/src/Umbraco.Core/Models/Content.cs index 9b95fe5475..2238260611 100644 --- a/src/Umbraco.Core/Models/Content.cs +++ b/src/Umbraco.Core/Models/Content.cs @@ -95,13 +95,7 @@ namespace Umbraco.Core.Models [DataMember] public virtual ITemplate Template { - get - { - if (_template == null) - return _contentType.DefaultTemplate; - - return _template; - } + get { return _template; } set { SetPropertyValueAndDetectChanges(o => diff --git a/src/Umbraco.Core/Persistence/Factories/TemplateFactory.cs b/src/Umbraco.Core/Persistence/Factories/TemplateFactory.cs index 52499bee7d..d1742dc030 100644 --- a/src/Umbraco.Core/Persistence/Factories/TemplateFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/TemplateFactory.cs @@ -43,10 +43,7 @@ namespace Umbraco.Core.Persistence.Factories Path = dto.NodeDto.Path }; - if (childDefinitions.Any(x => x.ParentId == dto.NodeId)) - { - template.IsMasterTemplate = true; - } + template.IsMasterTemplate = childDefinitions.Any(x => x.ParentId == dto.NodeId); if(dto.NodeDto.ParentId > 0) template.MasterTemplateId = new Lazy(() => dto.NodeDto.ParentId); diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs index bb474a3440..61e94568e3 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs @@ -340,6 +340,12 @@ namespace Umbraco.Core.Persistence.Repositories { ((Content)entity).AddingEntity(); + //ensure the default template is assigned + if (entity.Template == null) + { + entity.Template = entity.ContentType.DefaultTemplate; + } + //Ensure unique name on the same level entity.Name = EnsureUniqueNodeName(entity.ParentId, entity.Name); @@ -855,7 +861,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// Private method to create a content object from a DocumentDto, which is used by Get and GetByVersion. /// - /// + /// /// /// /// @@ -873,6 +879,11 @@ namespace Umbraco.Core.Persistence.Repositories { content.Template = template ?? _templateRepository.Get(dto.TemplateId.Value); } + else + { + //ensure there isn't one set. + content.Template = null; + } content.Properties = propCollection; diff --git a/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs b/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs index e83ca6b40e..0c38d61223 100644 --- a/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs @@ -264,7 +264,11 @@ namespace Umbraco.Core.Persistence.Repositories Database.Update(dto.NodeDto); Database.Update(dto); - + + //re-update if this is a master template, since it could have changed! + var axisDefs = GetAxisDefinitions(dto); + template.IsMasterTemplate = axisDefs.Any(x => x.ParentId == dto.NodeId); + //now do the file work if (DetermineTemplateRenderingEngine(entity) == RenderingEngine.Mvc) @@ -326,14 +330,7 @@ namespace Umbraco.Core.Persistence.Repositories { var masterpageName = string.Concat(entity.Alias, ".master"); _masterpagesFileSystem.DeleteFile(masterpageName); - } - - //It is important that we clear ALL template cache, this is because templates have a couple of readonly - // flags that will get cached which will become stale if other templates change: - // * MasterTemplateAlias - // * IsMasterTemplate - - RuntimeCache.ClearCacheObjectTypes(); + } } #endregion diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs index 089e9ebaf9..146ec49a50 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs @@ -44,7 +44,13 @@ namespace Umbraco.Tests.Persistence.Repositories private ContentRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) { - var templateRepository = new TemplateRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, Mock.Of(), Mock.Of(), Mock.Of()); + TemplateRepository tr; + return CreateRepository(unitOfWork, out contentTypeRepository, out tr); + } + + private ContentRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository, out TemplateRepository templateRepository) + { + templateRepository = new TemplateRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, Mock.Of(), Mock.Of(), Mock.Of()); var tagRepository = new TagRepository(unitOfWork, CacheHelper, Logger, SqlSyntax); contentTypeRepository = new ContentTypeRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, templateRepository); var repository = new ContentRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, contentTypeRepository, templateRepository, tagRepository, Mock.Of()); @@ -217,6 +223,37 @@ namespace Umbraco.Tests.Persistence.Repositories // Assert Assert.That(contentType.HasIdentity, Is.True); Assert.That(textpage.HasIdentity, Is.True); + + } + } + + [Test] + public void Can_Perform_Add_With_Default_Template() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + ContentTypeRepository contentTypeRepository; + TemplateRepository templateRepository; + using (var repository = CreateRepository(unitOfWork, out contentTypeRepository, out templateRepository)) + { + var template = new Template("hello", "hello"); + templateRepository.AddOrUpdate(template); + unitOfWork.Commit(); + + ContentType contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage2", "Textpage"); + contentType.SetDefaultTemplate(template); + Content textpage = MockedContent.CreateSimpleContent(contentType); + + // Act + + contentTypeRepository.AddOrUpdate(contentType); + repository.AddOrUpdate(textpage); + unitOfWork.Commit(); + + // Assert + Assert.That(textpage.Template, Is.Not.Null); + Assert.That(textpage.Template, Is.EqualTo(contentType.DefaultTemplate)); } } @@ -327,6 +364,28 @@ namespace Umbraco.Tests.Persistence.Repositories } + [Test] + public void Can_Update_With_Null_Template() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + ContentTypeRepository contentTypeRepository; + using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) + { + // Act + var content = repository.Get(NodeDto.NodeIdSeed + 2); + content.Template = null; + repository.AddOrUpdate(content); + unitOfWork.Commit(); + var updatedContent = repository.Get(NodeDto.NodeIdSeed + 2); + + // Assert + Assert.That(updatedContent.Template, Is.Null); + } + + } + [Test] public void Can_Perform_Delete_On_ContentRepository() { diff --git a/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs b/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs index ed67c24fe1..22bce3d5bf 100644 --- a/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs @@ -47,6 +47,14 @@ namespace Umbraco.Web.Cache public override void Remove(int id) { RemoveFromCache(id); + + //During removal we need to clear the runtime cache for templates, content and content type instances!!! + // all three of these types are referenced by templates, and the cache needs to be cleared on every server, + // otherwise things like looking up content type's after a template is removed is still going to show that + // it has an associated template. + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); + base.Remove(id); } @@ -57,8 +65,7 @@ namespace Umbraco.Web.Cache ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem( string.Format("{0}{1}", CacheKeys.TemplateFrontEndCacheKey, id)); - //need to clear the runtime cache for template instances - //NOTE: This is temp until we implement the correct ApplicationCache and then we can remove the RuntimeCache, etc... + //need to clear the runtime cache for templates ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes(); } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/installedPackage.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/installedPackage.aspx.cs index 6146590293..2473a4cb5b 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/installedPackage.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/installedPackage.aspx.cs @@ -397,9 +397,11 @@ namespace umbraco.presentation.developer.packages if (int.TryParse(li.Value, out nId)) { - var s = new Template(nId); - s.RemoveAllReferences(); - s.delete(); + var found = ApplicationContext.Services.FileService.GetTemplate(nId); + if (found != null) + { + ApplicationContext.Services.FileService.DeleteTemplate(found.Alias, UmbracoUser.Id); + } _pack.Data.Templates.Remove(nId.ToString()); } }