Merge
This commit is contained in:
@@ -72,6 +72,12 @@ namespace Umbraco.Core.Models
|
||||
/// <param name="template">Default <see cref="ITemplate"/></param>
|
||||
public void SetDefaultTemplate(ITemplate template)
|
||||
{
|
||||
if (template == null)
|
||||
{
|
||||
DefaultTemplateId = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
DefaultTemplateId = template.Id;
|
||||
if(_allowedTemplates.Any(x => x != null && x.Id == template.Id) == false)
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Caching;
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Caching
|
||||
@@ -23,9 +24,10 @@ namespace Umbraco.Core.Persistence.Caching
|
||||
|
||||
#endregion
|
||||
|
||||
private readonly ObjectCache _memoryCache = new MemoryCache("in-memory");
|
||||
//TODO Save this in cache as well, so its not limited to a single server usage
|
||||
private ConcurrentDictionary<string, string> _keyTracker = new ConcurrentDictionary<string, string>();
|
||||
private ObjectCache _memoryCache = new MemoryCache("in-memory");
|
||||
private static readonly ReaderWriterLockSlim ClearLock = new ReaderWriterLockSlim();
|
||||
|
||||
public IEntity GetById(Type type, Guid id)
|
||||
{
|
||||
@@ -77,6 +79,16 @@ namespace Umbraco.Core.Persistence.Caching
|
||||
_keyTracker.TryRemove(key, out throwaway);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
using (new ReadLock(ClearLock))
|
||||
{
|
||||
_keyTracker.Clear();
|
||||
_memoryCache.DisposeIfDisposable();
|
||||
_memoryCache = new MemoryCache("in-memory");
|
||||
}
|
||||
}
|
||||
|
||||
private string GetCompositeId(Type type, Guid id)
|
||||
{
|
||||
return string.Format("{0}-{1}", type.Name, id.ToString());
|
||||
|
||||
@@ -365,6 +365,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
foreach (var property in entity.Properties)
|
||||
{
|
||||
if(keyDictionary.ContainsKey(property.PropertyTypeId) == false) continue;
|
||||
|
||||
property.Id = keyDictionary[property.PropertyTypeId];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,11 +168,19 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
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);
|
||||
var dbPropertyTypes = Database.Fetch<PropertyTypeDto>("WHERE contentTypeId = @Id", new { Id = entity.Id });
|
||||
var dbPropertyTypeAlias = dbPropertyTypes.Select(x => x.Alias.ToLowerInvariant());
|
||||
var entityPropertyTypes = entity.PropertyTypes.Select(x => x.Alias.ToLowerInvariant());
|
||||
var aliases = dbPropertyTypeAlias.Except(entityPropertyTypes);
|
||||
foreach (var alias in aliases)
|
||||
{
|
||||
//Before a PropertyType can be deleted, all Properties based on that PropertyType should be deleted.
|
||||
var propertyType = dbPropertyTypes.FirstOrDefault(x => x.Alias.ToLowerInvariant() == alias);
|
||||
if (propertyType != null)
|
||||
{
|
||||
Database.Delete<PropertyDataDto>("WHERE propertytypeid = @Id", new { Id = propertyType.Id });
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -270,6 +270,128 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
Assert.That(updated.AllowedContentTypes.Any(x => x.Alias == simpleSubpageContentType.Alias), Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Verify_Removal_Of_Used_PropertyType_From_ContentType()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
var repository = RepositoryResolver.Current.ResolveByType<IContentTypeRepository>(unitOfWork);
|
||||
var contentRepository = RepositoryResolver.Current.ResolveByType<IContentRepository>(unitOfWork);
|
||||
var contentType = repository.Get(1046);
|
||||
|
||||
var subpage = MockedContent.CreateTextpageContent(contentType, "Text Page 1", contentType.Id);
|
||||
contentRepository.AddOrUpdate(subpage);
|
||||
unitOfWork.Commit();
|
||||
|
||||
// Act
|
||||
contentType.RemovePropertyType("keywords");
|
||||
repository.AddOrUpdate(contentType);
|
||||
unitOfWork.Commit();
|
||||
|
||||
// Assert
|
||||
Assert.That(contentType.PropertyTypes.Count(), Is.EqualTo(3));
|
||||
Assert.That(contentType.PropertyTypes.Any(x => x.Alias == "keywords"), Is.False);
|
||||
Assert.That(subpage.Properties.First(x => x.Alias == "metaDescription").Value, Is.EqualTo("This is the meta description for a textpage"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Verify_Addition_Of_PropertyType_After_ContentType_Is_Used()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
var repository = RepositoryResolver.Current.ResolveByType<IContentTypeRepository>(unitOfWork);
|
||||
var contentRepository = RepositoryResolver.Current.ResolveByType<IContentRepository>(unitOfWork);
|
||||
var contentType = repository.Get(1046);
|
||||
|
||||
var subpage = MockedContent.CreateTextpageContent(contentType, "Text Page 1", contentType.Id);
|
||||
contentRepository.AddOrUpdate(subpage);
|
||||
unitOfWork.Commit();
|
||||
|
||||
// Act
|
||||
var propertyGroup = contentType.PropertyGroups.First(x => x.Name == "Meta");
|
||||
propertyGroup.PropertyTypes.Add(new PropertyType(new Guid(), DataTypeDatabaseType.Ntext) { Alias = "metaAuthor", Name = "Meta Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 });
|
||||
repository.AddOrUpdate(contentType);
|
||||
unitOfWork.Commit();
|
||||
|
||||
// Assert
|
||||
Assert.That(contentType.PropertyTypes.Count(), Is.EqualTo(5));
|
||||
Assert.That(contentType.PropertyTypes.Any(x => x.Alias == "metaAuthor"), Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Verify_Usage_Of_New_PropertyType_On_Content()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
var repository = RepositoryResolver.Current.ResolveByType<IContentTypeRepository>(unitOfWork);
|
||||
var contentRepository = RepositoryResolver.Current.ResolveByType<IContentRepository>(unitOfWork);
|
||||
var contentType = repository.Get(1046);
|
||||
|
||||
var subpage = MockedContent.CreateTextpageContent(contentType, "Text Page 1", contentType.Id);
|
||||
contentRepository.AddOrUpdate(subpage);
|
||||
unitOfWork.Commit();
|
||||
|
||||
var propertyGroup = contentType.PropertyGroups.First(x => x.Name == "Meta");
|
||||
propertyGroup.PropertyTypes.Add(new PropertyType(new Guid(), DataTypeDatabaseType.Ntext) { Alias = "metaAuthor", Name = "Meta Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 });
|
||||
repository.AddOrUpdate(contentType);
|
||||
unitOfWork.Commit();
|
||||
|
||||
// Act
|
||||
var content = contentRepository.Get(subpage.Id);
|
||||
content.SetValue("metaAuthor", "John Doe");
|
||||
contentRepository.AddOrUpdate(content);
|
||||
unitOfWork.Commit();
|
||||
|
||||
//Assert
|
||||
var updated = contentRepository.Get(subpage.Id);
|
||||
Assert.That(updated.GetValue("metaAuthor").ToString(), Is.EqualTo("John Doe"));
|
||||
Assert.That(contentType.PropertyTypes.Count(), Is.EqualTo(5));
|
||||
Assert.That(contentType.PropertyTypes.Any(x => x.Alias == "metaAuthor"), Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void
|
||||
Can_Verify_That_A_Combination_Of_Adding_And_Deleting_PropertyTypes_Doesnt_Cause_Issues_For_Content_And_ContentType
|
||||
()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
var repository = RepositoryResolver.Current.ResolveByType<IContentTypeRepository>(unitOfWork);
|
||||
var contentRepository = RepositoryResolver.Current.ResolveByType<IContentRepository>(unitOfWork);
|
||||
var contentType = repository.Get(1046);
|
||||
|
||||
var subpage = MockedContent.CreateTextpageContent(contentType, "Text Page 1", contentType.Id);
|
||||
contentRepository.AddOrUpdate(subpage);
|
||||
unitOfWork.Commit();
|
||||
|
||||
//Remove PropertyType
|
||||
contentType.RemovePropertyType("keywords");
|
||||
//Add PropertyType
|
||||
var propertyGroup = contentType.PropertyGroups.First(x => x.Name == "Meta");
|
||||
propertyGroup.PropertyTypes.Add(new PropertyType(new Guid(), DataTypeDatabaseType.Ntext) { Alias = "metaAuthor", Name = "Meta Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 });
|
||||
repository.AddOrUpdate(contentType);
|
||||
unitOfWork.Commit();
|
||||
|
||||
// Act
|
||||
var content = contentRepository.Get(subpage.Id);
|
||||
content.SetValue("metaAuthor", "John Doe");
|
||||
contentRepository.AddOrUpdate(content);
|
||||
unitOfWork.Commit();
|
||||
|
||||
//Assert
|
||||
var updated = contentRepository.Get(subpage.Id);
|
||||
Assert.That(updated.GetValue("metaAuthor").ToString(), Is.EqualTo("John Doe"));
|
||||
Assert.That(updated.Properties.First(x => x.Alias == "metaDescription").Value, Is.EqualTo("This is the meta description for a textpage"));
|
||||
|
||||
Assert.That(contentType.PropertyTypes.Count(), Is.EqualTo(4));
|
||||
Assert.That(contentType.PropertyTypes.Any(x => x.Alias == "metaAuthor"), Is.True);
|
||||
Assert.That(contentType.PropertyTypes.Any(x => x.Alias == "keywords"), Is.False);
|
||||
}
|
||||
|
||||
public void CreateTestData()
|
||||
{
|
||||
//Create and Save ContentType "umbTextpage" -> 1045
|
||||
|
||||
@@ -128,6 +128,8 @@ namespace umbraco.settings
|
||||
else
|
||||
dt.RemoveDefaultTemplate();
|
||||
|
||||
dt.Save();
|
||||
|
||||
bindTemplates();
|
||||
}
|
||||
else
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Persistence.Caching;
|
||||
using umbraco.BusinessLogic;
|
||||
using umbraco.cms.businesslogic.cache;
|
||||
using umbraco.cms.businesslogic.datatype;
|
||||
@@ -461,10 +462,10 @@ namespace umbraco.cms.businesslogic.propertytype
|
||||
// clear cache in contentype
|
||||
Cache.ClearCacheItem("ContentType_PropertyTypes_Content:" + _contenttypeid);
|
||||
|
||||
// clear cache in tab
|
||||
// zb-00040 #29889 : clear the right cache! t.ContentType is the ctype which _defines_ the tab, not the current one.
|
||||
// foreach (ContentType.TabI t in new ContentType(ContentTypeId).getVirtualTabs)
|
||||
// ContentType.FlushTabCache(t.Id, ContentTypeId);
|
||||
//Ensure that DocumentTypes are reloaded from db by clearing cache - this similar to the Save method on DocumentType.
|
||||
//NOTE Would be nice if we could clear cache by type instead of emptying the entire cache.
|
||||
InMemoryCacheProvider.Current.Clear();
|
||||
RuntimeCacheProvider.Current.Clear();
|
||||
}
|
||||
|
||||
public static PropertyType GetPropertyType(int id)
|
||||
|
||||
@@ -420,14 +420,11 @@ namespace umbraco.cms.businesslogic.web
|
||||
return doc;
|
||||
}
|
||||
|
||||
[Obsolete("Deprecated, Use RemoveTemplate() on Umbraco.Core.Models.ContentType", false)]
|
||||
[Obsolete("Deprecated, Use SetDefaultTemplate(null) on Umbraco.Core.Models.ContentType", false)]
|
||||
public void RemoveDefaultTemplate()
|
||||
{
|
||||
_defaultTemplate = 0;
|
||||
|
||||
var template = _contentType.DefaultTemplate;
|
||||
if(template != null)
|
||||
_contentType.RemoveTemplate(template);
|
||||
_contentType.SetDefaultTemplate(null);
|
||||
}
|
||||
|
||||
public bool HasTemplate()
|
||||
@@ -457,8 +454,10 @@ namespace umbraco.cms.businesslogic.web
|
||||
|
||||
ApplicationContext.Current.Services.ContentTypeService.Save(_contentType);
|
||||
|
||||
//Ensure that DocumentTypes are reloaded from db by clearing cache
|
||||
//Ensure that DocumentTypes are reloaded from db by clearing cache.
|
||||
//NOTE Would be nice if we could clear cache by type instead of emptying the entire cache.
|
||||
InMemoryCacheProvider.Current.Clear();
|
||||
RuntimeCacheProvider.Current.Clear();//Runtime cache is used for Content, so we clear that as well
|
||||
|
||||
base.Save();
|
||||
FireAfterSave(e);
|
||||
|
||||
Reference in New Issue
Block a user