Revert "Revert "Identify element types""

This reverts commit ff6a9ba9
This commit is contained in:
Bjarke Berg
2019-01-15 15:12:59 +01:00
parent 93ba694106
commit 11ffafacdf
19 changed files with 105 additions and 10 deletions

View File

@@ -121,6 +121,7 @@ namespace Umbraco.Core.Migrations.Upgrade
To<DropTaskTables>("{648A2D5F-7467-48F8-B309-E99CEEE00E2A}"); // fixed version
To<MakeTagsVariant>("{C39BF2A7-1454-4047-BBFE-89E40F66ED63}");
To<MakeRedirectUrlVariant>("{64EBCE53-E1F0-463A-B40B-E98EFCCA8AE2}");
To<AddContentTypeIsElementColumn>("{0009109C-A0B8-4F3F-8FEB-C137BBDDA268}");
//FINAL

View File

@@ -0,0 +1,15 @@
using Umbraco.Core.Persistence.Dtos;
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
{
public class AddContentTypeIsElementColumn : MigrationBase
{
public AddContentTypeIsElementColumn(IMigrationContext context) : base(context)
{ }
public override void Migrate()
{
AddColumn<ContentTypeDto>("isElement");
}
}
}

View File

@@ -26,6 +26,7 @@ namespace Umbraco.Core.Models
private string _thumbnail = "folder.png";
private bool _allowedAsRoot; // note: only one that's not 'pure element type'
private bool _isContainer;
private bool _isElement;
private PropertyGroupCollection _propertyGroups;
private PropertyTypeCollection _noGroupPropertyTypes;
private IEnumerable<ContentTypeSort> _allowedContentTypes;
@@ -90,6 +91,7 @@ namespace Umbraco.Core.Models
public readonly PropertyInfo IconSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Icon);
public readonly PropertyInfo ThumbnailSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Thumbnail);
public readonly PropertyInfo AllowedAsRootSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, bool>(x => x.AllowedAsRoot);
public readonly PropertyInfo IsElementSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, bool>(x => x.IsElement);
public readonly PropertyInfo IsContainerSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, bool>(x => x.IsContainer);
public readonly PropertyInfo AllowedContentTypesSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, IEnumerable<ContentTypeSort>>(x => x.AllowedContentTypes);
public readonly PropertyInfo PropertyGroupsSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, PropertyGroupCollection>(x => x.PropertyGroups);
@@ -180,6 +182,14 @@ namespace Umbraco.Core.Models
set => SetPropertyValueAndDetectChanges(value, ref _isContainer, Ps.Value.IsContainerSelector);
}
/// <inheritdoc />
[DataMember]
public bool IsElement
{
get => _isElement;
set => SetPropertyValueAndDetectChanges(value, ref _isElement, Ps.Value.IsElementSelector);
}
/// <summary>
/// Gets or sets a list of integer Ids for allowed ContentTypes
/// </summary>

View File

@@ -15,7 +15,8 @@ namespace Umbraco.Core.Models
{
var type = contentType.GetType();
var itemType = PublishedItemType.Unknown;
if (typeof(IContentType).IsAssignableFrom(type)) itemType = PublishedItemType.Content;
if (contentType.IsElement) itemType = PublishedItemType.Element;
else if (typeof(IContentType).IsAssignableFrom(type)) itemType = PublishedItemType.Content;
else if (typeof(IMediaType).IsAssignableFrom(type)) itemType = PublishedItemType.Media;
else if (typeof(IMemberType).IsAssignableFrom(type)) itemType = PublishedItemType.Member;
return itemType;

View File

@@ -25,7 +25,7 @@ namespace Umbraco.Core.Models
/// the icon (eg. <c>icon-home</c>) along with an optional CSS class name representing the
/// color (eg. <c>icon-blue</c>). Put together, the value for this scenario would be
/// <c>icon-home color-blue</c>.
///
///
/// If a class name for the color isn't specified, the icon color will default to black.
/// </summary>
string Icon { get; set; }
@@ -48,6 +48,16 @@ namespace Umbraco.Core.Models
/// </remarks>
bool IsContainer { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this content type is for an element.
/// </summary>
/// <remarks>
/// <para>By default a content type is for a true media, member or document, but
/// it can also be for an element, ie a subset that can for instance be used in
/// nested content.</para>
/// </remarks>
bool IsElement { get; set; }
/// <summary>
/// Gets or sets the content variation of the content type.
/// </summary>

View File

@@ -4,13 +4,18 @@
/// The type of published element.
/// </summary>
/// <remarks>Can be a simple element, or a document, a media, a member.</remarks>
public enum PublishedItemType // fixme - need to rename to PublishedElementType but then conflicts?
public enum PublishedItemType
{
/// <summary>
/// Unknown.
/// </summary>
Unknown = 0,
/// <summary>
/// An element.
/// </summary>
Element,
/// <summary>
/// A document.
/// </summary>

View File

@@ -41,6 +41,10 @@ namespace Umbraco.Core.Persistence.Dtos
[Constraint(Default = "0")]
public bool IsContainer { get; set; }
[Column("isElement")]
[Constraint(Default = "0")]
public bool IsElement { get; set; }
[Column("allowAtRoot")]
[Constraint(Default = "0")]
public bool AllowAtRoot { get; set; }

View File

@@ -107,6 +107,7 @@ namespace Umbraco.Core.Persistence.Factories
entity.CreatorId = dto.NodeDto.UserId ?? Constants.Security.UnknownUserId;
entity.AllowedAsRoot = dto.AllowAtRoot;
entity.IsContainer = dto.IsContainer;
entity.IsElement = dto.IsElement;
entity.Trashed = dto.NodeDto.Trashed;
entity.Variations = (ContentVariation) dto.Variations;
}
@@ -132,6 +133,7 @@ namespace Umbraco.Core.Persistence.Factories
NodeId = entity.Id,
AllowAtRoot = entity.AllowedAsRoot,
IsContainer = entity.IsContainer,
IsElement = entity.IsElement,
Variations = (byte) entity.Variations,
NodeDto = BuildNodeDto(entity, nodeObjectType)
};

View File

@@ -35,6 +35,7 @@ namespace Umbraco.Core.Persistence.Mappers
CacheMap<ContentType, ContentTypeDto>(src => src.Description, dto => dto.Description);
CacheMap<ContentType, ContentTypeDto>(src => src.Icon, dto => dto.Icon);
CacheMap<ContentType, ContentTypeDto>(src => src.IsContainer, dto => dto.IsContainer);
CacheMap<ContentType, ContentTypeDto>(src => src.IsElement, dto => dto.IsElement);
CacheMap<ContentType, ContentTypeDto>(src => src.Thumbnail, dto => dto.Thumbnail);
}
}

View File

@@ -35,6 +35,7 @@ namespace Umbraco.Core.Persistence.Mappers
CacheMap<MediaType, ContentTypeDto>(src => src.Description, dto => dto.Description);
CacheMap<MediaType, ContentTypeDto>(src => src.Icon, dto => dto.Icon);
CacheMap<MediaType, ContentTypeDto>(src => src.IsContainer, dto => dto.IsContainer);
CacheMap<MediaType, ContentTypeDto>(src => src.IsElement, dto => dto.IsElement);
CacheMap<MediaType, ContentTypeDto>(src => src.Thumbnail, dto => dto.Thumbnail);
}
}

View File

@@ -35,6 +35,7 @@ namespace Umbraco.Core.Persistence.Mappers
CacheMap<MemberType, ContentTypeDto>(src => src.Description, dto => dto.Description);
CacheMap<MemberType, ContentTypeDto>(src => src.Icon, dto => dto.Icon);
CacheMap<MemberType, ContentTypeDto>(src => src.IsContainer, dto => dto.IsContainer);
CacheMap<MemberType, ContentTypeDto>(src => src.IsElement, dto => dto.IsElement);
CacheMap<MemberType, ContentTypeDto>(src => src.Thumbnail, dto => dto.Thumbnail);
}
}

View File

@@ -1283,7 +1283,7 @@ AND umbracoNode.id <> @id",
if (db == null) throw new ArgumentNullException(nameof(db));
var sql = @"SELECT cmsContentType.pk as ctPk, cmsContentType.alias as ctAlias, cmsContentType.allowAtRoot as ctAllowAtRoot, cmsContentType.description as ctDesc, cmsContentType.variations as ctVariations,
cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb,
cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.IsElement as ctIsElement, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb,
AllowedTypes.AllowedId as ctaAllowedId, AllowedTypes.SortOrder as ctaSortOrder, AllowedTypes.alias as ctaAlias,
ParentTypes.parentContentTypeId as chtParentId, ParentTypes.parentContentTypeKey as chtParentKey,
umbracoNode.createDate as nCreateDate, umbracoNode." + sqlSyntax.GetQuotedColumnName("level") + @" as nLevel, umbracoNode.nodeObjectType as nObjectType, umbracoNode.nodeUser as nUser,
@@ -1384,6 +1384,7 @@ AND umbracoNode.id <> @id",
Description = currCt.ctDesc,
Icon = currCt.ctIcon,
IsContainer = currCt.ctIsContainer,
IsElement = currCt.ctIsElement,
NodeId = currCt.ctId,
PrimaryKey = currCt.ctPk,
Thumbnail = currCt.ctThumb,
@@ -1422,7 +1423,7 @@ AND umbracoNode.id <> @id",
var sql = @"SELECT cmsDocumentType.IsDefault as dtIsDefault, cmsDocumentType.templateNodeId as dtTemplateId,
cmsContentType.pk as ctPk, cmsContentType.alias as ctAlias, cmsContentType.allowAtRoot as ctAllowAtRoot, cmsContentType.description as ctDesc, cmsContentType.variations as ctVariations,
cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb,
cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.IsElement as ctIsElement, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb,
AllowedTypes.AllowedId as ctaAllowedId, AllowedTypes.SortOrder as ctaSortOrder, AllowedTypes.alias as ctaAlias,
ParentTypes.parentContentTypeId as chtParentId,ParentTypes.parentContentTypeKey as chtParentKey,
umbracoNode.createDate as nCreateDate, umbracoNode." + sqlSyntax.GetQuotedColumnName("level") + @" as nLevel, umbracoNode.nodeObjectType as nObjectType, umbracoNode.nodeUser as nUser,
@@ -1559,6 +1560,7 @@ AND umbracoNode.id <> @id",
Description = currCt.ctDesc,
Icon = currCt.ctIcon,
IsContainer = currCt.ctIsContainer,
IsElement = currCt.ctIsElement,
NodeId = currCt.ctId,
PrimaryKey = currCt.ctPk,
Thumbnail = currCt.ctThumb,

View File

@@ -337,7 +337,8 @@ namespace Umbraco.Core.Services
new XElement("Thumbnail", contentType.Thumbnail),
new XElement("Description", contentType.Description),
new XElement("AllowAtRoot", contentType.AllowedAsRoot.ToString()),
new XElement("IsListView", contentType.IsContainer.ToString()));
new XElement("IsListView", contentType.IsContainer.ToString()),
new XElement("IsElement", contentType.IsElement.ToString()));
var masterContentType = contentType.ContentTypeComposition.FirstOrDefault(x => x.Id == contentType.ParentId);
if(masterContentType != null)

View File

@@ -578,6 +578,10 @@ namespace Umbraco.Core.Services.Implement
if (isListView != null)
contentType.IsContainer = isListView.Value.InvariantEquals("true");
var isElement = infoElement.Element("IsElement");
if (isListView != null)
contentType.IsElement = isElement.Value.InvariantEquals("true");
//Name of the master corresponds to the parent and we need to ensure that the Parent Id is set
var masterElement = infoElement.Element("Master");
if (masterElement != null)

View File

@@ -377,6 +377,7 @@
<Compile Include="Migrations\Upgrade\V_7_9_0\AddUmbracoAuditTable.cs" />
<Compile Include="Migrations\Upgrade\V_7_9_0\AddUmbracoConsentTable.cs" />
<Compile Include="Migrations\Upgrade\V_7_9_0\CreateSensitiveDataUserGroup.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\AddContentTypeIsElementColumn.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\AddLogTableColumns.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\AddTypedLabels.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\AddVariationTables1A.cs" />

View File

@@ -233,7 +233,6 @@ namespace Umbraco.Tests.PublishedContent
}
[Test]
[Ignore("Fails as long as PublishedContentModel is internal.")] // fixme
public void Is_Last_From_Where_Filter2()
{
var doc = GetNode(1173);

View File

@@ -22,6 +22,36 @@ namespace Umbraco.Tests.Services
[UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, PublishedRepositoryEvents = true)]
public class ContentTypeServiceTests : TestWithSomeContentBase
{
[Test]
public void CanSaveAndGetIsElement()
{
//create content type with a property type that varies by culture
IContentType contentType = MockedContentTypes.CreateBasicContentType();
contentType.Variations = ContentVariation.Nothing;
var contentCollection = new PropertyTypeCollection(true);
contentCollection.Add(new PropertyType("test", ValueStorageType.Ntext)
{
Alias = "title",
Name = "Title",
Description = "",
Mandatory = false,
SortOrder = 1,
DataTypeId = -88,
Variations = ContentVariation.Nothing
});
contentType.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = "Content", SortOrder = 1 });
ServiceContext.ContentTypeService.Save(contentType);
contentType = ServiceContext.ContentTypeService.Get(contentType.Id);
Assert.IsFalse(contentType.IsElement);
contentType.IsElement = true;
ServiceContext.ContentTypeService.Save(contentType);
contentType = ServiceContext.ContentTypeService.Get(contentType.Id);
Assert.IsTrue(contentType.IsElement);
}
[Test]
public void Change_Content_Type_Variation_Clears_Redirects()
{

View File

@@ -86,6 +86,12 @@ namespace Umbraco.Web.Models.ContentEditing
[DataMember(Name = "isContainer")]
public bool IsContainer { get; set; }
/// <summary>
/// Indicates if the content is configured as an element
/// </summary>
[DataMember(Name = "isElement")]
public bool IsElement { get; set; }
/// <summary>
/// Property indicating if this item is part of a list view parent
/// </summary>
@@ -117,7 +123,7 @@ namespace Umbraco.Web.Models.ContentEditing
/// </remarks>
[DataMember(Name = "updateDate")]
public DateTime UpdateDate { get; set; }
[DataMember(Name = "template")]
public string TemplateAlias { get; set; }

View File

@@ -46,6 +46,7 @@ namespace Umbraco.Web.Models.Mapping
.ForMember(dest => dest.ContentTypeAlias, opt => opt.MapFrom(src => src.ContentType.Alias))
.ForMember(dest => dest.ContentTypeName, opt => opt.MapFrom(src => src.ContentType.Name))
.ForMember(dest => dest.IsContainer, opt => opt.MapFrom(src => src.ContentType.IsContainer))
.ForMember(dest => dest.IsElement, opt => opt.MapFrom(src => src.ContentType.IsElement))
.ForMember(dest => dest.IsBlueprint, opt => opt.MapFrom(src => src.Blueprint))
.ForMember(dest => dest.IsChildOfListView, opt => opt.ResolveUsing(childOfListViewResolver))
.ForMember(dest => dest.Trashed, opt => opt.MapFrom(src => src.Trashed))
@@ -59,7 +60,7 @@ namespace Umbraco.Web.Models.Mapping
.ForMember(dest => dest.AllowedTemplates, opt =>
opt.MapFrom(content => content.ContentType.AllowedTemplates
.Where(t => t.Alias.IsNullOrWhiteSpace() == false && t.Name.IsNullOrWhiteSpace() == false)
.ToDictionary(t => t.Alias, t => t.Name)))
.ToDictionary(t => t.Alias, t => t.Name)))
.ForMember(dest => dest.AllowedActions, opt => opt.ResolveUsing(src => actionButtonsResolver.Resolve(src)))
.ForMember(dest => dest.AdditionalData, opt => opt.Ignore());
@@ -140,5 +141,5 @@ namespace Umbraco.Web.Models.Mapping
return source.CultureInfos.TryGetValue(culture, out var name) && !name.Name.IsNullOrWhiteSpace() ? name.Name : $"(({source.Name}))";
}
}
}
}
}