From 62712cef3d7bfdf19808f71589cb6cc4e623fcc3 Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 23 Nov 2017 16:30:04 +0100 Subject: [PATCH] More segment-only values --- src/Umbraco.Core/Models/Content.cs | 87 ++----------- src/Umbraco.Core/Models/ContentBase.cs | 116 ++++++++++++------ src/Umbraco.Core/Models/IContentBase.cs | 62 +++++++--- src/Umbraco.Core/Models/Property.cs | 30 +++-- src/Umbraco.Core/Models/PropertyCollection.cs | 6 + 5 files changed, 165 insertions(+), 136 deletions(-) diff --git a/src/Umbraco.Core/Models/Content.cs b/src/Umbraco.Core/Models/Content.cs index 049461522d..034c9bb91d 100644 --- a/src/Umbraco.Core/Models/Content.cs +++ b/src/Umbraco.Core/Models/Content.cs @@ -275,57 +275,14 @@ namespace Umbraco.Core.Models _publishedState = PublishedState.Publishing; } - internal virtual void CopyValues(IContentBase other, bool published = false) + internal virtual void CopyValues(IContentBase other, int? languageId, string segment, bool published = false) { // clear all existing properties - ClearEditValues(null, null); - - // copy other properties - var otherProperties = other.Properties; - foreach (var otherProperty in otherProperties) - { - var alias = otherProperty.PropertyType.Alias; - SetValue(alias, otherProperty.GetValue(published)); - } - } - - internal virtual void CopyValues(IContentBase other, int? nLanguageId, bool published = false) - { - if (!nLanguageId.HasValue) - { - CopyValues(other); - return; - } - - var languageId = nLanguageId.Value; - - // clear all existing properties - ClearEditValues(nLanguageId, null); - - // copy other properties - var otherProperties = other.Properties; - foreach (var otherProperty in otherProperties) - { - var alias = otherProperty.PropertyType.Alias; - SetValue(alias, languageId, otherProperty.GetValue(languageId, published)); - } - } - - internal virtual void CopyValues(IContentBase other, int? nLanguageId, string segment, bool published = false) - { - if (segment == null) - { - CopyValues(other, nLanguageId, published); - return; - } - - if (!nLanguageId.HasValue) - throw new ArgumentException("Cannot be null when segment is not null.", nameof(nLanguageId)); - - var languageId = nLanguageId.Value; - - // clear all existing properties - ClearEditValues(nLanguageId, segment); + // note: use property.SetValue(), don't assign pvalue.EditValue, else change tracking fails + foreach (var property in Properties) + foreach (var pvalue in property.Values) + if (pvalue.LanguageId == languageId && pvalue.Segment == segment) + property.SetValue(pvalue.LanguageId, pvalue.Segment, null); // copy other properties var otherProperties = other.Properties; @@ -336,29 +293,13 @@ namespace Umbraco.Core.Models } } - private void ClearEditValues() - { - // clear all existing properties - // note: use property.SetValue(), don't assign pvalue.EditValue, else change tracking fails - foreach (var property in Properties) - foreach (var pvalue in property.Values) - property.SetValue(pvalue.LanguageId, pvalue.Segment, null); - } - - private void ClearEditValues(int? nLanguageId, string segment) - { - // clear all existing properties - // note: use property.SetValue(), don't assign pvalue.EditValue, else change tracking fails - foreach (var property in Properties) - foreach (var pvalue in property.Values) - if (pvalue.LanguageId == nLanguageId && pvalue.Segment == segment) - property.SetValue(pvalue.LanguageId, pvalue.Segment, null); - } - internal virtual void CopyAllValues(IContentBase other, bool published = false) { // clear all existing properties - ClearEditValues(); + // note: use property.SetValue(), don't assign pvalue.EditValue, else change tracking fails + foreach (var property in Properties) + foreach (var pvalue in property.Values) + property.SetValue(pvalue.LanguageId, pvalue.Segment, null); // copy other properties var otherProperties = other.Properties; @@ -367,14 +308,8 @@ namespace Umbraco.Core.Models var alias = otherProperty.PropertyType.Alias; foreach (var pvalue in otherProperty.Values) { - // fixme can we update SetValue to accept null lang/segment and fallback? var value = published ? pvalue.PublishedValue : pvalue.EditedValue; - if (!pvalue.LanguageId.HasValue) - SetValue(alias, value); - else if (pvalue.Segment == null) - SetValue(alias, pvalue.LanguageId.Value, value); - else - SetValue(alias, pvalue.LanguageId.Value, pvalue.Segment, value); + SetValue(alias, pvalue.LanguageId, pvalue.Segment, value); } } } diff --git a/src/Umbraco.Core/Models/ContentBase.cs b/src/Umbraco.Core/Models/ContentBase.cs index 207f54c981..a981fb3387 100644 --- a/src/Umbraco.Core/Models/ContentBase.cs +++ b/src/Umbraco.Core/Models/ContentBase.cs @@ -275,23 +275,39 @@ namespace Umbraco.Core.Models /// public virtual object GetValue(string propertyTypeAlias, bool published = false) { - return Properties.Contains(propertyTypeAlias) ? Properties[propertyTypeAlias].GetValue(published) : null; + return Properties.TryGetValue(propertyTypeAlias, out var property) + ? property.GetValue(published) + : null; } /// /// Gets the culture value of a property. /// - public virtual object GetValue(string propertyTypeAlias, int languageId, bool published = false) + public virtual object GetValue(string propertyTypeAlias, int? languageId, bool published = false) { - return Properties.Contains(propertyTypeAlias) ? Properties[propertyTypeAlias].GetValue(languageId, published) : null; + return Properties.TryGetValue(propertyTypeAlias, out var property) + ? property.GetValue(languageId, null, published) + : null; } /// /// Gets the segment value of a property. /// - public virtual object GetValue(string propertyTypeAlias, int languageId, string segment, bool published = false) + public virtual object GetValue(string propertyTypeAlias, string segment, bool published = false) { - return Properties.Contains(propertyTypeAlias) ? Properties[propertyTypeAlias].GetValue(languageId, segment, published) : null; + return Properties.TryGetValue(propertyTypeAlias, out var property) + ? property.GetValue(null, segment, published) + : null; + } + + /// + /// Gets the culture+segment value of a property. + /// + public virtual object GetValue(string propertyTypeAlias, int? languageId, string segment, bool published = false) + { + return Properties.TryGetValue(propertyTypeAlias, out var property) + ? property.GetValue(languageId, segment, published) + : null; } /// @@ -299,34 +315,46 @@ namespace Umbraco.Core.Models /// public virtual TPropertyValue GetValue(string propertyTypeAlias, bool published = false) { - if (Properties.Contains(propertyTypeAlias) == false) + if (!Properties.TryGetValue(propertyTypeAlias, out var property)) return default; - var convertAttempt = Properties[propertyTypeAlias].GetValue(published).TryConvertTo(); + var convertAttempt = property.GetValue(published).TryConvertTo(); return convertAttempt.Success ? convertAttempt.Result : default; } /// /// Gets the typed culture value of a property. /// - public virtual TPropertyValue GetValue(string propertyTypeAlias, int languageId, bool published = false) + public virtual TPropertyValue GetValue(string propertyTypeAlias, int? languageId, bool published = false) { - if (Properties.Contains(propertyTypeAlias) == false) + if (!Properties.TryGetValue(propertyTypeAlias, out var property)) return default; - var convertAttempt = Properties[propertyTypeAlias].GetValue(languageId, published).TryConvertTo(); + var convertAttempt = property.GetValue(languageId, null, published).TryConvertTo(); return convertAttempt.Success ? convertAttempt.Result : default; } /// /// Gets the typed segment value of a property. /// - public virtual TPropertyValue GetValue(string propertyTypeAlias, int languageId, string segment, bool published = false) + public virtual TPropertyValue GetValue(string propertyTypeAlias, string segment, bool published = false) { - if (Properties.Contains(propertyTypeAlias) == false) + if (!Properties.TryGetValue(propertyTypeAlias, out var property)) return default; - var convertAttempt = Properties[propertyTypeAlias].GetValue(languageId, segment, published).TryConvertTo(); + var convertAttempt = property.GetValue(null, segment, published).TryConvertTo(); + return convertAttempt.Success ? convertAttempt.Result : default; + } + + /// + /// Gets the typed culture+segment value of a property. + /// + public virtual TPropertyValue GetValue(string propertyTypeAlias, int? languageId, string segment, bool published = false) + { + if (!Properties.TryGetValue(propertyTypeAlias, out var property)) + return default; + + var convertAttempt = property.GetValue(languageId, segment, published).TryConvertTo(); return convertAttempt.Success ? convertAttempt.Result : default; } @@ -348,11 +376,11 @@ namespace Umbraco.Core.Models /// /// Sets the culture (draft) value of a property. /// - public virtual void SetValue(string propertyTypeAlias, int languageId, object value) + public virtual void SetValue(string propertyTypeAlias, int? languageId, object value) { if (value == null) { - SetValueOnProperty(propertyTypeAlias, languageId, null); + SetValueOnProperty(propertyTypeAlias, languageId, null, null); return; } @@ -361,9 +389,24 @@ namespace Umbraco.Core.Models } /// - /// Sets the segment (draft) value of a property. + /// Sets the culture+segment (draft) value of a property. /// - public virtual void SetValue(string propertyTypeAlias, int languageId, string segment, object value) + public virtual void SetValue(string propertyTypeAlias, string segment, object value) + { + if (value == null) + { + SetValueOnProperty(propertyTypeAlias, null, segment, null); + return; + } + + // .NET magic to call one of the 'SetPropertyValue' handlers with matching signature + ((dynamic) this).SetPropertyValue(propertyTypeAlias, null, segment, (dynamic) value); + } + + /// + /// Sets the culture+segment (draft) value of a property. + /// + public virtual void SetValue(string propertyTypeAlias, int? languageId, string segment, object value) { if (value == null) { @@ -375,6 +418,16 @@ namespace Umbraco.Core.Models ((dynamic) this).SetPropertyValue(propertyTypeAlias, languageId, segment, (dynamic) value); } + + + + + // FIXME fix everything below + + + + + /// /// Sets the neutral (draft) string value of a Property /// @@ -595,30 +648,10 @@ namespace Umbraco.Core.Models Properties.Add(property); } - /// - /// Sets the culture (draft) value of a property. - /// - private void SetValueOnProperty(string propertyTypeAlias, int languageId, object value) - { - if (Properties.Contains(propertyTypeAlias)) - { - Properties[propertyTypeAlias].SetValue(languageId, value); - return; - } - - var propertyType = PropertyTypes.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias)); - if (propertyType == null) - throw new InvalidOperationException($"No PropertyType exists with the supplied alias \"{propertyTypeAlias}\"."); - - var property = propertyType.CreateProperty(); - property.SetValue(languageId, value); - Properties.Add(property); - } - /// /// Sets the segment (draft) value of a property. /// - private void SetValueOnProperty(string propertyTypeAlias, int languageId, string segment, object value) + private void SetValueOnProperty(string propertyTypeAlias, int? languageId, string segment, object value) { if (Properties.Contains(propertyTypeAlias)) { @@ -649,11 +682,16 @@ namespace Umbraco.Core.Models return _invalidProperties.Any() == false; } + public virtual bool Validate(int? languageId, string segment, out IEnumerable invalidProperties) + { + // fixme etc + } + /// /// Gets the properties marked as invalid during the last validation. /// [IgnoreDataMember] - internal IEnumerable InvalidProperties => _invalidProperties; + internal IEnumerable InvalidProperties => _invalidProperties; // fixme return it, don't keep it here! #endregion diff --git a/src/Umbraco.Core/Models/IContentBase.cs b/src/Umbraco.Core/Models/IContentBase.cs index 8feda0d733..ea698bff7f 100644 --- a/src/Umbraco.Core/Models/IContentBase.cs +++ b/src/Umbraco.Core/Models/IContentBase.cs @@ -48,7 +48,7 @@ namespace Umbraco.Core.Models /// /// Alias of the PropertyType /// True if Property with given alias exists, otherwise False - bool HasProperty(string propertyTypeAlias); + bool HasProperty(string propertyTypeAlias); // fixme - what does this mean???? /// /// Gets the neutral value of a Property @@ -58,12 +58,17 @@ namespace Umbraco.Core.Models /// /// Gets the culture value of a Property /// - object GetValue(string propertyTypeAlias, int languageId, bool published = false); + object GetValue(string propertyTypeAlias, int? languageId, bool published = false); /// /// Gets the segment value of a Property /// - object GetValue(string propertyTypeAlias, int languageId, string segment, bool published = false); + object GetValue(string propertyTypeAlias, string segment, bool published = false); + + /// + /// Gets the culture+segment value of a Property + /// + object GetValue(string propertyTypeAlias, int? languageId, string segment, bool published = false); /// /// Gets the typed neutral value of a Property @@ -71,34 +76,63 @@ namespace Umbraco.Core.Models TPropertyValue GetValue(string propertyTypeAlias, bool published = false); /// - /// Gets the typed neutral value of a Property + /// Gets the typed culture value of a Property /// - TPropertyValue GetValue(string propertyTypeAlias, int languageId, bool published = false); + TPropertyValue GetValue(string propertyTypeAlias, int? languageId, bool published = false); /// - /// Gets the typed neutral value of a Property + /// Gets the typed segment value of a Property /// - TPropertyValue GetValue(string propertyTypeAlias, int languageId, string segment, bool published = false); + TPropertyValue GetValue(string propertyTypeAlias, string segment, bool published = false); /// - /// Sets the neutral (draft) value of a Property + /// Gets the typed culture+segment value of a Property + /// + TPropertyValue GetValue(string propertyTypeAlias, int? languageId, string segment, bool published = false); + + /// + /// Sets the neutral (edited) value of a Property /// void SetValue(string propertyTypeAlias, object value); /// - /// Sets the culture (draft) value of a Property + /// Sets the culture (edited) value of a Property /// - void SetValue(string propertyTypeAlias, int languageId, object value); + void SetValue(string propertyTypeAlias, int? languageId, object value); /// - /// Sets the segment (draft) value of a Property + /// Sets the segment (edited) value of a Property /// - void SetValue(string propertyTypeAlias, int languageId, string segment, object value); + void SetValue(string propertyTypeAlias, string segment, object value); /// - /// Boolean indicating whether the content and its properties are valid + /// Sets the culture+segment (edited) value of a Property + /// + void SetValue(string propertyTypeAlias, int? languageId, string segment, object value); + + /// + /// Gets a value indicating whether the content and its neutral properties values are valid. /// - /// True if content is valid otherwise false bool Validate(); + + /// + /// Gets a value indicating whether the content and its culture properties values are valid. + /// + bool Validate(int? languageId); + + /// + /// Gets a value indicating whether the content and its segment properties values are valid. + /// + bool Validate(string segment); + + /// + /// Gets a value indicating whether the content and its culture+segment properties values are valid. + /// + bool Validate(int? languageId, string segment); + + /// + /// Gets a value indicating whether the content and all its properties values are valid. + /// + bool ValidateAll(); } } diff --git a/src/Umbraco.Core/Models/Property.cs b/src/Umbraco.Core/Models/Property.cs index 557a46afd9..3e20e633dc 100644 --- a/src/Umbraco.Core/Models/Property.cs +++ b/src/Umbraco.Core/Models/Property.cs @@ -91,9 +91,7 @@ namespace Umbraco.Core.Models set { _values = value; - _pvalue = value.FirstOrDefault(x => !x.LanguageId.HasValue && x.Segment == null); - _vvalues = value.ToDictionary(x => (x.LanguageId, x.Segment), x => x); } } @@ -349,7 +347,7 @@ namespace Umbraco.Core.Models } /// - /// Gets a value indicating whether the (edit) neutral value is valid. + /// Gets a value indicating whether the (edited) neutral value is valid. /// /// An invalid value can be saved, but only valid values can be published. public bool IsValid() @@ -358,23 +356,41 @@ namespace Umbraco.Core.Models } /// - /// Gets a value indicating whether the (edit) culture value is valid. + /// Gets a value indicating whether the (edited) culture value is valid. /// /// An invalid value can be saved, but only valid values can be published. - public bool IsValid(int languageId) + public bool IsValid(int? languageId) { return IsValid(GetValue(languageId)); } /// - /// Gets a value indicating whether the (edit) segment value is valid. + /// Gets a value indicating whether the (edited) segment value is valid. /// /// An invalid value can be saved, but only valid values can be published. - public bool IsValue(int languageId, string segment) + public bool IsValue(string segment) + { + return IsValid(GetValue(segment)); + } + + /// + /// Gets a value indicating whether the (edited) culture+segment value is valid. + /// + /// An invalid value can be saved, but only valid values can be published. + public bool IsValue(int? languageId, string segment) { return IsValid(GetValue(languageId, segment)); } + /// + /// Gets a value indicating whether all (edited) values are valid. + /// + /// An invalid value can be saved, but only valid values can be published. + public bool IsAllValid() + { + return _values.All(x => IsValid(x.EditedValue)); + } + /// /// Boolean indicating whether the passed in value is valid /// diff --git a/src/Umbraco.Core/Models/PropertyCollection.cs b/src/Umbraco.Core/Models/PropertyCollection.cs index 1bedf57333..9c51ddbe79 100644 --- a/src/Umbraco.Core/Models/PropertyCollection.cs +++ b/src/Umbraco.Core/Models/PropertyCollection.cs @@ -156,6 +156,12 @@ namespace Umbraco.Core.Models } } + public bool TryGetValue(string propertyTypeAlias, out Property property) + { + property = this[propertyTypeAlias]; + return property != null; + } + /// /// Occurs when the collection changes. ///