Skip to content

Adds selective Element Model Attributes #231

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: v8/dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added src/._SolutionInfo.cs
Binary file not shown.
22 changes: 19 additions & 3 deletions src/Umbraco.ModelsBuilder/Building/Builder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -329,11 +329,27 @@ public string GetModelsNamespace()
protected string GetModelsBaseClassName(TypeModel type)
{
// code attribute overrides everything
if (ParseResult.HasModelsBaseClassName)
if (ParseResult.HasModelsBaseClassName && !type.IsElement && !ParseResult.HasSelectiveModelsBaseClassName(type.Alias))
return ParseResult.ModelsBaseClassName;

// default
return type.IsElement ? "PublishedElementModel" : "PublishedContentModel";
if (ParseResult.HasElementModelsBaseClassName && type.IsElement && !ParseResult.HasSelectiveElementsModelsBaseClassName(type.Alias))
return ParseResult.ElementModelsBaseClassName;

if (ParseResult.HasSelectiveModelsBaseClassName(type.Alias) && !type.IsElement) {
var selectiveBaseClass = ParseResult.GetSelectiveModelsBaseClassName(type.Alias);
if (!string.IsNullOrEmpty(selectiveBaseClass))
return selectiveBaseClass;
}

if (ParseResult.HasSelectiveElementsModelsBaseClassName(type.Alias) && type.IsElement)
{
var selectiveBaseClass = ParseResult.GetSelectiveElementsModelsBaseClassName(type.Alias);
if (!string.IsNullOrEmpty(selectiveBaseClass))
return selectiveBaseClass;
}

// default
return type.IsElement ? "PublishedElementModel" : "PublishedContentModel";
}
}
}
25 changes: 24 additions & 1 deletion src/Umbraco.ModelsBuilder/Building/CodeParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,22 @@ private static void ParseAssemblySymbols(ParseResult disco, ISymbol symbol)
disco.SetModelsBaseClassName(SymbolDisplay.ToDisplayString(modelsBaseClass));
break;

case "Umbraco.ModelsBuilder.ModelsNamespaceAttribute":
case "Umbraco.ModelsBuilder.ElementModelsBaseClassAttribute":
var elementModelsBaseClass = (INamedTypeSymbol)attrData.ConstructorArguments[0].Value;
if (elementModelsBaseClass is IErrorTypeSymbol)
throw new Exception($"Invalid base class type \"{elementModelsBaseClass.Name}\".");
disco.SetElementModelsBaseClassName(SymbolDisplay.ToDisplayString(elementModelsBaseClass));
break;

case "Umbraco.ModelsBuilder.SelectiveElementModelsBaseClassAttribute":
var selectiveElementModelsBaseClass = (INamedTypeSymbol)attrData.ConstructorArguments[0].Value;
if (selectiveElementModelsBaseClass is IErrorTypeSymbol)
throw new Exception($"Invalid base class type \"{selectiveElementModelsBaseClass.Name}\".");
var elementAliasToInclude = (string)attrData.ConstructorArguments[1].Value;
disco.SetSelectiveElement(elementAliasToInclude, SymbolDisplay.ToDisplayString(selectiveElementModelsBaseClass));
break;

case "Umbraco.ModelsBuilder.ModelsNamespaceAttribute":
var modelsNamespace= (string) attrData.ConstructorArguments[0].Value;
disco.SetModelsNamespace(modelsNamespace);
break;
Expand All @@ -205,6 +220,14 @@ private static void ParseAssemblySymbols(ParseResult disco, ISymbol symbol)
var usingNamespace = (string)attrData.ConstructorArguments[0].Value;
disco.SetUsingNamespace(usingNamespace);
break;
case "Umbraco.ModelsBuilder.SelectiveModelsBaseClassAttribute":
var selectiveModelsBaseClass = (INamedTypeSymbol)attrData.ConstructorArguments[0].Value;
if (selectiveModelsBaseClass is IErrorTypeSymbol)
throw new Exception($"Invalid base class type \"{selectiveModelsBaseClass.Name}\".");
var contentAliasToInclude = (string)attrData.ConstructorArguments[1].Value;
disco.SetSelectiveContent(contentAliasToInclude, SymbolDisplay.ToDisplayString(selectiveModelsBaseClass));
break;

}
}
}
Expand Down
137 changes: 133 additions & 4 deletions src/Umbraco.ModelsBuilder/Building/ParseResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ private readonly Dictionary<string, List<StaticMixinMethodInfo>> _staticMixins
private readonly HashSet<string> _withCtor
= new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);

private Dictionary<string, string> _selectiveModelsBaseClassNameOverides = new Dictionary<string, string>();
private Dictionary<string, string> _selectiveElementsModelsBaseClassNameOverides = new Dictionary<string, string>();

public static readonly ParseResult Empty = new ParseResult();

private class StaticMixinMethodInfo
Expand Down Expand Up @@ -80,8 +83,24 @@ public void SetIgnoredContent(string contentAlias /*, bool ignoreContent, bool i
// _ignoredMixinProperties.Add(contentAlias);
}

// content with that alias should be generated with a different name
public void SetRenamedContent(string contentAlias, string contentName, bool withImplement)
// content with that alias should included to be generated
// alias can end with a * (wildcard)
public void SetSelectiveContent(string contentAlias, string baseClassName)
{
if (!_selectiveModelsBaseClassNameOverides.ContainsKey(contentAlias))
_selectiveModelsBaseClassNameOverides.Add(contentAlias, baseClassName);
}

// element with that alias should included to be generated
// alias can end with a * (wildcard)
public void SetSelectiveElement(string contentAlias, string baseClassName)
{
if (!_selectiveElementsModelsBaseClassNameOverides.ContainsKey(contentAlias))
_selectiveElementsModelsBaseClassNameOverides.Add(contentAlias, baseClassName);
}

// content with that alias should be generated with a different name
public void SetRenamedContent(string contentAlias, string contentName, bool withImplement)
{
_renamedContent[contentAlias] = contentName;
if (withImplement)
Expand Down Expand Up @@ -129,7 +148,13 @@ public void SetModelsBaseClassName(string modelsBaseClassName)
ModelsBaseClassName = modelsBaseClassName;
}

public void SetModelsNamespace(string modelsNamespace)
public void SetElementModelsBaseClassName(string elementModelsBaseClassName)
{
ElementModelsBaseClassName = elementModelsBaseClassName;
}


public void SetModelsNamespace(string modelsNamespace)
{
ModelsNamespace = modelsNamespace;
}
Expand Down Expand Up @@ -161,11 +186,16 @@ public bool IsIgnored(string contentAlias)
return IsContentOrMixinIgnored(contentAlias, _ignoredContent);
}

public bool IsIncluded(string contentAlias)
{
return IsContentOrMixinIncluded(contentAlias, _ignoredContent);
}

//public bool IsMixinIgnored(string contentAlias)
//{
// return IsContentOrMixinIgnored(contentAlias, _ignoredMixin);
//}

//public bool IsMixinPropertiesIgnored(string contentAlias)
//{
// return IsContentOrMixinIgnored(contentAlias, _ignoredMixinProperties);
Expand All @@ -180,6 +210,15 @@ private static bool IsContentOrMixinIgnored(string contentAlias, HashSet<string>
.Any(x => contentAlias.StartsWith(x, StringComparison.InvariantCultureIgnoreCase));
}

private static bool IsContentOrMixinIncluded(string contentAlias, HashSet<string> included)
{
if (included.Contains(contentAlias)) return true;
return included
.Where(x => x.EndsWith("*"))
.Select(x => x.Substring(0, x.Length - 1))
.Any(x => contentAlias.StartsWith(x, StringComparison.InvariantCultureIgnoreCase));
}

public bool HasContentBase(string contentName)
{
return _contentBase.ContainsKey(contentName);
Expand Down Expand Up @@ -244,7 +283,97 @@ public bool HasModelsBaseClassName
get { return !string.IsNullOrWhiteSpace(ModelsBaseClassName); }
}

public bool HasSelectiveModelsBaseClassName(string key)
{
if (_selectiveModelsBaseClassNameOverides.ContainsKey(key))
return true;

return _selectiveModelsBaseClassNameOverides.Keys.Any(x =>
{
if (x.StartsWith("*"))
{
return key.EndsWith(x.Replace("*", string.Empty));
}
return key.StartsWith(x.Replace("*", string.Empty));
});
}



public string GetSelectiveModelsBaseClassName(string key)
{
if (_selectiveModelsBaseClassNameOverides.ContainsKey(key))
{
return _selectiveModelsBaseClassNameOverides[key];
}

var retVal = _selectiveModelsBaseClassNameOverides.SingleOrDefault(x =>
{
if (x.Key.StartsWith("*"))
{
return key.EndsWith(x.Key.Replace("*", string.Empty));
}
return key.StartsWith(x.Key.Replace("*", string.Empty));
});

if(!retVal.Equals(new KeyValuePair<string,string>()))
{
return retVal.Value;
}

return null;
}

public bool HasSelectiveElementsModelsBaseClassName(string key)
{
if (_selectiveElementsModelsBaseClassNameOverides.ContainsKey(key))
return true;

return _selectiveElementsModelsBaseClassNameOverides.Keys.Any(x =>
{
if (x.StartsWith("*"))
{
return key.EndsWith(x.Replace("*", string.Empty));
}
return key.StartsWith(x.Replace("*", string.Empty));
});
}


public string GetSelectiveElementsModelsBaseClassName(string key)
{
if (_selectiveElementsModelsBaseClassNameOverides.ContainsKey(key))
{
return _selectiveElementsModelsBaseClassNameOverides[key];
}

var retVal = _selectiveElementsModelsBaseClassNameOverides.SingleOrDefault(x =>
{
if (x.Key.StartsWith("*"))
{
return key.EndsWith(x.Key.Replace("*", string.Empty));
}
return key.StartsWith(x.Key.Replace("*", string.Empty));
});

if (!retVal.Equals(new KeyValuePair<string, string>()))
{
return retVal.Value;
}

return null;
}

public bool HasElementModelsBaseClassName
{
get { return !string.IsNullOrWhiteSpace(ElementModelsBaseClassName); }
}


public string ModelsBaseClassName { get; private set; }
public string ElementModelsBaseClassName { get; private set; }



public bool HasModelsNamespace
{
Expand Down
16 changes: 16 additions & 0 deletions src/Umbraco.ModelsBuilder/ElementModelsBaseClassAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;

namespace Umbraco.ModelsBuilder
{
/// <summary>
/// Indicates the default base class for element models.
/// </summary>
/// <remarks>Otherwise it is PublishedElementModel. Would make sense to inherit from PublishedElementModel.</remarks>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)]
public sealed class ElementModelsBaseClassAttribute : Attribute
{
public ElementModelsBaseClassAttribute(Type type)
{}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;

namespace Umbraco.ModelsBuilder
{
/// <summary>
/// Indicates the default base class for element models.
/// </summary>
/// <remarks>Otherwise it is PublishedElementModel. Would make sense to inherit from PublishedElementModel.</remarks>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)]
public sealed class SelectiveElementModelsBaseClassAttribute : Attribute
{
public SelectiveElementModelsBaseClassAttribute(Type type, string alias)
{}
}
}

16 changes: 16 additions & 0 deletions src/Umbraco.ModelsBuilder/SelectiveModelsBaseClassAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;

namespace Umbraco.ModelsBuilder
{
/// <summary>
/// Indicates the default base class for models.
/// </summary>
/// <remarks>Otherwise it is PublishedContentModel. Would make sense to inherit from PublishedContentModel.</remarks>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)]
public sealed class SelectiveModelsBaseClassAttribute : Attribute
{
public SelectiveModelsBaseClassAttribute(Type type, string alias)
{}
}
}

3 changes: 3 additions & 0 deletions src/Umbraco.ModelsBuilder/Umbraco.ModelsBuilder.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@
<Compile Include="Building\TextHeaderWriter.cs" />
<Compile Include="Configuration\ClrNameSource.cs" />
<Compile Include="Dashboard\BuilderDashboardHelper.cs" />
<Compile Include="SelectiveElementModelsBaseClassAttribute.cs" />
<Compile Include="ElementModelsBaseClassAttribute.cs" />
<Compile Include="SelectiveModelsBaseClassAttribute.cs" />
<Compile Include="ModelsBuilderAssemblyAttribute.cs" />
<Compile Include="PublishedElementExtensions.cs" />
<Compile Include="PureLiveAssemblyAttribute.cs" />
Expand Down