Skip to content

Commit

Permalink
Use Decorators to mark Content Types as shared
Browse files Browse the repository at this point in the history
  • Loading branch information
iJungleboy committed Nov 22, 2021
1 parent bed83e0 commit cd4f9ed
Show file tree
Hide file tree
Showing 21 changed files with 373 additions and 152 deletions.
4 changes: 2 additions & 2 deletions ToSic.Eav.Apps/ImportExport/XmlExporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ protected void InitExportXDocument(string defaultLanguage, string moduleVersion)
: (ContentType) AppState.GetContentType(attributeSetId); // in case it's the name, not the number

// skip system/code-types
if((set.ParentId ?? 0) == Constants.PresetContentTypeFakeParent)
if (set.HasPresetAncestor()) // ((set.ParentId ?? 0) == Constants.PresetContentTypeFakeParent)
continue;

var attributes = new XElement(XmlConstants.Attributes);
Expand Down Expand Up @@ -187,7 +187,7 @@ select GetEntityXElement(c.EntityId, c.Type.StaticName)
attributes);

// Add Ghost-Info if content type inherits from another content type
if (set.ParentId.HasValue)
if (set.HasAncestor()) // .ParentId.HasValue)
{
var parentStaticName = set.StaticName;
attributeSet.Add(new XAttribute(XmlConstants.AttributeSetParentDef, parentStaticName));
Expand Down
53 changes: 27 additions & 26 deletions ToSic.Eav.Core.Tests/Types/TypesBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,33 +17,34 @@ public abstract class TypesBase: ContentType
protected const string DefInp = "default";
private const string UndefinedScope = "Undefined";

protected TypesBase(string name, string staticName, string scope = UndefinedScope) : base(0, name, staticName)
{
Scope = scope;
Description = "todo";
Attributes = new List<IContentTypeAttribute>();
//IsInstalledInPrimaryStorage = false;
RepositoryType = RepositoryTypes.Code;
ParentId = Constants.PresetContentTypeFakeParent; // important that parentid is different, so the GUI regards this as a ghost, and doesn't provide editing features
//I18nKey = i18nKey;
}
// 2021-11-22 2dm disabled all of this, don't believe it's ever used, maybe #cleanup EOY 2021
//protected TypesBase(string name, string staticName, string scope = UndefinedScope) : base(0, name, staticName)
//{
// Scope = scope;
// Description = "todo";
// Attributes = new List<IContentTypeAttribute>();
// //IsInstalledInPrimaryStorage = false;
// RepositoryType = RepositoryTypes.Code;
// ParentId = Constants.PresetContentTypeFakeParent; // important that parentid is different, so the GUI regards this as a ghost, and doesn't provide editing features
// //I18nKey = i18nKey;
//}

protected ContentTypeAttribute Add(ContentTypeAttribute attDef)
{
Attributes.Add(attDef);
return attDef;
}
//protected ContentTypeAttribute Add(ContentTypeAttribute attDef)
//{
// Attributes.Add(attDef);
// return attDef;
//}

protected ContentTypeAttribute AttDef(ValueTypes type, string input, string name, string niceName = null, string description = null, string defaultValue = null)
{
var correctedInput = type.ToString().ToLowerInvariant() + "-" + input;
var attDef = new ContentTypeAttribute(AppId, name, /* niceName, */ type.ToString(), /* correctedInput, description, true, defaultValue, */
attributeMetadata: new List<IEntity>
{
AttDefBuilder.GenerateAttributeMetadata(null /* TODO: NOW NEEDS GlobalTypes, but tests not updated */, AppId, niceName, description, true,
HelpersToRefactor.SerializeValue(defaultValue), correctedInput)
});
return attDef;
}
//protected ContentTypeAttribute AttDef(ValueTypes type, string input, string name, string niceName = null, string description = null, string defaultValue = null)
//{
// var correctedInput = type.ToString().ToLowerInvariant() + "-" + input;
// var attDef = new ContentTypeAttribute(AppId, name, /* niceName, */ type.ToString(), /* correctedInput, description, true, defaultValue, */
// attributeMetadata: new List<IEntity>
// {
// AttDefBuilder.GenerateAttributeMetadata(null /* TODO: NOW NEEDS GlobalTypes, but tests not updated */, AppId, niceName, description, true,
// HelpersToRefactor.SerializeValue(defaultValue), correctedInput)
// });
// return attDef;
//}
}
}
30 changes: 17 additions & 13 deletions ToSic.Eav.Core/Data/Builder/ContentTypeBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
using System.Collections.Generic;
using ToSic.Eav.Data.Shared;
using ToSic.Eav.Repositories;

namespace ToSic.Eav.Data.Builder
{
public static class ContentTypeBuilder
{
/// <summary>
/// Shortcut go get a new AttributeSet with Scope=System and Name=StaticName
/// </summary>
public static ContentType SystemAttributeSet(int appId, string staticName, string description,
List<IContentTypeAttribute> attributes, bool alwaysShareConfiguration = false)
=> new ContentType(appId, staticName, staticName, 0, Constants.ScopeSystem, description, null, 0, 0,
alwaysShareConfiguration)
{
Attributes = attributes
};
// 2021-11-22 2dm removed, seems unused - #cleanup EOY 2021
///// <summary>
///// Shortcut go get a new AttributeSet with Scope=System and Name=StaticName
///// </summary>
//public static ContentType SystemAttributeSet(int appId, string staticName, string description,
// List<IContentTypeAttribute> attributes, bool alwaysShareConfiguration = false)
// => new ContentType(appId, staticName, staticName, 0, Constants.ScopeSystem, description, null, 0, 0,
// alwaysShareConfiguration)
// {
// Attributes = attributes
// };

public const int DynTypeId = 1;
public const string DynTypeDefScope = Constants.ScopeSystem;
Expand All @@ -24,8 +26,7 @@ public static ContentType Fake(string typeName)
=> DynamicContentType(Constants.TransientAppId, typeName, typeName);

public static ContentType DynamicContentType(int appId, string typeName, string typeIdentifier, string scope = DynTypeDefScope)
=> new ContentType(appId, typeName, typeIdentifier, DynTypeId, scope, DynTypeDefDescription, null, 0, 0,
false)
=> new ContentType(appId, typeName, typeIdentifier, DynTypeId, scope, DynTypeDefDescription)
{
Attributes = new List<IContentTypeAttribute>(),
IsDynamic = true
Expand All @@ -39,8 +40,11 @@ public static void SetSource(this ContentType type, RepositoryTypes repoType)
public static void SetSourceAndParent(this ContentType type, RepositoryTypes repoType, int parentId, string address)
{
type.RepositoryType = repoType;
type.ParentId = parentId;
//type.ParentId = parentId;
type.RepositoryAddress = address;
var ancestorDecorator = type.GetDecorator<IAncestor>();
if (ancestorDecorator != null) ancestorDecorator.Id = parentId;
else type.Decorators.Add(new Ancestor<IContentType>(Constants.PresetIdentity, parentId));
}
}
}
11 changes: 11 additions & 0 deletions ToSic.Eav.Core/Data/ContentTypes/ContentType.Decorators.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System.Collections.Generic;

namespace ToSic.Eav.Data
{
public partial class ContentType: IHasDecorators<IContentType>
{
public List<IDecorator<IContentType>> Decorators =>
_decorators ?? (_decorators = new List<IDecorator<IContentType>>());
private List<IDecorator<IContentType>> _decorators;
}
}
29 changes: 29 additions & 0 deletions ToSic.Eav.Core/Data/ContentTypes/ContentType.Import.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using ToSic.Eav.Documentation;

namespace ToSic.Eav.Data
{
public partial class ContentType
{

#region Helpers just for creating ContentTypes which will be imported
[PrivateApi]
public void SetImportParameters(string scope, string staticName, string description, bool alwaysShareDef)
{
Scope = scope;
StaticName = staticName;
Description = description;
AlwaysShareConfiguration = alwaysShareDef;
}

// special values just needed for import / save
// todo: try to place in a sub-object to un-clutter this ContentType object
[PrivateApi]
public bool OnSaveSortAttributes { get; set; } = false;

[PrivateApi]
public string OnSaveUseParentStaticName { get; set; }


#endregion
}
}
21 changes: 21 additions & 0 deletions ToSic.Eav.Core/Data/ContentTypes/ContentType.Metadata.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;
using ToSic.Eav.Metadata;

namespace ToSic.Eav.Data
{
public partial class ContentType
{

#region Metadata

/// <inheritdoc />
public ContentTypeMetadata Metadata => _metadata ?? (_metadata = new ContentTypeMetadata(StaticName, _metaSourceFinder));

private ContentTypeMetadata _metadata;
private readonly Func<IHasMetadataSource> _metaSourceFinder;

IMetadataOf IHasMetadata.Metadata => Metadata;

#endregion
}
}
18 changes: 18 additions & 0 deletions ToSic.Eav.Core/Data/ContentTypes/ContentType.Shared.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace ToSic.Eav.Data
{
public partial class ContentType
{

#region Sharing Content Types
///// <inheritdoc />
//public int? ParentId { get; internal set; }
///// <inheritdoc />
//public int ParentAppId { get; }
///// <inheritdoc />
//public int ParentZoneId { get; }
/// <inheritdoc />
public bool AlwaysShareConfiguration { get; private set; }

#endregion
}
}
76 changes: 19 additions & 57 deletions ToSic.Eav.Core/Data/ContentTypes/ContentType.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ToSic.Eav.Apps;
using ToSic.Eav.Data.Shared;
using ToSic.Eav.Documentation;
using ToSic.Eav.Metadata;
using ToSic.Eav.Repositories;
Expand All @@ -15,7 +17,7 @@ namespace ToSic.Eav.Data
// We should actually make it PrivateApi, but other code references this, so we need to change that to IContentType,
// Otherwise docs won't generate cross-links as needed
[PrivateApi("2021-09-30 hidden now, was internal_don't use Always use the interface, not this class")]
public class ContentType : IContentType, IContentTypeShared
public partial class ContentType : IContentType, IContentTypeShared
{
#region simple properties

Expand Down Expand Up @@ -49,6 +51,8 @@ public class ContentType : IContentType, IContentTypeShared
/// <inheritdoc />
public bool IsDynamic { get; internal set; }

#endregion

/// <inheritdoc />
public bool Is(string name) => Name.Equals(name, InvariantCultureIgnoreCase) || StaticName.Equals(name, InvariantCultureIgnoreCase);

Expand All @@ -57,25 +61,13 @@ public class ContentType : IContentType, IContentTypeShared


#region New DynamicChildren Navigation - new in 12.03

/// <inheritdoc />
[PrivateApi("WIP 12.03")]
// Don't cache the result, as it could change during runtime
public string DynamicChildrenField => Metadata.GetBestValue<string>(ContentTypes.DynamicChildrenField);


#endregion

#endregion

#region Sharing Content Types
/// <inheritdoc />
public int? ParentId { get; internal set; }
/// <inheritdoc />
public int ParentAppId { get; }
/// <inheritdoc />
public int ParentZoneId { get; }
/// <inheritdoc />
public bool AlwaysShareConfiguration { get; private set; }

#endregion


Expand All @@ -87,21 +79,27 @@ public class ContentType : IContentType, IContentTypeShared
/// </summary>
[PrivateApi]
public ContentType(int appId, string name, string staticName, int attributeSetId, string scope,
string description, int? usesConfigurationOfAttributeSet,
int configZoneId, int configAppId,
bool configurationIsOmnipresent,
string description,
int? parentTypeId = null,
int configZoneId = 0,
int configAppId = 0,
bool configurationIsOmnipresent = false,
Func<IHasMetadataSource> metaSourceFinder = null): this(appId, name, staticName)
{
ContentTypeId = attributeSetId;
Description = description;
Scope = scope;

// Shared Content-Types
ParentId = usesConfigurationOfAttributeSet;
ParentZoneId = configZoneId;
ParentAppId = configAppId;
//ParentId = parentTypeId;
//ParentZoneId = configZoneId;
//ParentAppId = configAppId;
AlwaysShareConfiguration = configurationIsOmnipresent;

if (parentTypeId != null)
Decorators.Add(new Ancestor<IContentType>(new AppIdentity(configZoneId, configAppId),
parentTypeId.Value));

// Metadata
_metaSourceFinder = metaSourceFinder;
}
Expand All @@ -123,43 +121,7 @@ public ContentType(int appId, string name, string staticName = null)
#endregion


#region Helpers just for creating ContentTypes which will be imported
[PrivateApi]
public void SetImportParameters(string scope, string staticName, string description, bool alwaysShareDef)
{
Scope = scope;
StaticName = staticName;
Description = description;
AlwaysShareConfiguration = alwaysShareDef;
}

// special values just needed for import / save
// todo: try to place in a sub-object to un-clutter this ContentType object
[PrivateApi]
public bool OnSaveSortAttributes { get; set; } = false;

[PrivateApi]
public string OnSaveUseParentStaticName { get; set; }


#endregion

#region Metadata



/// <inheritdoc />
public ContentTypeMetadata Metadata
=> _metadata ?? (_metadata = new ContentTypeMetadata(StaticName, _metaSourceFinder));
//=> _metadata ?? (_metadata = ParentAppId == AppId
//? new ContentTypeMetadata(StaticName, _metaOfThisApp)
//: new ContentTypeMetadata(StaticName, _metaSourceFinder));
private ContentTypeMetadata _metadata;
//private readonly IHasMetadataSource _metaOfThisApp;
private readonly Func<IHasMetadataSource> _metaSourceFinder;

IMetadataOf IHasMetadata.Metadata => Metadata;
#endregion

}
}
19 changes: 19 additions & 0 deletions ToSic.Eav.Core/Data/ContentTypes/ContentTypeExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using ToSic.Eav.Data.Shared;

namespace ToSic.Eav.Data
{
public static class ContentTypeExtensions
{
public static bool HasAncestor(this IContentType contentType)
{
var anc = contentType.GetDecorator<IAncestor>();
return anc != null && anc.Id != 0;
}

public static bool HasPresetAncestor(this IContentType contentType)
{
var anc = contentType.GetDecorator<IAncestor>();
return anc != null && anc.Id == Constants.PresetContentTypeFakeParent;
}
}
}
24 changes: 24 additions & 0 deletions ToSic.Eav.Core/Data/ContentTypes/ContentTypeWrapper.Equality.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;

namespace ToSic.Eav.Data
{
public partial class ContentTypeWrapper : IEquatable<ContentTypeWrapper>
{
public bool Equals(ContentTypeWrapper other)
{
if (ReferenceEquals(null, other?.GetContents())) return false;
if (ReferenceEquals(this, other)) return true;
return Equals(GetContents(), other.GetContents());
}

public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((ContentTypeWrapper)obj);
}

public override int GetHashCode() => (GetContents() != null ? GetContents().GetHashCode() : 0);
}
}
Loading

0 comments on commit cd4f9ed

Please sign in to comment.