Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a8d7a1d01d | |||
| e62597521e | |||
| fa91321299 | |||
| 2d81691407 | |||
| 21f08ca491 | |||
| e202f21934 | |||
| 2936ff0bf9 | |||
| 8e4e575276 | |||
| 84752babc8 | |||
| 60a1116acd | |||
| a480d7bbe6 | |||
| 7316c5462a | |||
| 2a9960afb3 | |||
| ed899ec73d | |||
| 8f26f9385d | |||
| a446cc224d | |||
| 07f9a9700d | |||
| 7e7acd0049 | |||
| 57985c26a2 | |||
| 504c1f7254 | |||
| 52ad36a6c2 | |||
| 01670e0832 | |||
| 99c96bce86 | |||
| da2bc6764b | |||
| d11a377f0f | |||
| d445f7cb0d | |||
| 899d325ca1 | |||
| f1107b7a91 | |||
| a3f171e7b3 |
@@ -1,2 +1,2 @@
|
||||
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
|
||||
7.2.0
|
||||
7.2.1
|
||||
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("7.2.0");
|
||||
private static readonly Version Version = new Version("7.2.1");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
private int _defaultTemplate;
|
||||
private IEnumerable<ITemplate> _allowedTemplates;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constuctor for creating a ContentType with the parent's id.
|
||||
/// </summary>
|
||||
@@ -31,9 +31,10 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
/// <remarks>Use this to ensure inheritance from parent.</remarks>
|
||||
/// <param name="parent"></param>
|
||||
public ContentType(IContentType parent) : this(parent, null)
|
||||
{
|
||||
}
|
||||
[Obsolete("This method is obsolete, use ContentType(IContentType parent, string alias) instead.", false)]
|
||||
public ContentType(IContentType parent) : this(parent, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constuctor for creating a ContentType with the parent as an inherited type.
|
||||
@@ -49,7 +50,7 @@ namespace Umbraco.Core.Models
|
||||
|
||||
private static readonly PropertyInfo DefaultTemplateSelector = ExpressionHelper.GetPropertyInfo<ContentType, int>(x => x.DefaultTemplateId);
|
||||
private static readonly PropertyInfo AllowedTemplatesSelector = ExpressionHelper.GetPropertyInfo<ContentType, IEnumerable<ITemplate>>(x => x.AllowedTemplates);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the alias of the default Template.
|
||||
/// </summary>
|
||||
@@ -106,7 +107,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
|
||||
DefaultTemplateId = template.Id;
|
||||
if(_allowedTemplates.Any(x => x != null && x.Id == template.Id) == false)
|
||||
if (_allowedTemplates.Any(x => x != null && x.Id == template.Id) == false)
|
||||
{
|
||||
var templates = AllowedTemplates.ToList();
|
||||
templates.Add(template);
|
||||
@@ -140,7 +141,7 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
base.AddingEntity();
|
||||
|
||||
if(Key == Guid.Empty)
|
||||
if (Key == Guid.Empty)
|
||||
Key = Guid.NewGuid();
|
||||
}
|
||||
|
||||
@@ -151,7 +152,7 @@ namespace Umbraco.Core.Models
|
||||
/// <returns></returns>
|
||||
[Obsolete("Use DeepCloneWithResetIdentities instead")]
|
||||
public IContentType Clone(string alias)
|
||||
{
|
||||
{
|
||||
return DeepCloneWithResetIdentities(alias);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
@@ -15,6 +16,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
[DebuggerDisplay("Id: {Id}, Name: {Name}, Alias: {Alias}")]
|
||||
public abstract class ContentTypeBase : Entity, IContentTypeBase
|
||||
{
|
||||
private Lazy<int> _parentId;
|
||||
@@ -497,7 +499,6 @@ namespace Umbraco.Core.Models
|
||||
/// <param name="propertyTypeAlias">Alias of the <see cref="PropertyType"/> to remove</param>
|
||||
public void RemovePropertyType(string propertyTypeAlias)
|
||||
{
|
||||
|
||||
//check if the property exist in one of our collections
|
||||
if (PropertyGroups.Any(group => group.PropertyTypes.Any(pt => pt.Alias == propertyTypeAlias))
|
||||
|| _propertyTypes.Any(x => x.Alias == propertyTypeAlias))
|
||||
@@ -524,6 +525,7 @@ namespace Umbraco.Core.Models
|
||||
public void RemovePropertyGroup(string propertyGroupName)
|
||||
{
|
||||
PropertyGroups.RemoveItem(propertyGroupName);
|
||||
OnPropertyChanged(PropertyGroupCollectionSelector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -20,7 +20,6 @@ namespace Umbraco.Core.Models
|
||||
private string _email;
|
||||
private string _rawPasswordValue;
|
||||
private object _providerUserKey;
|
||||
private Type _userTypeKey;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for creating an empty Member object
|
||||
@@ -114,7 +113,6 @@ namespace Umbraco.Core.Models
|
||||
private static readonly PropertyInfo EmailSelector = ExpressionHelper.GetPropertyInfo<Member, string>(x => x.Email);
|
||||
private static readonly PropertyInfo PasswordSelector = ExpressionHelper.GetPropertyInfo<Member, string>(x => x.RawPasswordValue);
|
||||
private static readonly PropertyInfo ProviderUserKeySelector = ExpressionHelper.GetPropertyInfo<Member, object>(x => x.ProviderUserKey);
|
||||
private static readonly PropertyInfo UserTypeKeySelector = ExpressionHelper.GetPropertyInfo<Member, Type>(x => x.ProviderUserKeyType);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Username
|
||||
@@ -502,38 +500,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the provider user key.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The type of the provider user key.
|
||||
/// </value>
|
||||
[IgnoreDataMember]
|
||||
internal Type ProviderUserKeyType
|
||||
{
|
||||
get
|
||||
{
|
||||
return _userTypeKey;
|
||||
}
|
||||
private set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_userTypeKey = value;
|
||||
return _userTypeKey;
|
||||
}, _userTypeKey, UserTypeKeySelector);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the type of the provider user key.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
internal void SetProviderUserKeyType(Type type)
|
||||
{
|
||||
ProviderUserKeyType = type;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Method to call when Entity is being saved
|
||||
/// </summary>
|
||||
|
||||
@@ -7,9 +7,9 @@ namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
internal static class MembershipUserExtensions
|
||||
{
|
||||
internal static UmbracoMembershipMember AsConcreteMembershipUser(this IMembershipUser member, string providerName)
|
||||
internal static UmbracoMembershipMember AsConcreteMembershipUser(this IMembershipUser member, string providerName, bool providerKeyAsGuid = false)
|
||||
{
|
||||
var membershipMember = new UmbracoMembershipMember(member, providerName);
|
||||
var membershipMember = new UmbracoMembershipMember(member, providerName, providerKeyAsGuid);
|
||||
return membershipMember;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Web.Security;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
@@ -25,7 +26,7 @@ namespace Umbraco.Core.Models.Membership
|
||||
|
||||
//NOTE: We are not calling the base constructor which will validate that a provider with the specified name exists which causes issues with unit tests. The ctor
|
||||
// validation for that doesn't need to be there anyways (have checked the source).
|
||||
public UmbracoMembershipMember(IMembershipUser member, string providerName)
|
||||
public UmbracoMembershipMember(IMembershipUser member, string providerName, bool providerKeyAsGuid = false)
|
||||
{
|
||||
_member = member;
|
||||
//NOTE: We are copying the values here so that everything is consistent with how the underlying built-in ASP.Net membership user
|
||||
@@ -37,7 +38,7 @@ namespace Umbraco.Core.Models.Membership
|
||||
if (member.PasswordQuestion != null)
|
||||
_passwordQuestion = member.PasswordQuestion.Trim();
|
||||
_providerName = providerName;
|
||||
_providerUserKey = member.ProviderUserKey;
|
||||
_providerUserKey = providerKeyAsGuid ? member.ProviderUserKey : member.Id;
|
||||
_comment = member.Comments;
|
||||
_isApproved = member.IsApproved;
|
||||
_isLockedOut = member.IsLockedOut;
|
||||
|
||||
@@ -58,7 +58,6 @@ namespace Umbraco.Core.Models.Membership
|
||||
|
||||
private IUserType _userType;
|
||||
private string _name;
|
||||
private Type _userTypeKey;
|
||||
private List<string> _addedSections;
|
||||
private List<string> _removedSections;
|
||||
private ObservableCollection<string> _sectionCollection;
|
||||
@@ -80,7 +79,6 @@ namespace Umbraco.Core.Models.Membership
|
||||
private static readonly PropertyInfo StartMediaIdSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.StartMediaId);
|
||||
private static readonly PropertyInfo AllowedSectionsSelector = ExpressionHelper.GetPropertyInfo<User, IEnumerable<string>>(x => x.AllowedSections);
|
||||
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Name);
|
||||
private static readonly PropertyInfo UserTypeKeySelector = ExpressionHelper.GetPropertyInfo<User, Type>(x => x.ProviderUserKeyType);
|
||||
|
||||
private static readonly PropertyInfo UsernameSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Username);
|
||||
private static readonly PropertyInfo EmailSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Email);
|
||||
@@ -101,37 +99,6 @@ namespace Umbraco.Core.Models.Membership
|
||||
set { throw new NotSupportedException("Cannot set the provider user key for a user"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the provider user key.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The type of the provider user key.
|
||||
/// </value>
|
||||
[IgnoreDataMember]
|
||||
internal Type ProviderUserKeyType
|
||||
{
|
||||
get
|
||||
{
|
||||
return _userTypeKey;
|
||||
}
|
||||
private set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_userTypeKey = value;
|
||||
return _userTypeKey;
|
||||
}, _userTypeKey, UserTypeKeySelector);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the type of the provider user key.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
internal void SetProviderUserKeyType(Type type)
|
||||
{
|
||||
ProviderUserKeyType = type;
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public string Username
|
||||
|
||||
@@ -71,16 +71,34 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
using (new WriteLock(_addLocker))
|
||||
{
|
||||
var key = GetKeyForItem(item);
|
||||
if (key != null)
|
||||
//Note this is done to ensure existig groups can be renamed
|
||||
if (item.HasIdentity && item.Id > 0)
|
||||
{
|
||||
var exists = this.Contains(key);
|
||||
var exists = this.Contains(item.Id);
|
||||
if (exists)
|
||||
{
|
||||
SetItem(IndexOfKey(key), item);
|
||||
var keyExists = this.Contains(item.Name);
|
||||
if(keyExists)
|
||||
throw new Exception(string.Format("Naming conflict: Changing the name of PropertyGroup '{0}' would result in duplicates", item.Name));
|
||||
|
||||
SetItem(IndexOfKey(item.Id), item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var key = GetKeyForItem(item);
|
||||
if (key != null)
|
||||
{
|
||||
var exists = this.Contains(key);
|
||||
if (exists)
|
||||
{
|
||||
SetItem(IndexOfKey(key), item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base.Add(item);
|
||||
OnAdd.IfNotNull(x => x.Invoke());//Could this not be replaced by a Mandate/Contract for ensuring item is not null
|
||||
|
||||
@@ -99,6 +117,11 @@ namespace Umbraco.Core.Models
|
||||
return this.Any(x => x.Name == groupName);
|
||||
}
|
||||
|
||||
public bool Contains(int id)
|
||||
{
|
||||
return this.Any(x => x.Id == id);
|
||||
}
|
||||
|
||||
public void RemoveItem(string propertyGroupName)
|
||||
{
|
||||
var key = IndexOfKey(propertyGroupName);
|
||||
@@ -119,6 +142,18 @@ namespace Umbraco.Core.Models
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int IndexOfKey(int id)
|
||||
{
|
||||
for (var i = 0; i < this.Count; i++)
|
||||
{
|
||||
if (this[i].Id == id)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected override string GetKeyForItem(PropertyGroup item)
|
||||
{
|
||||
return item.Name;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text.RegularExpressions;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Strings;
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
[DebuggerDisplay("Id: {Id}, Name: {Name}, Alias: {Alias}")]
|
||||
public class PropertyType : Entity, IEquatable<PropertyType>
|
||||
{
|
||||
private readonly bool _isExplicitDbType;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -297,9 +298,38 @@ AND umbracoNode.id <> @id",
|
||||
//Delete Tabs/Groups by excepting entries from db with entries from collections
|
||||
var dbPropertyGroups =
|
||||
Database.Fetch<PropertyTypeGroupDto>("WHERE contenttypeNodeId = @Id", new {Id = entity.Id})
|
||||
.Select(x => new Tuple<int, string>(x.Id, x.Text));
|
||||
var entityPropertyGroups = entity.PropertyGroups.Select(x => new Tuple<int, string>(x.Id, x.Name));
|
||||
var tabs = dbPropertyGroups.Except(entityPropertyGroups);
|
||||
.Select(x => new Tuple<int, string>(x.Id, x.Text))
|
||||
.ToList();
|
||||
var entityPropertyGroups = entity.PropertyGroups.Select(x => new Tuple<int, string>(x.Id, x.Name)).ToList();
|
||||
var tabsToDelete = dbPropertyGroups.Select(x => x.Item1).Except(entityPropertyGroups.Select(x => x.Item1));
|
||||
var tabs = dbPropertyGroups.Where(x => tabsToDelete.Any(y => y == x.Item1));
|
||||
//Update Tab name downstream to ensure renaming is done properly
|
||||
foreach (var propertyGroup in entityPropertyGroups)
|
||||
{
|
||||
Database.Update<PropertyTypeGroupDto>("SET Text = @TabName WHERE parentGroupId = @TabId",
|
||||
new { TabName = propertyGroup.Item2, TabId = propertyGroup.Item1 });
|
||||
|
||||
var childGroups = Database.Fetch<PropertyTypeGroupDto>("WHERE parentGroupId = @TabId", new { TabId = propertyGroup.Item1 });
|
||||
foreach (var childGroup in childGroups)
|
||||
{
|
||||
var sibling = Database.Fetch<PropertyTypeGroupDto>("WHERE contenttypeNodeId = @Id AND text = @Name",
|
||||
new { Id = childGroup.ContentTypeNodeId, Name = propertyGroup.Item2 })
|
||||
.FirstOrDefault(x => x.ParentGroupId.HasValue == false || x.ParentGroupId.Value.Equals(propertyGroup.Item1) == false);
|
||||
//If the child group doesn't have a sibling there is no chance of duplicates and we continue
|
||||
if (sibling == null || (sibling.ParentGroupId.HasValue && sibling.ParentGroupId.Value.Equals(propertyGroup.Item1))) continue;
|
||||
|
||||
//Since the child group has a sibling with the same name we need to point any PropertyTypes to the sibling
|
||||
//as this child group is about to leave the party.
|
||||
Database.Update<PropertyTypeDto>(
|
||||
"SET propertyTypeGroupId = @PropertyTypeGroupId WHERE propertyTypeGroupId = @PropertyGroupId AND ContentTypeId = @ContentTypeId",
|
||||
new { PropertyTypeGroupId = sibling.Id, PropertyGroupId = childGroup.Id, ContentTypeId = childGroup.ContentTypeNodeId });
|
||||
|
||||
//Since the parent group has been renamed and we have duplicates we remove this group
|
||||
//and leave our sibling in charge of the part.
|
||||
Database.Delete(childGroup);
|
||||
}
|
||||
}
|
||||
//Do Tab updates
|
||||
foreach (var tab in tabs)
|
||||
{
|
||||
Database.Update<PropertyTypeDto>("SET propertyTypeGroupId = NULL WHERE propertyTypeGroupId = @PropertyGroupId",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
@@ -8,11 +9,13 @@ using System.Threading;
|
||||
using Umbraco.Core.Auditing;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
@@ -273,6 +276,74 @@ namespace Umbraco.Core.Services
|
||||
|
||||
}
|
||||
|
||||
public void Validate(IContentTypeComposition compo)
|
||||
{
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
ValidateLocked(compo);
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateLocked(IContentTypeComposition compositionContentType)
|
||||
{
|
||||
// performs business-level validation of the composition
|
||||
// should ensure that it is absolutely safe to save the composition
|
||||
|
||||
// eg maybe a property has been added, with an alias that's OK (no conflict with ancestors)
|
||||
// but that cannot be used (conflict with descendants)
|
||||
|
||||
var contentType = compositionContentType as IContentType;
|
||||
var mediaType = compositionContentType as IMediaType;
|
||||
|
||||
IContentTypeComposition[] allContentTypes;
|
||||
if (contentType != null)
|
||||
allContentTypes = GetAllContentTypes().Cast<IContentTypeComposition>().ToArray();
|
||||
else if (mediaType != null)
|
||||
allContentTypes = GetAllMediaTypes().Cast<IContentTypeComposition>().ToArray();
|
||||
else
|
||||
throw new Exception("Composition is neither IContentType nor IMediaType?");
|
||||
|
||||
var compositionAliases = compositionContentType.CompositionAliases();
|
||||
var compositions = allContentTypes.Where(x => compositionAliases.Any(y => x.Alias.Equals(y)));
|
||||
var propertyTypeAliases = compositionContentType.PropertyTypes.Select(x => x.Alias.ToLowerInvariant()).ToArray();
|
||||
var indirectReferences = allContentTypes.Where(x => x.ContentTypeComposition.Any(y => y.Id == compositionContentType.Id));
|
||||
var comparer = new DelegateEqualityComparer<IContentTypeComposition>((x, y) => x.Id == y.Id, x => x.Id);
|
||||
var dependencies = new HashSet<IContentTypeComposition>(compositions, comparer);
|
||||
var stack = new Stack<IContentTypeComposition>();
|
||||
indirectReferences.ForEach(stack.Push);//Push indirect references to a stack, so we can add recursively
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
var indirectReference = stack.Pop();
|
||||
dependencies.Add(indirectReference);
|
||||
//Get all compositions for the current indirect reference
|
||||
var directReferences = indirectReference.ContentTypeComposition;
|
||||
|
||||
foreach (var directReference in directReferences)
|
||||
{
|
||||
if (directReference.Id == compositionContentType.Id || directReference.Alias.Equals(compositionContentType.Alias)) continue;
|
||||
dependencies.Add(directReference);
|
||||
//A direct reference has compositions of its own - these also need to be taken into account
|
||||
var directReferenceGraph = directReference.CompositionAliases();
|
||||
allContentTypes.Where(x => directReferenceGraph.Any(y => x.Alias.Equals(y, StringComparison.InvariantCultureIgnoreCase))).ForEach(c => dependencies.Add(c));
|
||||
}
|
||||
//Recursive lookup of indirect references
|
||||
allContentTypes.Where(x => x.ContentTypeComposition.Any(y => y.Id == indirectReference.Id)).ForEach(stack.Push);
|
||||
}
|
||||
|
||||
foreach (var dependency in dependencies)
|
||||
{
|
||||
if (dependency.Id == compositionContentType.Id) continue;
|
||||
var contentTypeDependency = allContentTypes.FirstOrDefault(x => x.Alias.Equals(dependency.Alias, StringComparison.InvariantCultureIgnoreCase));
|
||||
if (contentTypeDependency == null) continue;
|
||||
var intersect = contentTypeDependency.PropertyTypes.Select(x => x.Alias.ToLowerInvariant()).Intersect(propertyTypeAliases).ToArray();
|
||||
if (intersect.Length == 0) continue;
|
||||
|
||||
var message = string.Format("The following PropertyType aliases from the current ContentType conflict with existing PropertyType aliases: {0}.",
|
||||
string.Join(", ", intersect));
|
||||
throw new Exception(message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves a single <see cref="IContentType"/> object
|
||||
/// </summary>
|
||||
@@ -288,6 +359,7 @@ namespace Umbraco.Core.Services
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateContentTypeRepository(uow))
|
||||
{
|
||||
ValidateLocked(contentType); // throws if invalid
|
||||
contentType.CreatorId = userId;
|
||||
repository.AddOrUpdate(contentType);
|
||||
|
||||
@@ -317,6 +389,11 @@ namespace Umbraco.Core.Services
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateContentTypeRepository(uow))
|
||||
{
|
||||
// all-or-nothing, validate them all first
|
||||
foreach (var contentType in asArray)
|
||||
{
|
||||
ValidateLocked(contentType); // throws if invalid
|
||||
}
|
||||
foreach (var contentType in asArray)
|
||||
{
|
||||
contentType.CreatorId = userId;
|
||||
@@ -487,6 +564,7 @@ namespace Umbraco.Core.Services
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow))
|
||||
{
|
||||
ValidateLocked(mediaType); // throws if invalid
|
||||
mediaType.CreatorId = userId;
|
||||
repository.AddOrUpdate(mediaType);
|
||||
uow.Commit();
|
||||
@@ -517,7 +595,11 @@ namespace Umbraco.Core.Services
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow))
|
||||
{
|
||||
|
||||
// all-or-nothing, validate them all first
|
||||
foreach (var mediaType in asArray)
|
||||
{
|
||||
ValidateLocked(mediaType); // throws if invalid
|
||||
}
|
||||
foreach (var mediaType in asArray)
|
||||
{
|
||||
mediaType.CreatorId = userId;
|
||||
|
||||
@@ -74,7 +74,8 @@ namespace Umbraco.Tests.PublishedContent
|
||||
{
|
||||
var contentTypeService = ctx.Application.Services.ContentTypeService;
|
||||
var baseType = new ContentType(-1) {Alias = "base", Name = "Base"};
|
||||
var inheritedType = new ContentType(baseType) {Alias = "inherited", Name = "Inherited"};
|
||||
const string contentTypeAlias = "inherited";
|
||||
var inheritedType = new ContentType(baseType, contentTypeAlias) {Alias = contentTypeAlias, Name = "Inherited"};
|
||||
contentTypeService.Save(baseType);
|
||||
contentTypeService.Save(inheritedType);
|
||||
createContentTypes = false;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Runtime.Remoting;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -5,6 +6,8 @@ using System.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.Caching;
|
||||
using Umbraco.Tests.CodeFirst.TestModels.Composition;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Tests.TestHelpers.Entities;
|
||||
|
||||
@@ -178,10 +181,11 @@ namespace Umbraco.Tests.Services
|
||||
/*,"Navigation"*/);
|
||||
cts.Save(ctBase);
|
||||
|
||||
var ctHomePage = new ContentType(ctBase)
|
||||
const string contentTypeAlias = "HomePage";
|
||||
var ctHomePage = new ContentType(ctBase, contentTypeAlias)
|
||||
{
|
||||
Name = "Home Page",
|
||||
Alias = "HomePage",
|
||||
Alias = contentTypeAlias,
|
||||
Icon = "settingDomain.gif",
|
||||
Thumbnail = "folder.png",
|
||||
AllowedAsRoot = true
|
||||
@@ -191,7 +195,7 @@ namespace Umbraco.Tests.Services
|
||||
cts.Save(ctHomePage);
|
||||
|
||||
// Act
|
||||
var homeDoc = cs.CreateContent("Home Page", -1, "HomePage");
|
||||
var homeDoc = cs.CreateContent("Home Page", -1, contentTypeAlias);
|
||||
cs.SaveAndPublishWithStatus(homeDoc);
|
||||
|
||||
// Assert
|
||||
@@ -243,13 +247,13 @@ namespace Umbraco.Tests.Services
|
||||
var global = MockedContentTypes.CreateSimpleContentType("global", "Global");
|
||||
service.Save(global);
|
||||
|
||||
var components = MockedContentTypes.CreateSimpleContentType("components", "Components", global);
|
||||
var components = MockedContentTypes.CreateSimpleContentType("components", "Components", global, true);
|
||||
service.Save(components);
|
||||
|
||||
var component = MockedContentTypes.CreateSimpleContentType("component", "Component", components);
|
||||
var component = MockedContentTypes.CreateSimpleContentType("component", "Component", components, true);
|
||||
service.Save(component);
|
||||
|
||||
var category = MockedContentTypes.CreateSimpleContentType("category", "Category", global);
|
||||
var category = MockedContentTypes.CreateSimpleContentType("category", "Category", global, true);
|
||||
service.Save(category);
|
||||
|
||||
var success = category.AddContentType(component);
|
||||
@@ -464,6 +468,766 @@ namespace Umbraco.Tests.Services
|
||||
Assert.AreNotEqual(clonedContentType.PropertyGroups.First(x => x.Name.StartsWith("Content")).Id, originalContentType.PropertyGroups.First(x => x.Name.StartsWith("Content")).Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Cannot_Add_Duplicate_PropertyType_Alias_To_Referenced_Composition()
|
||||
{
|
||||
//Related the second issue in screencast from this post http://issues.umbraco.org/issue/U4-5986
|
||||
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
|
||||
var parent = MockedContentTypes.CreateSimpleContentType();
|
||||
service.Save(parent);
|
||||
var child = MockedContentTypes.CreateSimpleContentType("simpleChildPage", "Simple Child Page", parent, true);
|
||||
service.Save(child);
|
||||
var composition = MockedContentTypes.CreateMetaContentType();
|
||||
service.Save(composition);
|
||||
|
||||
//Adding Meta-composition to child doc type
|
||||
child.AddContentType(composition);
|
||||
service.Save(child);
|
||||
|
||||
// Act
|
||||
var duplicatePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var added = composition.AddPropertyType(duplicatePropertyType, "Meta");
|
||||
|
||||
// Assert
|
||||
Assert.That(added, Is.True);
|
||||
Assert.Throws<Exception>(() => service.Save(composition));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("simpleChildPage"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Cannot_Add_Duplicate_PropertyType_Alias_In_Composition_Graph()
|
||||
{
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
|
||||
var basePage = MockedContentTypes.CreateSimpleContentType("basePage", "Base Page", null, true);
|
||||
service.Save(basePage);
|
||||
var contentPage = MockedContentTypes.CreateSimpleContentType("contentPage", "Content Page", basePage);
|
||||
service.Save(contentPage);
|
||||
var advancedPage = MockedContentTypes.CreateSimpleContentType("advancedPage", "Advanced Page", contentPage, true);
|
||||
service.Save(advancedPage);
|
||||
|
||||
var metaComposition = MockedContentTypes.CreateMetaContentType();
|
||||
service.Save(metaComposition);
|
||||
var seoComposition = MockedContentTypes.CreateSeoContentType();
|
||||
service.Save(seoComposition);
|
||||
|
||||
var metaAdded = contentPage.AddContentType(metaComposition);
|
||||
service.Save(contentPage);
|
||||
var seoAdded = advancedPage.AddContentType(seoComposition);
|
||||
service.Save(advancedPage);
|
||||
|
||||
// Act
|
||||
var duplicatePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var addedToBasePage = basePage.AddPropertyType(duplicatePropertyType, "Content");
|
||||
var addedToAdvancedPage = advancedPage.AddPropertyType(duplicatePropertyType, "Content");
|
||||
var addedToMeta = metaComposition.AddPropertyType(duplicatePropertyType, "Meta");
|
||||
var addedToSeo = seoComposition.AddPropertyType(duplicatePropertyType, "Seo");
|
||||
|
||||
// Assert
|
||||
Assert.That(metaAdded, Is.True);
|
||||
Assert.That(seoAdded, Is.True);
|
||||
|
||||
Assert.That(addedToBasePage, Is.True);
|
||||
Assert.That(addedToAdvancedPage, Is.False);
|
||||
Assert.That(addedToMeta, Is.True);
|
||||
Assert.That(addedToSeo, Is.True);
|
||||
|
||||
Assert.Throws<Exception>(() => service.Save(basePage));
|
||||
Assert.Throws<Exception>(() => service.Save(metaComposition));
|
||||
Assert.Throws<Exception>(() => service.Save(seoComposition));
|
||||
|
||||
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("meta"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("seo"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Cannot_Add_Duplicate_PropertyType_Alias_At_Root_Which_Conflicts_With_Third_Levels_Composition()
|
||||
{
|
||||
/*
|
||||
* BasePage, gets 'Title' added but should not be allowed
|
||||
* -- Content Page
|
||||
* ---- Advanced Page -> Content Meta
|
||||
* Content Meta :: Composition, has 'Title'
|
||||
*
|
||||
* Content Meta has 'Title' PropertyType
|
||||
* Adding 'Title' to BasePage should fail
|
||||
*/
|
||||
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var basePage = MockedContentTypes.CreateBasicContentType();
|
||||
service.Save(basePage);
|
||||
var contentPage = MockedContentTypes.CreateBasicContentType("contentPage", "Content Page", basePage);
|
||||
service.Save(contentPage);
|
||||
var advancedPage = MockedContentTypes.CreateBasicContentType("advancedPage", "Advanced Page", contentPage);
|
||||
service.Save(advancedPage);
|
||||
|
||||
var contentMetaComposition = MockedContentTypes.CreateContentMetaContentType();
|
||||
service.Save(contentMetaComposition);
|
||||
|
||||
// Act
|
||||
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var bodyTextAdded = basePage.AddPropertyType(bodyTextPropertyType, "Content");
|
||||
service.Save(basePage);
|
||||
|
||||
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content");
|
||||
service.Save(contentPage);
|
||||
|
||||
var compositionAdded = advancedPage.AddContentType(contentMetaComposition);
|
||||
service.Save(advancedPage);
|
||||
|
||||
//NOTE: It should not be possible to Save 'BasePage' with the Title PropertyType added
|
||||
var titlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var titleAdded = basePage.AddPropertyType(titlePropertyType, "Content");
|
||||
|
||||
// Assert
|
||||
Assert.That(bodyTextAdded, Is.True);
|
||||
Assert.That(authorAdded, Is.True);
|
||||
Assert.That(titleAdded, Is.True);
|
||||
Assert.That(compositionAdded, Is.True);
|
||||
|
||||
Assert.Throws<Exception>(() => service.Save(basePage));
|
||||
|
||||
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Cannot_Rename_PropertyType_Alias_On_Composition_Which_Would_Cause_Conflict_In_Other_Composition()
|
||||
{
|
||||
/*
|
||||
* Meta renames alias to 'title'
|
||||
* Seo has 'Title'
|
||||
* BasePage
|
||||
* -- ContentPage
|
||||
* ---- AdvancedPage -> Seo
|
||||
* ------ MoreAdvanedPage -> Meta
|
||||
*/
|
||||
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var basePage = MockedContentTypes.CreateBasicContentType();
|
||||
service.Save(basePage);
|
||||
var contentPage = MockedContentTypes.CreateBasicContentType("contentPage", "Content Page", basePage);
|
||||
service.Save(contentPage);
|
||||
var advancedPage = MockedContentTypes.CreateBasicContentType("advancedPage", "Advanced Page", contentPage);
|
||||
service.Save(advancedPage);
|
||||
var moreAdvancedPage = MockedContentTypes.CreateBasicContentType("moreAdvancedPage", "More Advanced Page", advancedPage);
|
||||
service.Save(moreAdvancedPage);
|
||||
|
||||
var seoComposition = MockedContentTypes.CreateSeoContentType();
|
||||
service.Save(seoComposition);
|
||||
var metaComposition = MockedContentTypes.CreateMetaContentType();
|
||||
service.Save(metaComposition);
|
||||
|
||||
// Act
|
||||
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var bodyTextAdded = basePage.AddPropertyType(bodyTextPropertyType, "Content");
|
||||
service.Save(basePage);
|
||||
|
||||
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content");
|
||||
service.Save(contentPage);
|
||||
|
||||
var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "subtitle", Name = "Subtitle", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var subtitleAdded = advancedPage.AddPropertyType(subtitlePropertyType, "Content");
|
||||
service.Save(advancedPage);
|
||||
|
||||
var titlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var titleAdded = seoComposition.AddPropertyType(titlePropertyType, "Content");
|
||||
service.Save(seoComposition);
|
||||
|
||||
var seoCompositionAdded = advancedPage.AddContentType(seoComposition);
|
||||
var metaCompositionAdded = moreAdvancedPage.AddContentType(metaComposition);
|
||||
service.Save(advancedPage);
|
||||
service.Save(moreAdvancedPage);
|
||||
|
||||
var keywordsPropertyType = metaComposition.PropertyTypes.First(x => x.Alias.Equals("metakeywords"));
|
||||
keywordsPropertyType.Alias = "title";
|
||||
|
||||
// Assert
|
||||
Assert.That(bodyTextAdded, Is.True);
|
||||
Assert.That(subtitleAdded, Is.True);
|
||||
Assert.That(authorAdded, Is.True);
|
||||
Assert.That(titleAdded, Is.True);
|
||||
Assert.That(seoCompositionAdded, Is.True);
|
||||
Assert.That(metaCompositionAdded, Is.True);
|
||||
|
||||
Assert.Throws<Exception>(() => service.Save(metaComposition));
|
||||
|
||||
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("moreAdvancedPage"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Add_Additional_Properties_On_Composition_Once_Composition_Has_Been_Saved()
|
||||
{
|
||||
/*
|
||||
* Meta renames alias to 'title'
|
||||
* Seo has 'Title'
|
||||
* BasePage
|
||||
* -- ContentPage
|
||||
* ---- AdvancedPage -> Seo
|
||||
* ------ MoreAdvancedPage -> Meta
|
||||
*/
|
||||
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var basePage = MockedContentTypes.CreateBasicContentType();
|
||||
service.Save(basePage);
|
||||
var contentPage = MockedContentTypes.CreateBasicContentType("contentPage", "Content Page", basePage);
|
||||
service.Save(contentPage);
|
||||
var advancedPage = MockedContentTypes.CreateBasicContentType("advancedPage", "Advanced Page", contentPage);
|
||||
service.Save(advancedPage);
|
||||
var moreAdvancedPage = MockedContentTypes.CreateBasicContentType("moreAdvancedPage", "More Advanced Page", advancedPage);
|
||||
service.Save(moreAdvancedPage);
|
||||
|
||||
var seoComposition = MockedContentTypes.CreateSeoContentType();
|
||||
service.Save(seoComposition);
|
||||
var metaComposition = MockedContentTypes.CreateMetaContentType();
|
||||
service.Save(metaComposition);
|
||||
|
||||
// Act
|
||||
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var bodyTextAdded = basePage.AddPropertyType(bodyTextPropertyType, "Content");
|
||||
service.Save(basePage);
|
||||
|
||||
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content");
|
||||
service.Save(contentPage);
|
||||
|
||||
var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "subtitle", Name = "Subtitle", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var subtitleAdded = advancedPage.AddPropertyType(subtitlePropertyType, "Content");
|
||||
service.Save(advancedPage);
|
||||
|
||||
var titlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var titleAdded = seoComposition.AddPropertyType(titlePropertyType, "Content");
|
||||
service.Save(seoComposition);
|
||||
|
||||
var seoCompositionAdded = advancedPage.AddContentType(seoComposition);
|
||||
var metaCompositionAdded = moreAdvancedPage.AddContentType(metaComposition);
|
||||
service.Save(advancedPage);
|
||||
service.Save(moreAdvancedPage);
|
||||
|
||||
// Assert
|
||||
Assert.That(bodyTextAdded, Is.True);
|
||||
Assert.That(subtitleAdded, Is.True);
|
||||
Assert.That(authorAdded, Is.True);
|
||||
Assert.That(titleAdded, Is.True);
|
||||
Assert.That(seoCompositionAdded, Is.True);
|
||||
Assert.That(metaCompositionAdded, Is.True);
|
||||
|
||||
var testPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "test", Name = "Test", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var testAdded = seoComposition.AddPropertyType(testPropertyType, "Content");
|
||||
service.Save(seoComposition);
|
||||
|
||||
Assert.That(testAdded, Is.True);
|
||||
|
||||
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("moreAdvancedPage"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Cannot_Rename_PropertyGroup_On_Child_Avoiding_Conflict_With_Parent_PropertyGroup()
|
||||
{
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var page = MockedContentTypes.CreateSimpleContentType("page", "Page", null, true, "Content");
|
||||
service.Save(page);
|
||||
var contentPage = MockedContentTypes.CreateSimpleContentType("contentPage", "Content Page", page, true, "Content_");
|
||||
service.Save(contentPage);
|
||||
var advancedPage = MockedContentTypes.CreateSimpleContentType("advancedPage", "Advanced Page", contentPage, true, "Details");
|
||||
service.Save(advancedPage);
|
||||
|
||||
var contentMetaComposition = MockedContentTypes.CreateContentMetaContentType();
|
||||
service.Save(contentMetaComposition);
|
||||
|
||||
// Act
|
||||
var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "subtitle", Name = "Subtitle", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var subtitleAdded = contentPage.AddPropertyType(subtitlePropertyType, "Content");
|
||||
var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content");
|
||||
service.Save(contentPage);
|
||||
|
||||
var compositionAdded = contentPage.AddContentType(contentMetaComposition);
|
||||
service.Save(contentPage);
|
||||
|
||||
//Change the name of the tab on the "root" content type 'page'.
|
||||
var propertyGroup = contentPage.PropertyGroups["Content_"];
|
||||
Assert.Throws<Exception>(() => contentPage.PropertyGroups.Add(new PropertyGroup
|
||||
{
|
||||
Id = propertyGroup.Id,
|
||||
Name = "Content",
|
||||
SortOrder = 0
|
||||
}));
|
||||
|
||||
// Assert
|
||||
Assert.That(compositionAdded, Is.True);
|
||||
Assert.That(subtitleAdded, Is.True);
|
||||
Assert.That(authorAdded, Is.True);
|
||||
|
||||
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Cannot_Rename_PropertyType_Alias_Causing_Conflicts_With_Parents()
|
||||
{
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var basePage = MockedContentTypes.CreateBasicContentType();
|
||||
service.Save(basePage);
|
||||
var contentPage = MockedContentTypes.CreateBasicContentType("contentPage", "Content Page", basePage);
|
||||
service.Save(contentPage);
|
||||
var advancedPage = MockedContentTypes.CreateBasicContentType("advancedPage", "Advanced Page", contentPage);
|
||||
service.Save(advancedPage);
|
||||
|
||||
// Act
|
||||
var titlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var titleAdded = basePage.AddPropertyType(titlePropertyType, "Content");
|
||||
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var bodyTextAdded = contentPage.AddPropertyType(bodyTextPropertyType, "Content");
|
||||
var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "subtitle", Name = "Subtitle", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var subtitleAdded = contentPage.AddPropertyType(subtitlePropertyType, "Content");
|
||||
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var authorAdded = advancedPage.AddPropertyType(authorPropertyType, "Content");
|
||||
service.Save(basePage);
|
||||
service.Save(contentPage);
|
||||
service.Save(advancedPage);
|
||||
|
||||
//Rename the PropertyType to something that already exists in the Composition - NOTE this should not be allowed and Saving should throw an exception
|
||||
var authorPropertyTypeToRename = advancedPage.PropertyTypes.First(x => x.Alias.Equals("author"));
|
||||
authorPropertyTypeToRename.Alias = "title";
|
||||
|
||||
// Assert
|
||||
Assert.That(bodyTextAdded, Is.True);
|
||||
Assert.That(authorAdded, Is.True);
|
||||
Assert.That(titleAdded, Is.True);
|
||||
Assert.That(subtitleAdded, Is.True);
|
||||
|
||||
Assert.Throws<Exception>(() => service.Save(advancedPage));
|
||||
|
||||
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Add_PropertyType_Alias_Which_Exists_In_Composition_Outside_Graph()
|
||||
{
|
||||
/*
|
||||
* Meta (Composition)
|
||||
* Content Meta (Composition) has 'Title' -> Meta
|
||||
* BasePage
|
||||
* -- ContentPage gets 'Title' added -> Meta
|
||||
* ---- Advanced Page
|
||||
*/
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
|
||||
var basePage = MockedContentTypes.CreateSimpleContentType("basePage", "Base Page", null, true);
|
||||
service.Save(basePage);
|
||||
var contentPage = MockedContentTypes.CreateSimpleContentType("contentPage", "Content Page", basePage, true);
|
||||
service.Save(contentPage);
|
||||
var advancedPage = MockedContentTypes.CreateSimpleContentType("advancedPage", "Advanced Page", contentPage, true);
|
||||
service.Save(advancedPage);
|
||||
|
||||
var metaComposition = MockedContentTypes.CreateMetaContentType();
|
||||
service.Save(metaComposition);
|
||||
|
||||
var contentMetaComposition = MockedContentTypes.CreateContentMetaContentType();
|
||||
service.Save(contentMetaComposition);
|
||||
|
||||
var metaAdded = contentPage.AddContentType(metaComposition);
|
||||
service.Save(contentPage);
|
||||
|
||||
var metaAddedToComposition = contentMetaComposition.AddContentType(metaComposition);
|
||||
service.Save(contentMetaComposition);
|
||||
|
||||
// Act
|
||||
var propertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var addedToContentPage = contentPage.AddPropertyType(propertyType, "Content");
|
||||
|
||||
// Assert
|
||||
Assert.That(metaAdded, Is.True);
|
||||
Assert.That(metaAddedToComposition, Is.True);
|
||||
|
||||
Assert.That(addedToContentPage, Is.True);
|
||||
Assert.DoesNotThrow(() => service.Save(contentPage));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Rename_PropertyGroup_With_Inherited_PropertyGroups()
|
||||
{
|
||||
//Related the first issue in screencast from this post http://issues.umbraco.org/issue/U4-5986
|
||||
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
|
||||
var page = MockedContentTypes.CreateSimpleContentType("page", "Page", null, false, "Content_");
|
||||
service.Save(page);
|
||||
var contentPage = MockedContentTypes.CreateSimpleContentType("contentPage", "Content Page", page, true);
|
||||
service.Save(contentPage);
|
||||
var composition = MockedContentTypes.CreateMetaContentType();
|
||||
composition.AddPropertyGroup("Content");
|
||||
service.Save(composition);
|
||||
//Adding Meta-composition to child doc type
|
||||
contentPage.AddContentType(composition);
|
||||
service.Save(contentPage);
|
||||
|
||||
// Act
|
||||
var propertyTypeOne = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "testTextbox", Name = "Test Textbox", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var firstOneAdded = contentPage.AddPropertyType(propertyTypeOne, "Content_");
|
||||
var propertyTypeTwo = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "anotherTextbox", Name = "Another Test Textbox", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var secondOneAdded = contentPage.AddPropertyType(propertyTypeTwo, "Content");
|
||||
service.Save(contentPage);
|
||||
|
||||
Assert.That(page.PropertyGroups.Contains("Content_"), Is.True);
|
||||
var propertyGroup = page.PropertyGroups["Content_"];
|
||||
page.PropertyGroups.Add(new PropertyGroup{ Id = propertyGroup.Id, Name = "ContentTab", SortOrder = 0});
|
||||
service.Save(page);
|
||||
|
||||
// Assert
|
||||
Assert.That(firstOneAdded, Is.True);
|
||||
Assert.That(secondOneAdded, Is.True);
|
||||
|
||||
var contentType = service.GetContentType("contentPage");
|
||||
Assert.That(contentType, Is.Not.Null);
|
||||
|
||||
var compositionPropertyGroups = contentType.CompositionPropertyGroups;
|
||||
Assert.That(compositionPropertyGroups.Count(x => x.Name.Equals("Content_")), Is.EqualTo(0));
|
||||
|
||||
var propertyTypeCount = contentType.PropertyTypes.Count();
|
||||
var compPropertyTypeCount = contentType.CompositionPropertyTypes.Count();
|
||||
Assert.That(propertyTypeCount, Is.EqualTo(5));
|
||||
Assert.That(compPropertyTypeCount, Is.EqualTo(10));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Rename_PropertyGroup_On_Parent_Without_Causing_Duplicate_PropertyGroups()
|
||||
{
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var page = MockedContentTypes.CreateSimpleContentType("page", "Page", null, true, "Content_");
|
||||
service.Save(page);
|
||||
var contentPage = MockedContentTypes.CreateSimpleContentType("contentPage", "Content Page", page, true, "Contentx");
|
||||
service.Save(contentPage);
|
||||
var advancedPage = MockedContentTypes.CreateSimpleContentType("advancedPage", "Advanced Page", contentPage, true, "Contenty");
|
||||
service.Save(advancedPage);
|
||||
|
||||
var contentMetaComposition = MockedContentTypes.CreateContentMetaContentType();
|
||||
service.Save(contentMetaComposition);
|
||||
var compositionAdded = contentPage.AddContentType(contentMetaComposition);
|
||||
service.Save(contentPage);
|
||||
|
||||
// Act
|
||||
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "subtitle", Name = "Subtitle", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var bodyTextAdded = contentPage.AddPropertyType(bodyTextPropertyType, "Content_");//Will be added to the parent tab
|
||||
var subtitleAdded = contentPage.AddPropertyType(subtitlePropertyType, "Content");//Will be added to the "Content Meta" composition
|
||||
service.Save(contentPage);
|
||||
|
||||
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var descriptionPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "description", Name = "Description", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var keywordsPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "keywords", Name = "Keywords", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var authorAdded = advancedPage.AddPropertyType(authorPropertyType, "Content_");//Will be added to an ancestor tab
|
||||
var descriptionAdded = advancedPage.AddPropertyType(descriptionPropertyType, "Contentx");//Will be added to a parent tab
|
||||
var keywordsAdded = advancedPage.AddPropertyType(keywordsPropertyType, "Content");//Will be added to the "Content Meta" composition
|
||||
service.Save(advancedPage);
|
||||
|
||||
//Change the name of the tab on the "root" content type 'page'.
|
||||
var propertyGroup = page.PropertyGroups["Content_"];
|
||||
page.PropertyGroups.Add(new PropertyGroup { Id = propertyGroup.Id, Name = "Content", SortOrder = 0 });
|
||||
service.Save(page);
|
||||
|
||||
// Assert
|
||||
Assert.That(compositionAdded, Is.True);
|
||||
Assert.That(bodyTextAdded, Is.True);
|
||||
Assert.That(subtitleAdded, Is.True);
|
||||
Assert.That(authorAdded, Is.True);
|
||||
Assert.That(descriptionAdded, Is.True);
|
||||
Assert.That(keywordsAdded, Is.True);
|
||||
|
||||
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
|
||||
|
||||
var advancedPageReloaded = service.GetContentType("advancedPage");
|
||||
var contentUnderscoreTabExists = advancedPageReloaded.CompositionPropertyGroups.Any(x => x.Name.Equals("Content_"));
|
||||
Assert.That(contentUnderscoreTabExists, Is.False);
|
||||
|
||||
var numberOfContentTabs = advancedPageReloaded.CompositionPropertyGroups.Count(x => x.Name.Equals("Content"));
|
||||
Assert.That(numberOfContentTabs, Is.EqualTo(4));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Rename_PropertyGroup_On_Parent_Without_Causing_Duplicate_PropertyGroups_v2()
|
||||
{
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var page = MockedContentTypes.CreateSimpleContentType("page", "Page", null, true, "Content_");
|
||||
service.Save(page);
|
||||
var contentPage = MockedContentTypes.CreateSimpleContentType("contentPage", "Content Page", page, true, "Content");
|
||||
service.Save(contentPage);
|
||||
|
||||
var contentMetaComposition = MockedContentTypes.CreateContentMetaContentType();
|
||||
service.Save(contentMetaComposition);
|
||||
|
||||
// Act
|
||||
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "subtitle", Name = "Subtitle", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var bodyTextAdded = page.AddPropertyType(bodyTextPropertyType, "Content_");
|
||||
var subtitleAdded = contentPage.AddPropertyType(subtitlePropertyType, "Content");
|
||||
var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content_");
|
||||
service.Save(page);
|
||||
service.Save(contentPage);
|
||||
|
||||
var compositionAdded = contentPage.AddContentType(contentMetaComposition);
|
||||
service.Save(contentPage);
|
||||
|
||||
//Change the name of the tab on the "root" content type 'page'.
|
||||
var propertyGroup = page.PropertyGroups["Content_"];
|
||||
page.PropertyGroups.Add(new PropertyGroup { Id = propertyGroup.Id, Name = "Content", SortOrder = 0 });
|
||||
service.Save(page);
|
||||
|
||||
// Assert
|
||||
Assert.That(compositionAdded, Is.True);
|
||||
Assert.That(bodyTextAdded, Is.True);
|
||||
Assert.That(subtitleAdded, Is.True);
|
||||
Assert.That(authorAdded, Is.True);
|
||||
|
||||
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Remove_PropertyGroup_On_Parent_Without_Causing_Duplicate_PropertyGroups()
|
||||
{
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var basePage = MockedContentTypes.CreateBasicContentType();
|
||||
service.Save(basePage);
|
||||
|
||||
var contentPage = MockedContentTypes.CreateBasicContentType("contentPage", "Content Page", basePage);
|
||||
service.Save(contentPage);
|
||||
|
||||
var advancedPage = MockedContentTypes.CreateBasicContentType("advancedPage", "Advanced Page", contentPage);
|
||||
service.Save(advancedPage);
|
||||
|
||||
var contentMetaComposition = MockedContentTypes.CreateContentMetaContentType();
|
||||
service.Save(contentMetaComposition);
|
||||
|
||||
// Act
|
||||
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var bodyTextAdded = basePage.AddPropertyType(bodyTextPropertyType, "Content");
|
||||
service.Save(basePage);
|
||||
|
||||
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content");
|
||||
service.Save(contentPage);
|
||||
|
||||
var compositionAdded = contentPage.AddContentType(contentMetaComposition);
|
||||
service.Save(contentPage);
|
||||
|
||||
basePage.RemovePropertyGroup("Content");
|
||||
service.Save(basePage);
|
||||
|
||||
// Assert
|
||||
Assert.That(bodyTextAdded, Is.True);
|
||||
Assert.That(authorAdded, Is.True);
|
||||
Assert.That(compositionAdded, Is.True);
|
||||
|
||||
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
|
||||
|
||||
var contentType = service.GetContentType("contentPage");
|
||||
var propertyGroup = contentType.PropertyGroups["Content"];
|
||||
Assert.That(propertyGroup.ParentId.HasValue, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Add_PropertyGroup_With_Same_Name_On_Parent_and_Child()
|
||||
{
|
||||
/*
|
||||
* BasePage
|
||||
* - Content Page
|
||||
* -- Advanced Page
|
||||
* Content Meta :: Composition
|
||||
*/
|
||||
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var basePage = MockedContentTypes.CreateBasicContentType();
|
||||
service.Save(basePage);
|
||||
|
||||
var contentPage = MockedContentTypes.CreateBasicContentType("contentPage", "Content Page", basePage);
|
||||
service.Save(contentPage);
|
||||
|
||||
var advancedPage = MockedContentTypes.CreateBasicContentType("advancedPage", "Advanced Page", contentPage);
|
||||
service.Save(advancedPage);
|
||||
|
||||
var contentMetaComposition = MockedContentTypes.CreateContentMetaContentType();
|
||||
service.Save(contentMetaComposition);
|
||||
|
||||
// Act
|
||||
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content");
|
||||
service.Save(contentPage);
|
||||
|
||||
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var bodyTextAdded = basePage.AddPropertyType(bodyTextPropertyType, "Content");
|
||||
service.Save(basePage);
|
||||
|
||||
var compositionAdded = contentPage.AddContentType(contentMetaComposition);
|
||||
service.Save(contentPage);
|
||||
|
||||
// Assert
|
||||
Assert.That(bodyTextAdded, Is.True);
|
||||
Assert.That(authorAdded, Is.True);
|
||||
Assert.That(compositionAdded, Is.True);
|
||||
|
||||
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
|
||||
|
||||
var contentType = service.GetContentType("contentPage");
|
||||
var propertyGroup = contentType.PropertyGroups["Content"];
|
||||
Assert.That(propertyGroup.ParentId.HasValue, Is.False);
|
||||
|
||||
var numberOfContentTabs = contentType.CompositionPropertyGroups.Count(x => x.Name.Equals("Content"));
|
||||
Assert.That(numberOfContentTabs, Is.EqualTo(3));
|
||||
|
||||
//Ensure that adding a new PropertyType to the "Content"-tab also adds it to the right group
|
||||
|
||||
var descriptionPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "description", Name = "Description", Description = "", HelpText = "", Mandatory = false, SortOrder = 1,DataTypeDefinitionId = -88
|
||||
};
|
||||
var descriptionAdded = contentType.AddPropertyType(descriptionPropertyType, "Content");
|
||||
service.Save(contentType);
|
||||
Assert.That(descriptionAdded, Is.True);
|
||||
|
||||
var contentPageReloaded = service.GetContentType("contentPage");
|
||||
var propertyGroupReloaded = contentPageReloaded.PropertyGroups["Content"];
|
||||
var hasDescriptionPropertyType = propertyGroupReloaded.PropertyTypes.Contains("description");
|
||||
Assert.That(hasDescriptionPropertyType, Is.True);
|
||||
Assert.That(propertyGroupReloaded.ParentId.HasValue, Is.False);
|
||||
|
||||
var descriptionPropertyTypeReloaded = propertyGroupReloaded.PropertyTypes["description"];
|
||||
Assert.That(descriptionPropertyTypeReloaded.PropertyGroupId.IsValueCreated, Is.False);
|
||||
}
|
||||
|
||||
private ContentType CreateComponent()
|
||||
{
|
||||
var component = new ContentType(-1)
|
||||
@@ -487,9 +1251,10 @@ namespace Umbraco.Tests.Services
|
||||
|
||||
private ContentType CreateBannerComponent(ContentType parent)
|
||||
{
|
||||
var banner = new ContentType(parent)
|
||||
const string contentTypeAlias = "banner";
|
||||
var banner = new ContentType(parent, contentTypeAlias)
|
||||
{
|
||||
Alias = "banner",
|
||||
Alias = contentTypeAlias,
|
||||
Name = "Banner Component",
|
||||
Description = "ContentType used for Banner Component",
|
||||
Icon = ".sprTreeDoc3",
|
||||
@@ -535,9 +1300,10 @@ namespace Umbraco.Tests.Services
|
||||
|
||||
private ContentType CreateHomepage(ContentType parent)
|
||||
{
|
||||
var contentType = new ContentType(parent)
|
||||
const string contentTypeAlias = "homepage";
|
||||
var contentType = new ContentType(parent, contentTypeAlias)
|
||||
{
|
||||
Alias = "homepage",
|
||||
Alias = contentTypeAlias,
|
||||
Name = "Homepage",
|
||||
Description = "ContentType used for the Homepage",
|
||||
Icon = ".sprTreeDoc3",
|
||||
|
||||
@@ -6,7 +6,25 @@ namespace Umbraco.Tests.TestHelpers.Entities
|
||||
{
|
||||
public class MockedContentTypes
|
||||
{
|
||||
|
||||
public static ContentType CreateBasicContentType(string alias = "basePage", string name = "Base Page",
|
||||
ContentType parent = null)
|
||||
{
|
||||
var contentType = parent == null ? new ContentType(-1) : new ContentType(parent, alias);
|
||||
|
||||
contentType.Alias = alias;
|
||||
contentType.Name = name;
|
||||
contentType.Description = "ContentType used for basic pages";
|
||||
contentType.Icon = ".sprTreeDoc3";
|
||||
contentType.Thumbnail = "doc2.png";
|
||||
contentType.SortOrder = 1;
|
||||
contentType.CreatorId = 0;
|
||||
contentType.Trashed = false;
|
||||
|
||||
//ensure that nothing is marked as dirty
|
||||
contentType.ResetDirtyProperties(false);
|
||||
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public static ContentType CreateTextpageContentType(string alias = "textPage", string name = "Text Page")
|
||||
{
|
||||
@@ -65,6 +83,57 @@ namespace Umbraco.Tests.TestHelpers.Entities
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public static ContentType CreateContentMetaContentType()
|
||||
{
|
||||
var contentType = new ContentType(-1)
|
||||
{
|
||||
Alias = "contentMeta",
|
||||
Name = "Content Meta",
|
||||
Description = "ContentType used for Content Meta",
|
||||
Icon = ".sprTreeDoc3",
|
||||
Thumbnail = "doc.png",
|
||||
SortOrder = 1,
|
||||
CreatorId = 0,
|
||||
Trashed = false
|
||||
};
|
||||
|
||||
var metaCollection = new PropertyTypeCollection();
|
||||
metaCollection.Add(new PropertyType("test", DataTypeDatabaseType.Ntext) { Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 });
|
||||
|
||||
contentType.PropertyGroups.Add(new PropertyGroup(metaCollection) { Name = "Content", SortOrder = 2 });
|
||||
|
||||
//ensure that nothing is marked as dirty
|
||||
contentType.ResetDirtyProperties(false);
|
||||
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public static ContentType CreateSeoContentType()
|
||||
{
|
||||
var contentType = new ContentType(-1)
|
||||
{
|
||||
Alias = "seo",
|
||||
Name = "Seo",
|
||||
Description = "ContentType used for Seo",
|
||||
Icon = ".sprTreeDoc3",
|
||||
Thumbnail = "doc.png",
|
||||
SortOrder = 1,
|
||||
CreatorId = 0,
|
||||
Trashed = false
|
||||
};
|
||||
|
||||
var metaCollection = new PropertyTypeCollection();
|
||||
metaCollection.Add(new PropertyType("seotest", DataTypeDatabaseType.Ntext) { Alias = "seokeywords", Name = "Seo Keywords", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 });
|
||||
metaCollection.Add(new PropertyType("seotest", DataTypeDatabaseType.Ntext) { Alias = "seodescription", Name = "Seo Description", Description = "", HelpText = "", Mandatory = false, SortOrder = 2, DataTypeDefinitionId = -89 });
|
||||
|
||||
contentType.PropertyGroups.Add(new PropertyGroup(metaCollection) { Name = "Seo", SortOrder = 5 });
|
||||
|
||||
//ensure that nothing is marked as dirty
|
||||
contentType.ResetDirtyProperties(false);
|
||||
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public static ContentType CreateSimpleContentType()
|
||||
{
|
||||
var contentType = new ContentType(-1)
|
||||
@@ -92,9 +161,9 @@ namespace Umbraco.Tests.TestHelpers.Entities
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public static ContentType CreateSimpleContentType(string alias, string name, IContentType parent = null, bool randomizeAliases = false)
|
||||
public static ContentType CreateSimpleContentType(string alias, string name, IContentType parent = null, bool randomizeAliases = false, string propertyGroupName = "Content")
|
||||
{
|
||||
var contentType = parent == null ? new ContentType(-1) : new ContentType(parent);
|
||||
var contentType = parent == null ? new ContentType(-1) : new ContentType(parent, alias);
|
||||
|
||||
contentType.Alias = alias;
|
||||
contentType.Name = name;
|
||||
@@ -110,7 +179,7 @@ namespace Umbraco.Tests.TestHelpers.Entities
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.TinyMCEAlias, DataTypeDatabaseType.Ntext) { Alias = RandomAlias("bodyText", randomizeAliases), Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 2, DataTypeDefinitionId = -87 });
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) { Alias = RandomAlias("author", randomizeAliases) , Name = "Author", Description = "Name of the author", HelpText = "", Mandatory = false, SortOrder = 3, DataTypeDefinitionId = -88 });
|
||||
|
||||
contentType.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = "Content", SortOrder = 1 });
|
||||
contentType.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = propertyGroupName, SortOrder = 1 });
|
||||
|
||||
//ensure that nothing is marked as dirty
|
||||
contentType.ResetDirtyProperties(false);
|
||||
@@ -167,6 +236,27 @@ namespace Umbraco.Tests.TestHelpers.Entities
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public static ContentType CreateSimpleContentType(string alias, string name, PropertyTypeCollection collection, string propertyGroupName, IContentType parent = null)
|
||||
{
|
||||
var contentType = parent == null ? new ContentType(-1) : new ContentType(parent, alias);
|
||||
|
||||
contentType.Alias = alias;
|
||||
contentType.Name = name;
|
||||
contentType.Description = "ContentType used for simple text pages";
|
||||
contentType.Icon = ".sprTreeDoc3";
|
||||
contentType.Thumbnail = "doc2.png";
|
||||
contentType.SortOrder = 1;
|
||||
contentType.CreatorId = 0;
|
||||
contentType.Trashed = false;
|
||||
|
||||
contentType.PropertyGroups.Add(new PropertyGroup(collection) { Name = propertyGroupName, SortOrder = 1 });
|
||||
|
||||
//ensure that nothing is marked as dirty
|
||||
contentType.ResetDirtyProperties(false);
|
||||
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public static ContentType CreateSimpleContentType(string alias, string name, PropertyTypeCollection groupedCollection, PropertyTypeCollection nonGroupedCollection)
|
||||
{
|
||||
var contentType = CreateSimpleContentType(alias, name, groupedCollection);
|
||||
|
||||
@@ -2542,9 +2542,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.0\x86\*.* "$(TargetDir)x86\"
|
||||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>7200</DevelopmentServerPort>
|
||||
<DevelopmentServerPort>7210</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:7200</IISUrl>
|
||||
<IISUrl>http://localhost:7210</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
|
||||
@@ -130,7 +130,7 @@
|
||||
<create assembly="umbraco" type="MediaTypeTasks" />
|
||||
<delete assembly="umbraco" type="MediaTypeTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
</nodeType>
|
||||
<nodeType alias="initmember">
|
||||
<header>member</header>
|
||||
<usercontrol>/create/member.ascx</usercontrol>
|
||||
@@ -324,7 +324,7 @@
|
||||
</nodeType>
|
||||
<nodeType alias="partialViews">
|
||||
<header>Macro</header>
|
||||
<usercontrol>/Create/PartialView.ascx</usercontrol>
|
||||
<usercontrol>/Create/PartialView.ascx</usercontrol>
|
||||
<tasks>
|
||||
<create assembly="umbraco" type="PartialViewTasks" />
|
||||
<delete assembly="umbraco" type="PartialViewTasks" />
|
||||
@@ -338,4 +338,20 @@
|
||||
<delete assembly="umbraco" type="PartialViewMacroTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
<nodeType alias="partialViewsFolder">
|
||||
<header>Macro</header>
|
||||
<usercontrol>/Create/PartialView.ascx</usercontrol>
|
||||
<tasks>
|
||||
<create assembly="umbraco" type="PartialViewTasks" />
|
||||
<delete assembly="umbraco" type="PartialViewTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
<nodeType alias="partialViewMacrosFolder">
|
||||
<header>Macro</header>
|
||||
<usercontrol>/Create/PartialViewMacro.ascx</usercontrol>
|
||||
<tasks>
|
||||
<create assembly="umbraco" type="PartialViewMacroTasks" />
|
||||
<delete assembly="umbraco" type="PartialViewMacroTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
</createUI>
|
||||
|
||||
@@ -330,14 +330,6 @@
|
||||
<delete assembly="umbraco" type="PartialViewTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
<nodeType alias="partialViewsFolder">
|
||||
<header>Macro</header>
|
||||
<usercontrol>/Create/PartialView.ascx</usercontrol>
|
||||
<tasks>
|
||||
<create assembly="umbraco" type="PartialViewTasks" />
|
||||
<delete assembly="umbraco" type="PartialViewTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
<nodeType alias="partialViewMacros">
|
||||
<header>Macro</header>
|
||||
<usercontrol>/Create/PartialViewMacro.ascx</usercontrol>
|
||||
@@ -346,6 +338,14 @@
|
||||
<delete assembly="umbraco" type="PartialViewMacroTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
<nodeType alias="partialViewsFolder">
|
||||
<header>Macro</header>
|
||||
<usercontrol>/Create/PartialView.ascx</usercontrol>
|
||||
<tasks>
|
||||
<create assembly="umbraco" type="PartialViewTasks" />
|
||||
<delete assembly="umbraco" type="PartialViewTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
<nodeType alias="partialViewMacrosFolder">
|
||||
<header>Macro</header>
|
||||
<usercontrol>/Create/PartialViewMacro.ascx</usercontrol>
|
||||
|
||||
@@ -415,7 +415,7 @@ namespace Umbraco.Web.Security
|
||||
if (member != null)
|
||||
{
|
||||
var propValue = member.Properties[prop.Alias];
|
||||
if (propValue != null)
|
||||
if (propValue != null && propValue.Value != null)
|
||||
{
|
||||
value = propValue.Value.ToString();
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ namespace Umbraco.Web.Security.Providers
|
||||
private string _defaultMemberTypeAlias = "Member";
|
||||
private volatile bool _hasDefaultMember = false;
|
||||
private static readonly object Locker = new object();
|
||||
private bool _providerKeyAsGuid = false;
|
||||
|
||||
public override string ProviderName
|
||||
{
|
||||
@@ -58,7 +59,7 @@ namespace Umbraco.Web.Security.Providers
|
||||
|
||||
protected override MembershipUser ConvertToMembershipUser(IMember entity)
|
||||
{
|
||||
return entity.AsConcreteMembershipUser(Name);
|
||||
return entity.AsConcreteMembershipUser(Name, _providerKeyAsGuid);
|
||||
}
|
||||
|
||||
public string LockPropertyTypeAlias { get; private set; }
|
||||
@@ -85,6 +86,15 @@ namespace Umbraco.Web.Security.Providers
|
||||
}
|
||||
_hasDefaultMember = true;
|
||||
}
|
||||
|
||||
//devs can configure the provider user key to be a guid if they want, by default it is int
|
||||
if (config["providerKeyType"] != null)
|
||||
{
|
||||
if (config["providerKeyType"] == "guid")
|
||||
{
|
||||
_providerKeyAsGuid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string DefaultMemberTypeAlias
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace Umbraco.Web.Security.Providers
|
||||
protected override MembershipUser ConvertToMembershipUser(IUser entity)
|
||||
{
|
||||
//the provider user key is always the int id
|
||||
return entity.AsConcreteMembershipUser(Name);
|
||||
return entity.AsConcreteMembershipUser(Name, true);
|
||||
}
|
||||
|
||||
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
|
||||
|
||||
@@ -500,15 +500,18 @@ namespace umbraco
|
||||
() => GetMediaDo(MediaId, Deep));
|
||||
|
||||
if (xml != null)
|
||||
{
|
||||
return FromXElement(xml, xml.Attribute("nodeTypeAlias").Value);
|
||||
{
|
||||
//returning the root element of the Media item fixes the problem
|
||||
return xml.CreateNavigator().Select("/");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
var xml = GetMediaDo(MediaId, Deep);
|
||||
return FromXElement(xml, xml.Attribute("nodeTypeAlias").Value);
|
||||
|
||||
//returning the root element of the Media item fixes the problem
|
||||
return xml.CreateNavigator().Select("/");
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
@@ -536,15 +539,6 @@ namespace umbraco
|
||||
return serialized;
|
||||
}
|
||||
|
||||
private static XPathNodeIterator FromXElement(XNode xml, string mediaContentType)
|
||||
{
|
||||
var xp = xml.CreateNavigator();
|
||||
var xpath = UmbracoConfig.For.UmbracoSettings().Content.UseLegacyXmlSchema
|
||||
? "/node"
|
||||
: String.Format("/{0}", Casing.SafeAliasWithForcingCheck(mediaContentType));
|
||||
return xp.Select(xpath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a member as an xml object
|
||||
/// </summary>
|
||||
|
||||
+75
-60
@@ -16,6 +16,7 @@ using System.Web.UI.WebControls;
|
||||
using ClientDependency.Core;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Strings;
|
||||
@@ -308,7 +309,7 @@ namespace umbraco.controls
|
||||
Trace.Write("ContentTypeControlNew", "executing task");
|
||||
|
||||
//we need to re-set the UmbracoContext since it will be nulled and our cache handlers need it
|
||||
//global::Umbraco.Web.UmbracoContext.Current = asyncState.UmbracoContext;
|
||||
global::Umbraco.Web.UmbracoContext.Current = asyncState.UmbracoContext;
|
||||
|
||||
_contentType.ContentTypeItem.Name = txtName.Text;
|
||||
_contentType.ContentTypeItem.Alias = txtAlias.Text; // raw, contentType.Alias takes care of it
|
||||
@@ -322,56 +323,71 @@ namespace umbraco.controls
|
||||
var ids = SaveAllowedChildTypes();
|
||||
_contentType.ContentTypeItem.AllowedContentTypes = ids.Select(x => new ContentTypeSort {Id = new Lazy<int>(() => x), SortOrder = i++});
|
||||
|
||||
//Saving ContentType Compositions
|
||||
var compositionIds = SaveCompositionContentTypes();
|
||||
var existingCompsitionIds = _contentType.ContentTypeItem.CompositionIds().ToList();
|
||||
if (compositionIds.Any())
|
||||
// figure out whether compositions are locked
|
||||
var allContentTypes = Request.Path.ToLowerInvariant().Contains("editmediatype.aspx")
|
||||
? ApplicationContext.Services.ContentTypeService.GetAllMediaTypes().Cast<IContentTypeComposition>().ToArray()
|
||||
: ApplicationContext.Services.ContentTypeService.GetAllContentTypes().Cast<IContentTypeComposition>().ToArray();
|
||||
var isUsing = allContentTypes.Where(x => x.ContentTypeComposition.Any(y => y.Id == _contentType.Id)).ToArray();
|
||||
|
||||
// if compositions are locked, do nothing (leave them as they are)
|
||||
// else process the checkbox list and add/remove compositions accordingly
|
||||
|
||||
if (isUsing.Length == 0)
|
||||
{
|
||||
//Iterate ContentType Ids from the save-collection
|
||||
foreach (var compositionId in compositionIds)
|
||||
//Saving ContentType Compositions
|
||||
var compositionIds = SaveCompositionContentTypes();
|
||||
var existingCompsitionIds = _contentType.ContentTypeItem.CompositionIds().ToList();
|
||||
if (compositionIds.Any())
|
||||
{
|
||||
//If the compositionId is the Id of the current ContentType we skip it
|
||||
if(_contentType.Id.Equals(compositionId)) continue;
|
||||
// if some compositions were checked in the list, iterate over them
|
||||
foreach (var compositionId in compositionIds)
|
||||
{
|
||||
// ignore if it is the current content type
|
||||
if (_contentType.Id.Equals(compositionId)) continue;
|
||||
|
||||
//If the Id already exists we'll just skip it
|
||||
if (existingCompsitionIds.Any(x => x.Equals(compositionId))) continue;
|
||||
// ignore if it is already a composition of the content type
|
||||
if (existingCompsitionIds.Any(x => x.Equals(compositionId))) continue;
|
||||
|
||||
//New Ids will get added to the collection
|
||||
var compositionType = isMediaType
|
||||
? Services.ContentTypeService.GetMediaType(compositionId)
|
||||
.SafeCast<IContentTypeComposition>()
|
||||
: Services.ContentTypeService.GetContentType(compositionId)
|
||||
.SafeCast<IContentTypeComposition>();
|
||||
var added = _contentType.ContentTypeItem.AddContentType(compositionType);
|
||||
//TODO if added=false then return error message
|
||||
// add to the content type compositions
|
||||
var compositionType = isMediaType
|
||||
? Services.ContentTypeService.GetMediaType(compositionId).SafeCast<IContentTypeComposition>()
|
||||
: Services.ContentTypeService.GetContentType(compositionId).SafeCast<IContentTypeComposition>();
|
||||
try
|
||||
{
|
||||
//TODO if added=false then return error message
|
||||
var added = _contentType.ContentTypeItem.AddContentType(compositionType);
|
||||
}
|
||||
catch (InvalidCompositionException ex)
|
||||
{
|
||||
state.SaveArgs.IconType = BasePage.speechBubbleIcon.error;
|
||||
state.SaveArgs.Message = ex.Message;
|
||||
}
|
||||
}
|
||||
|
||||
// then iterate over removed = existing except checked
|
||||
var removeIds = existingCompsitionIds.Except(compositionIds);
|
||||
foreach (var removeId in removeIds)
|
||||
{
|
||||
// and remove from the content type composition
|
||||
var compositionType = isMediaType
|
||||
? Services.ContentTypeService.GetMediaType(removeId).SafeCast<IContentTypeComposition>()
|
||||
: Services.ContentTypeService.GetContentType(removeId).SafeCast<IContentTypeComposition>();
|
||||
var removed = _contentType.ContentTypeItem.RemoveContentType(compositionType.Alias);
|
||||
}
|
||||
}
|
||||
|
||||
//Iterate the set except of existing and new Ids
|
||||
var removeIds = existingCompsitionIds.Except(compositionIds);
|
||||
foreach (var removeId in removeIds)
|
||||
else if (existingCompsitionIds.Any())
|
||||
{
|
||||
//Remove ContentTypes that was deselected in the list
|
||||
var compositionType = isMediaType
|
||||
? Services.ContentTypeService.GetMediaType(removeId)
|
||||
.SafeCast<IContentTypeComposition>()
|
||||
: Services.ContentTypeService.GetContentType(removeId)
|
||||
.SafeCast<IContentTypeComposition>();
|
||||
var removed = _contentType.ContentTypeItem.RemoveContentType(compositionType.Alias);
|
||||
}
|
||||
}
|
||||
else if (existingCompsitionIds.Any())
|
||||
{
|
||||
//Iterate the set except of existing and new Ids
|
||||
var removeIds = existingCompsitionIds.Except(compositionIds);
|
||||
foreach (var removeId in removeIds)
|
||||
{
|
||||
//Remove ContentTypes that was deselected in the list
|
||||
var compositionType = isMediaType
|
||||
? Services.ContentTypeService.GetMediaType(removeId)
|
||||
.SafeCast<IContentTypeComposition>()
|
||||
: Services.ContentTypeService.GetContentType(removeId)
|
||||
.SafeCast<IContentTypeComposition>();
|
||||
var removed = _contentType.ContentTypeItem.RemoveContentType(compositionType.Alias);
|
||||
// else none were checked - if the content type had compositions,
|
||||
// iterate over them all and remove them
|
||||
var removeIds = existingCompsitionIds.Except(compositionIds); // except here makes no sense?
|
||||
foreach (var removeId in removeIds)
|
||||
{
|
||||
// remove existing
|
||||
var compositionType = isMediaType
|
||||
? Services.ContentTypeService.GetMediaType(removeId).SafeCast<IContentTypeComposition>()
|
||||
: Services.ContentTypeService.GetContentType(removeId).SafeCast<IContentTypeComposition>();
|
||||
var removed = _contentType.ContentTypeItem.RemoveContentType(compositionType.Alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,6 +435,11 @@ namespace umbraco.controls
|
||||
state.SaveArgs.Message = ex.Message;
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
state.SaveArgs.IconType = BasePage.speechBubbleIcon.error;
|
||||
state.SaveArgs.Message = ex.Message;
|
||||
}
|
||||
|
||||
Trace.Write("ContentTypeControlNew", "task completing");
|
||||
};
|
||||
@@ -710,7 +731,7 @@ jQuery(document).ready(function() {{ refreshDropDowns(); }});
|
||||
DualContentTypeCompositions.Value = "";
|
||||
|
||||
PlaceHolderContentTypeCompositions.Controls.Add(new Literal { Text = "<em>This content type is used as a parent and/or in "
|
||||
+ "a composition, and therefore cannot be composed itself.<br /><br />"
|
||||
+ "a composition, and therefore cannot be composed itself.<br /><br />Used by: "
|
||||
+ string.Join(", ", isUsing.Select(x => x.Name))
|
||||
+ "</em>" });
|
||||
}
|
||||
@@ -795,16 +816,10 @@ jQuery(document).ready(function() {{ refreshDropDowns(); }});
|
||||
|
||||
private int[] SaveCompositionContentTypes()
|
||||
{
|
||||
var tmp = new ArrayList();
|
||||
foreach (ListItem li in lstContentTypeCompositions.Items)
|
||||
{
|
||||
if (li.Selected)
|
||||
tmp.Add(int.Parse(li.Value));
|
||||
}
|
||||
var ids = new int[tmp.Count];
|
||||
for (int i = 0; i < tmp.Count; i++) ids[i] = (int)tmp[i];
|
||||
|
||||
return ids;
|
||||
return lstContentTypeCompositions.Items.Cast<ListItem>()
|
||||
.Where(x => x.Selected)
|
||||
.Select(x => int.Parse(x.Value))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -1067,7 +1082,7 @@ jQuery(document).ready(function() {{ refreshDropDowns(); }});
|
||||
|
||||
private string GetHtmlForNoPropertiesMessageListItem()
|
||||
{
|
||||
return @"<li class=""no-properties-on-tab"">" + ui.Text("settings", "noPropertiesDefinedOnTab") + "</li></ul>";
|
||||
return @"<li class=""no-properties-on-tab"">" + ui.Text("settings", "noPropertiesDefinedOnTab", Security.CurrentUser) + "</li></ul>";
|
||||
}
|
||||
|
||||
private void SavePropertyType(SaveClickEventArgs e, IContentTypeComposition contentTypeItem)
|
||||
@@ -1121,7 +1136,7 @@ jQuery(document).ready(function() {{ refreshDropDowns(); }});
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Message = ui.Text("contentTypeDublicatePropertyType");
|
||||
e.Message = ui.Text("contentTypeDublicatePropertyType", Security.CurrentUser);
|
||||
e.IconType = BasePage.speechBubbleIcon.warning;
|
||||
}
|
||||
}
|
||||
@@ -1424,7 +1439,7 @@ jQuery(document).ready(function() {{ refreshDropDowns(); }});
|
||||
|
||||
LoadContentType();
|
||||
|
||||
var ea = new SaveClickEventArgs(ui.Text("contentTypeTabCreated"));
|
||||
var ea = new SaveClickEventArgs(ui.Text("contentTypeTabCreated", Security.CurrentUser));
|
||||
ea.IconType = BasePage.speechBubbleIcon.success;
|
||||
|
||||
RaiseBubbleEvent(new object(), ea);
|
||||
@@ -1463,7 +1478,7 @@ jQuery(document).ready(function() {{ refreshDropDowns(); }});
|
||||
|
||||
LoadContentType();
|
||||
|
||||
var ea = new SaveClickEventArgs(ui.Text("contentTypeTabDeleted"));
|
||||
var ea = new SaveClickEventArgs(ui.Text("contentTypeTabDeleted", Security.CurrentUser));
|
||||
ea.IconType = BasePage.speechBubbleIcon.success;
|
||||
|
||||
RaiseBubbleEvent(new object(), ea);
|
||||
|
||||
@@ -24,13 +24,18 @@ namespace umbraco
|
||||
//NOTE: TypeID is the parent id!
|
||||
//NOTE: ParentID is aparently a flag to determine if we are to create a template! Hack much ?! :P
|
||||
var parentId = TypeID != 0 ? TypeID : -1;
|
||||
var contentType = parentId == -1
|
||||
? new ContentType(-1)
|
||||
: new ContentType(ApplicationContext.Current.Services.ContentTypeService.GetContentType(parentId));
|
||||
contentType.CreatorId = User.Id;
|
||||
|
||||
// when creating a content type, enforce PascalCase
|
||||
// preserve separator because contentType.Alias will re-alias it
|
||||
contentType.Alias = Alias.ToCleanString(CleanStringType.Alias | CleanStringType.PascalCase, ' ');
|
||||
var cleanAlias = Alias.ToCleanString(CleanStringType.Alias | CleanStringType.PascalCase, ' ');
|
||||
|
||||
var contentType = parentId == -1
|
||||
? new ContentType(-1)
|
||||
: new ContentType(ApplicationContext.Current.Services.ContentTypeService.GetContentType(parentId), cleanAlias);
|
||||
|
||||
contentType.CreatorId = User.Id;
|
||||
|
||||
contentType.Alias = cleanAlias;
|
||||
contentType.Name = Alias.Replace("'", "''");
|
||||
contentType.Icon = ".sprTreeFolder";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user