diff --git a/src/._SolutionInfo.cs b/src/._SolutionInfo.cs new file mode 100644 index 00000000..b3cbed0c Binary files /dev/null and b/src/._SolutionInfo.cs differ diff --git a/src/Umbraco.ModelsBuilder/Building/Builder.cs b/src/Umbraco.ModelsBuilder/Building/Builder.cs index bd6bef8c..80239c69 100644 --- a/src/Umbraco.ModelsBuilder/Building/Builder.cs +++ b/src/Umbraco.ModelsBuilder/Building/Builder.cs @@ -329,9 +329,18 @@ 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; + if (ParseResult.HasElementModelsBaseClassName && type.IsElement && !ParseResult.HasSelectiveModelsBaseClassName(type.Alias)) + return ParseResult.ElementModelsBaseClassName; + + if (ParseResult.HasSelectiveModelsBaseClassName(type.Alias) && !type.IsElement) { + var selectiveBaseClass = ParseResult.GetSelectiveModelsBaseClassName(type.Alias); + if (!string.IsNullOrEmpty(selectiveBaseClass)) + return selectiveBaseClass; + } + // default return type.IsElement ? "PublishedElementModel" : "PublishedContentModel"; } diff --git a/src/Umbraco.ModelsBuilder/Building/CodeParser.cs b/src/Umbraco.ModelsBuilder/Building/CodeParser.cs index 30fcbf1f..bf411926 100644 --- a/src/Umbraco.ModelsBuilder/Building/CodeParser.cs +++ b/src/Umbraco.ModelsBuilder/Building/CodeParser.cs @@ -196,6 +196,13 @@ private static void ParseAssemblySymbols(ParseResult disco, ISymbol symbol) disco.SetModelsBaseClassName(SymbolDisplay.ToDisplayString(modelsBaseClass)); break; + 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.ModelsNamespaceAttribute": var modelsNamespace= (string) attrData.ConstructorArguments[0].Value; disco.SetModelsNamespace(modelsNamespace); @@ -205,6 +212,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; + } } } diff --git a/src/Umbraco.ModelsBuilder/Building/ParseResult.cs b/src/Umbraco.ModelsBuilder/Building/ParseResult.cs index d1f61363..ffc169a3 100644 --- a/src/Umbraco.ModelsBuilder/Building/ParseResult.cs +++ b/src/Umbraco.ModelsBuilder/Building/ParseResult.cs @@ -40,6 +40,8 @@ internal class ParseResult private readonly HashSet _withCtor = new HashSet(StringComparer.InvariantCultureIgnoreCase); + private Dictionary _selectiveModelsBaseClassNameOverides = new Dictionary(); + public static readonly ParseResult Empty = new ParseResult(); private class StaticMixinMethodInfo @@ -80,6 +82,14 @@ public void SetIgnoredContent(string contentAlias /*, bool ignoreContent, bool i // _ignoredMixinProperties.Add(contentAlias); } + // 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); + } + // content with that alias should be generated with a different name public void SetRenamedContent(string contentAlias, string contentName, bool withImplement) { @@ -129,6 +139,11 @@ public void SetModelsBaseClassName(string modelsBaseClassName) ModelsBaseClassName = modelsBaseClassName; } + public void SetElementModelsBaseClassName(string elementModelsBaseClassName) + { + ElementModelsBaseClassName = elementModelsBaseClassName; + } + public void SetModelsNamespace(string modelsNamespace) { ModelsNamespace = modelsNamespace; @@ -161,11 +176,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); @@ -180,6 +200,15 @@ private static bool IsContentOrMixinIgnored(string contentAlias, HashSet .Any(x => contentAlias.StartsWith(x, StringComparison.InvariantCultureIgnoreCase)); } + private static bool IsContentOrMixinIncluded(string contentAlias, HashSet 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); @@ -244,7 +273,55 @@ 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())) + { + 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 { diff --git a/src/Umbraco.ModelsBuilder/ElementModelsBaseClassAttribute.cs b/src/Umbraco.ModelsBuilder/ElementModelsBaseClassAttribute.cs new file mode 100644 index 00000000..94e1fa3b --- /dev/null +++ b/src/Umbraco.ModelsBuilder/ElementModelsBaseClassAttribute.cs @@ -0,0 +1,16 @@ +using System; + +namespace Umbraco.ModelsBuilder +{ + /// + /// Indicates the default base class for element models. + /// + /// Otherwise it is PublishedElementModel. Would make sense to inherit from PublishedElementModel. + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)] + public sealed class ElementModelsBaseClassAttribute : Attribute + { + public ElementModelsBaseClassAttribute(Type type) + {} + } +} + diff --git a/src/Umbraco.ModelsBuilder/SelectiveModelsBaseClassAttribute.cs b/src/Umbraco.ModelsBuilder/SelectiveModelsBaseClassAttribute.cs new file mode 100644 index 00000000..920acb0c --- /dev/null +++ b/src/Umbraco.ModelsBuilder/SelectiveModelsBaseClassAttribute.cs @@ -0,0 +1,16 @@ +using System; + +namespace Umbraco.ModelsBuilder +{ + /// + /// Indicates the default base class for models. + /// + /// Otherwise it is PublishedContentModel. Would make sense to inherit from PublishedContentModel. + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)] + public sealed class SelectiveModelsBaseClassAttribute : Attribute + { + public SelectiveModelsBaseClassAttribute(Type type, string alias) + {} + } +} + diff --git a/src/Umbraco.ModelsBuilder/Umbraco.ModelsBuilder.csproj b/src/Umbraco.ModelsBuilder/Umbraco.ModelsBuilder.csproj index 2ff90a27..4fe5ab87 100644 --- a/src/Umbraco.ModelsBuilder/Umbraco.ModelsBuilder.csproj +++ b/src/Umbraco.ModelsBuilder/Umbraco.ModelsBuilder.csproj @@ -53,6 +53,8 @@ + +