diff --git a/src/Umbraco.Abstractions/Models/IProperty.cs b/src/Umbraco.Abstractions/Models/IProperty.cs
new file mode 100644
index 0000000000..308f4ae851
--- /dev/null
+++ b/src/Umbraco.Abstractions/Models/IProperty.cs
@@ -0,0 +1,100 @@
+using System;
+using System.Collections.Generic;
+using Umbraco.Core.Models.Entities;
+
+namespace Umbraco.Core.Models
+{
+ public interface IProperty
+ {
+ ///
+ /// Returns the PropertyType, which this Property is based on
+ ///
+ IPropertyType PropertyType { get; }
+
+ ///
+ /// Gets the list of values.
+ ///
+ IReadOnlyCollection Values { get; set; }
+
+ ///
+ /// Returns the Alias of the PropertyType, which this Property is based on
+ ///
+ string Alias { get; }
+
+ ///
+ int Id { get; set; }
+
+ ///
+ Guid Key { get; set; }
+
+ ///
+ DateTime CreateDate { get; set; }
+
+ ///
+ DateTime UpdateDate { get; set; }
+
+ ///
+ DateTime? DeleteDate { get; set; } // no change tracking - not persisted
+
+ ///
+ bool HasIdentity { get; }
+
+ ///
+ /// Gets the value.
+ ///
+ object GetValue(string culture = null, string segment = null, bool published = false);
+
+ ///
+ /// Sets a value.
+ ///
+ void SetValue(object value, string culture = null, string segment = null);
+
+ ///
+ /// Resets the entity identity.
+ ///
+ void ResetIdentity();
+
+ bool Equals(EntityBase other);
+ bool Equals(object obj);
+ int GetHashCode();
+ object DeepClone();
+
+ ///
+ bool IsDirty();
+
+ ///
+ bool IsPropertyDirty(string propertyName);
+
+ ///
+ IEnumerable GetDirtyProperties();
+
+ ///
+ /// Saves dirty properties so they can be checked with WasDirty.
+ void ResetDirtyProperties();
+
+ ///
+ bool WasDirty();
+
+ ///
+ bool WasPropertyDirty(string propertyName);
+
+ ///
+ void ResetWereDirtyProperties();
+
+ ///
+ void ResetDirtyProperties(bool rememberDirty);
+
+ ///
+ IEnumerable GetWereDirtyProperties();
+
+ ///
+ /// Disables change tracking.
+ ///
+ void DisableChangeTracking();
+
+ ///
+ /// Enables change tracking.
+ ///
+ void EnableChangeTracking();
+ }
+}
diff --git a/src/Umbraco.Abstractions/Models/IPropertyType.cs b/src/Umbraco.Abstractions/Models/IPropertyType.cs
new file mode 100644
index 0000000000..4447a858ab
--- /dev/null
+++ b/src/Umbraco.Abstractions/Models/IPropertyType.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Runtime.Serialization;
+using Umbraco.Core.Models.Entities;
+
+namespace Umbraco.Core.Models
+{
+ public interface IPropertyType : IEntity
+ {
+ [DataMember]
+ string Name { get; }
+ [DataMember]
+ string Alias { get; }
+ [DataMember]
+ string Description { get; }
+ [DataMember]
+ int DataTypeId { get; }
+ [DataMember]
+ Guid DataTypeKey { get; }
+ [DataMember]
+ string PropertyEditorAlias { get; }
+ [DataMember]
+ ValueStorageType ValueStorageType { get; }
+ [DataMember]
+ Lazy PropertyGroupId { get; }
+ [DataMember]
+ bool Mandatory { get; }
+ [DataMember]
+ int SortOrder { get; }
+ [DataMember]
+ string ValidationRegExp { get; }
+
+ bool SupportsPublishing { get; }
+
+ ContentVariation Variations { get; }
+
+
+
+ bool SupportsVariation(string culture, string segment, bool wildcards = false);
+ object ConvertAssignedValue(object value);
+
+
+ }
+}
diff --git a/src/Umbraco.Abstractions/Models/IPropertyValue.cs b/src/Umbraco.Abstractions/Models/IPropertyValue.cs
new file mode 100644
index 0000000000..abc459a72f
--- /dev/null
+++ b/src/Umbraco.Abstractions/Models/IPropertyValue.cs
@@ -0,0 +1,34 @@
+namespace Umbraco.Core.Models
+{
+ public interface IPropertyValue
+ {
+ ///
+ /// Gets or sets the culture of the property.
+ ///
+ /// The culture is either null (invariant) or a non-empty string. If the property is
+ /// set with an empty or whitespace value, its value is converted to null.
+ string Culture { get; set; }
+
+ ///
+ /// Gets or sets the segment of the property.
+ ///
+ /// The segment is either null (neutral) or a non-empty string. If the property is
+ /// set with an empty or whitespace value, its value is converted to null.
+ string Segment { get; set; }
+
+ ///
+ /// Gets or sets the edited value of the property.
+ ///
+ object EditedValue { get; set; }
+
+ ///
+ /// Gets or sets the published value of the property.
+ ///
+ object PublishedValue { get; set; }
+
+ ///
+ /// Clones the property value.
+ ///
+ IPropertyValue Clone();
+ }
+}
diff --git a/src/Umbraco.Core/PropertyEditors/ConfigurationFieldAttribute.cs b/src/Umbraco.Abstractions/PropertyEditors/ConfigurationFieldAttribute.cs
similarity index 100%
rename from src/Umbraco.Core/PropertyEditors/ConfigurationFieldAttribute.cs
rename to src/Umbraco.Abstractions/PropertyEditors/ConfigurationFieldAttribute.cs
diff --git a/src/Umbraco.Core/PropertyEditors/GridEditor.cs b/src/Umbraco.Abstractions/PropertyEditors/GridEditor.cs
similarity index 68%
rename from src/Umbraco.Core/PropertyEditors/GridEditor.cs
rename to src/Umbraco.Abstractions/PropertyEditors/GridEditor.cs
index 388e79675c..7af72cf5ea 100644
--- a/src/Umbraco.Core/PropertyEditors/GridEditor.cs
+++ b/src/Umbraco.Abstractions/PropertyEditors/GridEditor.cs
@@ -1,48 +1,37 @@
using System.Collections.Generic;
-using Newtonsoft.Json;
-using Umbraco.Core.Composing;
+using System.Runtime.Serialization;
using Umbraco.Core.Configuration.Grid;
-using Umbraco.Core.IO;
namespace Umbraco.Core.PropertyEditors
{
+
+ [DataContract]
public class GridEditor : IGridEditorConfig
{
- private string _view;
- private string _render;
-
public GridEditor()
{
Config = new Dictionary();
}
- [JsonProperty("name", Required = Required.Always)]
+ [DataMember(Name = "name", IsRequired = true)]
public string Name { get; set; }
- [JsonProperty("nameTemplate")]
+ [DataMember(Name = "nameTemplate")]
public string NameTemplate { get; set; }
- [JsonProperty("alias", Required = Required.Always)]
+ [DataMember(Name = "alias", IsRequired = true)]
public string Alias { get; set; }
- [JsonProperty("view", Required = Required.Always)]
- public string View
- {
- get => _view;
- set => _view = Current.IOHelper.ResolveVirtualUrl(value);
- }
+ [DataMember(Name = "view", IsRequired = true)]
+ public string View{ get; set; }
- [JsonProperty("render")]
- public string Render
- {
- get => _render;
- set => _render = Current.IOHelper.ResolveVirtualUrl(value);
- }
+ [DataMember(Name = "render")]
+ public string Render { get; set; }
- [JsonProperty("icon", Required = Required.Always)]
+ [DataMember(Name = "icon", IsRequired = true)]
public string Icon { get; set; }
- [JsonProperty("config")]
+ [DataMember(Name = "config")]
public IDictionary Config { get; set; }
protected bool Equals(GridEditor other)
diff --git a/src/Umbraco.Core/PropertyEditors/IConfigurationEditor.cs b/src/Umbraco.Abstractions/PropertyEditors/IConfigurationEditor.cs
similarity index 100%
rename from src/Umbraco.Core/PropertyEditors/IConfigurationEditor.cs
rename to src/Umbraco.Abstractions/PropertyEditors/IConfigurationEditor.cs
diff --git a/src/Umbraco.Core/CompositionExtensions_Essentials.cs b/src/Umbraco.Core/CompositionExtensions_Essentials.cs
index b85479716c..34c9492072 100644
--- a/src/Umbraco.Core/CompositionExtensions_Essentials.cs
+++ b/src/Umbraco.Core/CompositionExtensions_Essentials.cs
@@ -1,5 +1,6 @@
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
+using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;
@@ -30,6 +31,7 @@ namespace Umbraco.Core
composition.RegisterUnique(factory => factory.GetInstance().SqlContext);
composition.RegisterUnique(typeLoader);
composition.RegisterUnique(state);
+ composition.RegisterUnique();
}
}
}
diff --git a/src/Umbraco.Core/ContentVariationExtensions.cs b/src/Umbraco.Core/ContentVariationExtensions.cs
index 5b157307ab..bdcf300f3f 100644
--- a/src/Umbraco.Core/ContentVariationExtensions.cs
+++ b/src/Umbraco.Core/ContentVariationExtensions.cs
@@ -50,18 +50,18 @@ namespace Umbraco.Core
/// Determines whether the property type varies by culture.
///
/// And then it could also vary by segment.
- public static bool VariesByCulture(this PropertyType propertyType) => propertyType.Variations.VariesByCulture();
+ public static bool VariesByCulture(this IPropertyType propertyType) => propertyType.Variations.VariesByCulture();
///
/// Determines whether the property type varies by segment.
///
/// And then it could also vary by culture.
- public static bool VariesBySegment(this PropertyType propertyType) => propertyType.Variations.VariesBySegment();
+ public static bool VariesBySegment(this IPropertyType propertyType) => propertyType.Variations.VariesBySegment();
///
/// Determines whether the property type varies by culture and segment.
///
- public static bool VariesByCultureAndSegment(this PropertyType propertyType) => propertyType.Variations.VariesByCultureAndSegment();
+ public static bool VariesByCultureAndSegment(this IPropertyType propertyType) => propertyType.Variations.VariesByCultureAndSegment();
///
/// Determines whether the content type is invariant.
@@ -161,13 +161,13 @@ namespace Umbraco.Core
if (variation.VariesByCulture())
{
// varies by culture
- // in exact mode, the culture cannot be null
+ // in exact mode, the culture cannot be null
if (exact && culture == null)
{
if (throwIfInvalid)
throw new NotSupportedException($"Culture may not be null because culture variation is enabled.");
return false;
- }
+ }
}
else
{
@@ -180,7 +180,7 @@ namespace Umbraco.Core
throw new NotSupportedException($"Culture \"{culture}\" is invalid because culture variation is disabled.");
return false;
}
- }
+ }
// if it does not vary by segment
// the segment cannot have a value
diff --git a/src/Umbraco.Core/IO/IMediaFileSystem.cs b/src/Umbraco.Core/IO/IMediaFileSystem.cs
index ed88516135..8ed0ba60ca 100644
--- a/src/Umbraco.Core/IO/IMediaFileSystem.cs
+++ b/src/Umbraco.Core/IO/IMediaFileSystem.cs
@@ -52,7 +52,7 @@ namespace Umbraco.Core.IO
/// If an is provided then that file (and associated thumbnails if any) is deleted
/// before the new file is saved, and depending on the media path scheme, the folder may be reused for the new file.
///
- string StoreFile(IContentBase content, PropertyType propertyType, string filename, Stream filestream, string oldpath);
+ string StoreFile(IContentBase content, IPropertyType propertyType, string filename, Stream filestream, string oldpath);
///
/// Copies a media file as a new media file, associated to a property of a content item.
@@ -61,6 +61,6 @@ namespace Umbraco.Core.IO
/// The property type owning the copy of the media file.
/// The filesystem-relative path to the source media file.
/// The filesystem-relative path to the copy of the media file.
- string CopyFile(IContentBase content, PropertyType propertyType, string sourcepath);
+ string CopyFile(IContentBase content, IPropertyType propertyType, string sourcepath);
}
}
diff --git a/src/Umbraco.Core/IO/MediaFileSystem.cs b/src/Umbraco.Core/IO/MediaFileSystem.cs
index 2de7bc2f81..edcbfadf0d 100644
--- a/src/Umbraco.Core/IO/MediaFileSystem.cs
+++ b/src/Umbraco.Core/IO/MediaFileSystem.cs
@@ -88,7 +88,7 @@ namespace Umbraco.Core.IO
#region Associated Media Files
///
- public string StoreFile(IContentBase content, PropertyType propertyType, string filename, Stream filestream, string oldpath)
+ public string StoreFile(IContentBase content, IPropertyType propertyType, string filename, Stream filestream, string oldpath)
{
if (content == null) throw new ArgumentNullException(nameof(content));
if (propertyType == null) throw new ArgumentNullException(nameof(propertyType));
@@ -107,7 +107,7 @@ namespace Umbraco.Core.IO
}
///
- public string CopyFile(IContentBase content, PropertyType propertyType, string sourcepath)
+ public string CopyFile(IContentBase content, IPropertyType propertyType, string sourcepath)
{
if (content == null) throw new ArgumentNullException(nameof(content));
if (propertyType == null) throw new ArgumentNullException(nameof(propertyType));
diff --git a/src/Umbraco.Core/Manifest/DataEditorConverter.cs b/src/Umbraco.Core/Manifest/DataEditorConverter.cs
index 86982e17f2..86347d3894 100644
--- a/src/Umbraco.Core/Manifest/DataEditorConverter.cs
+++ b/src/Umbraco.Core/Manifest/DataEditorConverter.cs
@@ -1,6 +1,8 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
+using Umbraco.Core.Composing;
+using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Serialization;
@@ -13,13 +15,15 @@ namespace Umbraco.Core.Manifest
internal class DataEditorConverter : JsonReadConverter
{
private readonly ILogger _logger;
+ private readonly IIOHelper _ioHelper;
///
/// Initializes a new instance of the class.
///
- public DataEditorConverter(ILogger logger)
+ public DataEditorConverter(ILogger logger, IIOHelper ioHelper)
{
_logger = logger;
+ _ioHelper = ioHelper;
}
///
@@ -62,11 +66,11 @@ namespace Umbraco.Core.Manifest
PrepareForPropertyEditor(jobject, dataEditor);
else
PrepareForParameterEditor(jobject, dataEditor);
-
+
base.Deserialize(jobject, target, serializer);
}
- private static void PrepareForPropertyEditor(JObject jobject, DataEditor target)
+ private void PrepareForPropertyEditor(JObject jobject, DataEditor target)
{
if (jobject["editor"] == null)
throw new InvalidOperationException("Missing 'editor' value.");
@@ -86,6 +90,9 @@ namespace Umbraco.Core.Manifest
if (jobject["editor"]["validation"] is JObject validation)
jobject["editor"]["validation"] = RewriteValidators(validation);
+ if(jobject["editor"]["view"] is JValue view)
+ jobject["editor"]["view"] = RewriteVirtualUrl(view);
+
if (jobject["prevalues"] is JObject config)
{
// explicitly assign a configuration editor of type ConfigurationEditor
@@ -100,6 +107,9 @@ namespace Umbraco.Core.Manifest
{
if (field["validation"] is JObject fvalidation)
field["validation"] = RewriteValidators(fvalidation);
+
+ if(field["view"] is JValue fview)
+ field["view"] = RewriteVirtualUrl(fview);
}
}
@@ -118,7 +128,12 @@ namespace Umbraco.Core.Manifest
}
}
- private static void PrepareForParameterEditor(JObject jobject, DataEditor target)
+ private string RewriteVirtualUrl(JValue view)
+ {
+ return _ioHelper.ResolveVirtualUrl(view.Value as string);
+ }
+
+ private void PrepareForParameterEditor(JObject jobject, DataEditor target)
{
// in a manifest, a parameter editor looks like:
//
@@ -148,6 +163,9 @@ namespace Umbraco.Core.Manifest
jobject["defaultConfig"] = config;
jobject.Remove("config");
}
+
+ if(jobject["editor"]?["view"] is JValue view) // We need to null check, if view do not exists, then editor do not exists
+ jobject["editor"]["view"] = RewriteVirtualUrl(view);
}
private static JArray RewriteValidators(JObject validation)
diff --git a/src/Umbraco.Core/Manifest/ManifestDashboard.cs b/src/Umbraco.Core/Manifest/ManifestDashboard.cs
index 33af12e3cd..2642ca3646 100644
--- a/src/Umbraco.Core/Manifest/ManifestDashboard.cs
+++ b/src/Umbraco.Core/Manifest/ManifestDashboard.cs
@@ -9,8 +9,6 @@ namespace Umbraco.Core.Manifest
{
public class ManifestDashboard : IDashboard
{
- private string _view;
-
[JsonProperty("alias", Required = Required.Always)]
public string Alias { get; set; }
@@ -19,11 +17,7 @@ namespace Umbraco.Core.Manifest
public int Weight { get; set; }
[JsonProperty("view", Required = Required.Always)]
- public string View
- {
- get => _view;
- set => _view = Current.IOHelper.ResolveVirtualUrl(value);
- }
+ public string View { get; set; }
[JsonProperty("sections")]
public string[] Sections { get; set; } = Array.Empty();
diff --git a/src/Umbraco.Core/Manifest/ManifestParser.cs b/src/Umbraco.Core/Manifest/ManifestParser.cs
index 7f2a1825b4..bf70def9dc 100644
--- a/src/Umbraco.Core/Manifest/ManifestParser.cs
+++ b/src/Umbraco.Core/Manifest/ManifestParser.cs
@@ -163,7 +163,7 @@ namespace Umbraco.Core.Manifest
throw new ArgumentNullOrEmptyException(nameof(text));
var manifest = JsonConvert.DeserializeObject(text,
- new DataEditorConverter(_logger),
+ new DataEditorConverter(_logger, _ioHelper),
new ValueValidatorConverter(_validators),
new DashboardAccessRuleConverter());
@@ -172,6 +172,19 @@ namespace Umbraco.Core.Manifest
manifest.Scripts[i] = _ioHelper.ResolveVirtualUrl(manifest.Scripts[i]);
for (var i = 0; i < manifest.Stylesheets.Length; i++)
manifest.Stylesheets[i] = _ioHelper.ResolveVirtualUrl(manifest.Stylesheets[i]);
+ foreach (var contentApp in manifest.ContentApps)
+ {
+ contentApp.View = _ioHelper.ResolveVirtualUrl(contentApp.View);
+ }
+ foreach (var dashboard in manifest.Dashboards)
+ {
+ dashboard.View = _ioHelper.ResolveVirtualUrl(dashboard.View);
+ }
+ foreach (var gridEditor in manifest.GridEditors)
+ {
+ gridEditor.View = _ioHelper.ResolveVirtualUrl(gridEditor.View);
+ gridEditor.Render = _ioHelper.ResolveVirtualUrl(gridEditor.Render);
+ }
// add property editors that are also parameter editors, to the parameter editors list
// (the manifest format is kinda legacy)
diff --git a/src/Umbraco.Core/Models/IDataValueEditor.cs b/src/Umbraco.Core/Models/IDataValueEditor.cs
index cb68531cc7..5a1c6fd29d 100644
--- a/src/Umbraco.Core/Models/IDataValueEditor.cs
+++ b/src/Umbraco.Core/Models/IDataValueEditor.cs
@@ -59,12 +59,12 @@ namespace Umbraco.Core.PropertyEditors
///
/// Converts a property value to a value for the editor.
///
- object ToEditor(Property property, IDataTypeService dataTypeService, string culture = null, string segment = null);
+ object ToEditor(IProperty property, IDataTypeService dataTypeService, string culture = null, string segment = null);
// TODO: / deal with this when unplugging the xml cache
// why property vs propertyType? services should be injected! etc...
- IEnumerable ConvertDbToXml(Property property, IDataTypeService dataTypeService, ILocalizationService localizationService, bool published);
- XNode ConvertDbToXml(PropertyType propertyType, object value, IDataTypeService dataTypeService);
- string ConvertDbToString(PropertyType propertyType, object value, IDataTypeService dataTypeService);
+ IEnumerable ConvertDbToXml(IProperty property, IDataTypeService dataTypeService, ILocalizationService localizationService, bool published);
+ XNode ConvertDbToXml(IPropertyType propertyType, object value, IDataTypeService dataTypeService);
+ string ConvertDbToString(IPropertyType propertyType, object value, IDataTypeService dataTypeService);
}
}
diff --git a/src/Umbraco.Core/Models/Property.cs b/src/Umbraco.Core/Models/Property.cs
index 76349823ac..9b2cda67c1 100644
--- a/src/Umbraco.Core/Models/Property.cs
+++ b/src/Umbraco.Core/Models/Property.cs
@@ -13,16 +13,16 @@ namespace Umbraco.Core.Models
///
[Serializable]
[DataContract(IsReference = true)]
- public class Property : EntityBase
+ public class Property : EntityBase, IProperty
{
// _values contains all property values, including the invariant-neutral value
- private List _values = new List();
+ private List _values = new List();
// _pvalue contains the invariant-neutral property value
- private PropertyValue _pvalue;
+ private IPropertyValue _pvalue;
// _vvalues contains the (indexed) variant property values
- private Dictionary _vvalues;
+ private Dictionary _vvalues;
///
/// Initializes a new instance of the class.
@@ -50,7 +50,7 @@ namespace Umbraco.Core.Models
///
/// Represents a property value.
///
- public class PropertyValue
+ public class PropertyValue : IPropertyValue
{
// TODO: Either we allow change tracking at this class level, or we add some special change tracking collections to the Property
// class to deal with change tracking which variants have changed
@@ -66,7 +66,7 @@ namespace Umbraco.Core.Models
public string Culture
{
get => _culture;
- internal set => _culture = value.IsNullOrWhiteSpace() ? null : value.ToLowerInvariant();
+ set => _culture = value.IsNullOrWhiteSpace() ? null : value.ToLowerInvariant();
}
///
@@ -77,23 +77,23 @@ namespace Umbraco.Core.Models
public string Segment
{
get => _segment;
- internal set => _segment = value?.ToLowerInvariant();
+ set => _segment = value?.ToLowerInvariant();
}
///
/// Gets or sets the edited value of the property.
///
- public object EditedValue { get; internal set; }
+ public object EditedValue { get; set; }
///
/// Gets or sets the published value of the property.
///
- public object PublishedValue { get; internal set; }
+ public object PublishedValue { get; set; }
///
/// Clones the property value.
///
- public PropertyValue Clone()
+ public IPropertyValue Clone()
=> new PropertyValue { _culture = _culture, _segment = _segment, PublishedValue = PublishedValue, EditedValue = EditedValue };
}
@@ -121,13 +121,13 @@ namespace Umbraco.Core.Models
/// Returns the PropertyType, which this Property is based on
///
[IgnoreDataMember]
- public PropertyType PropertyType { get; private set; }
+ public IPropertyType PropertyType { get; private set; }
///
/// Gets the list of values.
///
[DataMember]
- public IReadOnlyCollection Values
+ public IReadOnlyCollection Values
{
get => _values;
set
@@ -180,7 +180,7 @@ namespace Umbraco.Core.Models
: null;
}
- private object GetPropertyValue(PropertyValue pvalue, bool published)
+ private object GetPropertyValue(IPropertyValue pvalue, bool published)
{
if (pvalue == null) return null;
@@ -240,7 +240,7 @@ namespace Umbraco.Core.Models
UnpublishValue(pvalue);
}
- private void PublishValue(PropertyValue pvalue)
+ private void PublishValue(IPropertyValue pvalue)
{
if (pvalue == null) return;
@@ -251,7 +251,7 @@ namespace Umbraco.Core.Models
DetectChanges(pvalue.EditedValue, origValue, nameof(Values), PropertyValueComparer, false);
}
- private void UnpublishValue(PropertyValue pvalue)
+ private void UnpublishValue(IPropertyValue pvalue)
{
if (pvalue == null) return;
@@ -294,7 +294,7 @@ namespace Umbraco.Core.Models
pvalue.EditedValue = value;
}
- private (PropertyValue, bool) GetPValue(bool create)
+ private (IPropertyValue, bool) GetPValue(bool create)
{
var change = false;
if (_pvalue == null)
@@ -307,7 +307,7 @@ namespace Umbraco.Core.Models
return (_pvalue, change);
}
- private (PropertyValue, bool) GetPValue(string culture, string segment, bool create)
+ private (IPropertyValue, bool) GetPValue(string culture, string segment, bool create)
{
if (culture == null && segment == null)
return GetPValue(create);
@@ -316,7 +316,7 @@ namespace Umbraco.Core.Models
if (_vvalues == null)
{
if (!create) return (null, false);
- _vvalues = new Dictionary();
+ _vvalues = new Dictionary();
change = true;
}
var k = new CompositeNStringNStringKey(culture, segment);
diff --git a/src/Umbraco.Core/Models/PropertyType.cs b/src/Umbraco.Core/Models/PropertyType.cs
index 40af478ab8..1448e099be 100644
--- a/src/Umbraco.Core/Models/PropertyType.cs
+++ b/src/Umbraco.Core/Models/PropertyType.cs
@@ -13,7 +13,7 @@ namespace Umbraco.Core.Models
[Serializable]
[DataContract(IsReference = true)]
[DebuggerDisplay("Id: {Id}, Name: {Name}, Alias: {Alias}")]
- public class PropertyType : EntityBase, IEquatable
+ public class PropertyType : EntityBase, IPropertyType, IEquatable
{
private readonly bool _forceValueStorageType;
private string _name;
@@ -160,7 +160,7 @@ namespace Umbraco.Core.Models
/// Gets or sets the database type for storing value for this property type.
///
[DataMember]
- internal ValueStorageType ValueStorageType
+ public ValueStorageType ValueStorageType
{
get => _valueStorageType;
set
@@ -175,7 +175,7 @@ namespace Umbraco.Core.Models
///
/// For generic properties, the value is null.
[DataMember]
- internal Lazy PropertyGroupId
+ public Lazy PropertyGroupId
{
get => _propertyGroupId;
set => SetPropertyValueAndDetectChanges(value, ref _propertyGroupId, nameof(PropertyGroupId));
diff --git a/src/Umbraco.Core/PropertyEditors/ConfigurationFieldsExtensions.cs b/src/Umbraco.Core/PropertyEditors/ConfigurationFieldsExtensions.cs
deleted file mode 100644
index 25fba622d5..0000000000
--- a/src/Umbraco.Core/PropertyEditors/ConfigurationFieldsExtensions.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using System.Collections.Generic;
-
-namespace Umbraco.Core.PropertyEditors
-{
- public static partial class ConfigurationFieldsExtensions
- {
- ///
- /// Adds a configuration field.
- ///
- /// The list of configuration fields.
- /// The key (alias) of the field.
- /// The name (label) of the field.
- /// The description for the field.
- /// The path to the editor view to be used for the field.
- /// Optional configuration used for field's editor.
- public static void Add(
- this List fields,
- string key,
- string name,
- string description,
- string view,
- IDictionary config = null)
- {
- fields.Add(new ConfigurationField
- {
- Key = key,
- Name = name,
- Description = description,
- View = view,
- Config = config,
- });
- }
- }
-}
diff --git a/src/Umbraco.Core/PropertyEditors/DataValueEditor.cs b/src/Umbraco.Core/PropertyEditors/DataValueEditor.cs
index a9ce27d964..396d32c833 100644
--- a/src/Umbraco.Core/PropertyEditors/DataValueEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/DataValueEditor.cs
@@ -7,7 +7,6 @@ using System.Xml.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core.Composing;
-using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Editors;
@@ -72,11 +71,7 @@ namespace Umbraco.Core.PropertyEditors
/// folder, or (3) a view name which maps to views/propertyeditors/{view}/{view}.html.
///
[JsonProperty("view", Required = Required.Always)]
- public string View
- {
- get => _view;
- set => _view = Current.IOHelper.ResolveVirtualUrl(value);
- }
+ public string View { get; set; }
///
/// The value type which reflects how it is validated and stored in the database
@@ -237,7 +232,7 @@ namespace Umbraco.Core.PropertyEditors
/// The object returned will automatically be serialized into json notation. For most property editors
/// the value returned is probably just a string but in some cases a json structure will be returned.
///
- public virtual object ToEditor(Property property, IDataTypeService dataTypeService, string culture = null, string segment = null)
+ public virtual object ToEditor(IProperty property, IDataTypeService dataTypeService, string culture = null, string segment = null)
{
var val = property.GetValue(culture, segment);
if (val == null) return string.Empty;
@@ -288,7 +283,7 @@ namespace Umbraco.Core.PropertyEditors
///
/// Converts a property to Xml fragments.
///
- public IEnumerable ConvertDbToXml(Property property, IDataTypeService dataTypeService, ILocalizationService localizationService, bool published)
+ public IEnumerable ConvertDbToXml(IProperty property, IDataTypeService dataTypeService, ILocalizationService localizationService, bool published)
{
published &= property.PropertyType.SupportsPublishing;
@@ -322,7 +317,7 @@ namespace Umbraco.Core.PropertyEditors
/// Returns an XText or XCData instance which must be wrapped in a element.
/// If the value is empty we will not return as CDATA since that will just take up more space in the file.
///
- public XNode ConvertDbToXml(PropertyType propertyType, object value, IDataTypeService dataTypeService)
+ public XNode ConvertDbToXml(IPropertyType propertyType, object value, IDataTypeService dataTypeService)
{
//check for null or empty value, we don't want to return CDATA if that is the case
if (value == null || value.ToString().IsNullOrWhiteSpace())
@@ -348,7 +343,7 @@ namespace Umbraco.Core.PropertyEditors
///
/// Converts a property value to a string.
///
- public virtual string ConvertDbToString(PropertyType propertyType, object value, IDataTypeService dataTypeService)
+ public virtual string ConvertDbToString(IPropertyType propertyType, object value, IDataTypeService dataTypeService)
{
if (value == null)
return string.Empty;
diff --git a/src/Umbraco.Core/Services/PropertyValidationService.cs b/src/Umbraco.Core/Services/PropertyValidationService.cs
index a037a83920..f619e5f47e 100644
--- a/src/Umbraco.Core/Services/PropertyValidationService.cs
+++ b/src/Umbraco.Core/Services/PropertyValidationService.cs
@@ -74,7 +74,7 @@ namespace Umbraco.Core.Services
culture = culture.NullOrWhiteSpaceAsNull();
segment = segment.NullOrWhiteSpaceAsNull();
- Property.PropertyValue pvalue = null;
+ IPropertyValue pvalue = null;
// if validating invariant/neutral, and it is supported, validate
// (including ensuring that the value exists, if mandatory)
@@ -120,7 +120,7 @@ namespace Umbraco.Core.Services
///
///
/// True is property value is valid, otherwise false
- private bool IsValidPropertyValue(Property property, object value)
+ private bool IsValidPropertyValue(IProperty property, object value)
{
return IsPropertyValueValid(property.PropertyType, value);
}
@@ -128,7 +128,7 @@ namespace Umbraco.Core.Services
///
/// Determines whether a value is valid for this property type.
///
- private bool IsPropertyValueValid(PropertyType propertyType, object value)
+ private bool IsPropertyValueValid(IPropertyType propertyType, object value)
{
var editor = _propertyEditors[propertyType.PropertyEditorAlias];
if (editor == null)
diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index f22a29075f..45e25d9a8f 100755
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -36,7 +36,6 @@
-
@@ -65,11 +64,14 @@
all
- 1.3.0
+ 1.4.0
1.0.0
+
+ 4.6.0
+
1.0.5
runtime; build; native; contentfiles; analyzers
@@ -91,19 +93,19 @@
- 2.8.0
+ 2.9.0
2.0.1
- 3.0.0
+ 3.1.0
2.0.0
- 1.0.0
+ 1.1.0
1.0.3
@@ -112,7 +114,7 @@
2.2.2
- 4.0.0
+ 4.1.0
@@ -270,7 +272,6 @@
-
@@ -282,8 +283,6 @@
-
-
@@ -483,7 +482,6 @@
-
@@ -1000,7 +998,6 @@
-
diff --git a/src/Umbraco.ModelsBuilder.Embedded/Umbraco.ModelsBuilder.Embedded.csproj b/src/Umbraco.ModelsBuilder.Embedded/Umbraco.ModelsBuilder.Embedded.csproj
index 67919834ac..eb61e2a2c8 100644
--- a/src/Umbraco.ModelsBuilder.Embedded/Umbraco.ModelsBuilder.Embedded.csproj
+++ b/src/Umbraco.ModelsBuilder.Embedded/Umbraco.ModelsBuilder.Embedded.csproj
@@ -34,7 +34,6 @@
-
@@ -97,6 +96,9 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
all
+
+ 4.6.0
+
diff --git a/src/Umbraco.Tests/App.config b/src/Umbraco.Tests/App.config
index 91047ba6a2..9eeb93384d 100644
--- a/src/Umbraco.Tests/App.config
+++ b/src/Umbraco.Tests/App.config
@@ -94,6 +94,10 @@
+
+
+
+
diff --git a/src/Umbraco.Tests/Models/PropertyTypeTests.cs b/src/Umbraco.Tests/Models/PropertyTypeTests.cs
index 1bc99162af..b4d14e7bb5 100644
--- a/src/Umbraco.Tests/Models/PropertyTypeTests.cs
+++ b/src/Umbraco.Tests/Models/PropertyTypeTests.cs
@@ -54,7 +54,15 @@ namespace Umbraco.Tests.Models
var allProps = clone.GetType().GetProperties();
foreach (var propertyInfo in allProps)
{
- Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(pt, null));
+ var expected = propertyInfo.GetValue(pt, null);
+ var actual = propertyInfo.GetValue(clone, null);
+ if (propertyInfo.PropertyType == typeof(Lazy))
+ {
+ expected = ((Lazy) expected).Value;
+ actual = ((Lazy) actual).Value;
+ }
+
+ Assert.AreEqual(expected, actual, $"Value of propery: '{propertyInfo.Name}': {expected} != {actual}");
}
}
diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs
index b9fd0f6640..149d48032b 100644
--- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs
+++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs
@@ -219,6 +219,7 @@ namespace Umbraco.Tests.Testing
Composition.RegisterUnique();
Composition.RegisterUnique();
Composition.RegisterUnique();
+ Composition.RegisterUnique();
// register back office sections in the order we want them rendered
Composition.WithCollectionBuilder().Append()
diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj
index de76b94ff1..1292d2da2e 100644
--- a/src/Umbraco.Tests/Umbraco.Tests.csproj
+++ b/src/Umbraco.Tests/Umbraco.Tests.csproj
@@ -56,7 +56,6 @@
-
@@ -107,6 +106,7 @@
+
diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
index f2976716bb..a2ce0f95f7 100644
--- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
+++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
@@ -70,7 +70,6 @@
-
@@ -110,6 +109,7 @@
runtime; build; native; contentfiles; analyzers
all
+
@@ -432,4 +432,4 @@
-
+
\ No newline at end of file
diff --git a/src/Umbraco.Web/PropertyEditors/DateValueEditor.cs b/src/Umbraco.Web/PropertyEditors/DateValueEditor.cs
index a03ad4aa00..657e2b2b49 100644
--- a/src/Umbraco.Web/PropertyEditors/DateValueEditor.cs
+++ b/src/Umbraco.Web/PropertyEditors/DateValueEditor.cs
@@ -18,7 +18,7 @@ namespace Umbraco.Web.PropertyEditors
Validators.Add(new DateTimeValidator());
}
- public override object ToEditor(Property property, IDataTypeService dataTypeService, string culture= null, string segment = null)
+ public override object ToEditor(IProperty property, IDataTypeService dataTypeService, string culture= null, string segment = null)
{
var date = property.GetValue(culture, segment).TryConvertTo();
if (date.Success == false || date.Result == null)
diff --git a/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs
index 24e2fc29a5..5964964ab7 100644
--- a/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs
+++ b/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs
@@ -115,7 +115,7 @@ namespace Umbraco.Web.PropertyEditors
///
///
///
- public override object ToEditor(Property property, IDataTypeService dataTypeService, string culture = null, string segment = null)
+ public override object ToEditor(IProperty property, IDataTypeService dataTypeService, string culture = null, string segment = null)
{
var val = property.GetValue(culture, segment);
if (val == null) return string.Empty;
diff --git a/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyValueEditor.cs b/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyValueEditor.cs
index 4aac8f54aa..fdeb726902 100644
--- a/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyValueEditor.cs
+++ b/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyValueEditor.cs
@@ -32,7 +32,7 @@ namespace Umbraco.Web.PropertyEditors
/// This is called to merge in the prevalue crops with the value that is saved - similar to the property value converter for the front-end
///
- public override object ToEditor(Property property, IDataTypeService dataTypeService, string culture = null, string segment = null)
+ public override object ToEditor(IProperty property, IDataTypeService dataTypeService, string culture = null, string segment = null)
{
var val = property.GetValue(culture, segment);
if (val == null) return null;
@@ -161,7 +161,7 @@ namespace Umbraco.Web.PropertyEditors
}
- public override string ConvertDbToString(PropertyType propertyType, object value, IDataTypeService dataTypeService)
+ public override string ConvertDbToString(IPropertyType propertyType, object value, IDataTypeService dataTypeService)
{
if (value == null || string.IsNullOrEmpty(value.ToString()))
return null;
diff --git a/src/Umbraco.Web/PropertyEditors/MultiUrlPickerValueEditor.cs b/src/Umbraco.Web/PropertyEditors/MultiUrlPickerValueEditor.cs
index aa8fa73c7a..c2ad58a101 100644
--- a/src/Umbraco.Web/PropertyEditors/MultiUrlPickerValueEditor.cs
+++ b/src/Umbraco.Web/PropertyEditors/MultiUrlPickerValueEditor.cs
@@ -28,7 +28,7 @@ namespace Umbraco.Web.PropertyEditors
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
- public override object ToEditor(Property property, IDataTypeService dataTypeService, string culture = null, string segment = null)
+ public override object ToEditor(IProperty property, IDataTypeService dataTypeService, string culture = null, string segment = null)
{
var value = property.GetValue(culture, segment)?.ToString();
diff --git a/src/Umbraco.Web/PropertyEditors/MultipleTextStringPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MultipleTextStringPropertyEditor.cs
index fa82bc555c..23ceb0f22a 100644
--- a/src/Umbraco.Web/PropertyEditors/MultipleTextStringPropertyEditor.cs
+++ b/src/Umbraco.Web/PropertyEditors/MultipleTextStringPropertyEditor.cs
@@ -95,7 +95,7 @@ namespace Umbraco.Web.PropertyEditors
///
/// The legacy property editor saved this data as new line delimited! strange but we have to maintain that.
///
- public override object ToEditor(Property property, IDataTypeService dataTypeService, string culture = null, string segment = null)
+ public override object ToEditor(IProperty property, IDataTypeService dataTypeService, string culture = null, string segment = null)
{
var val = property.GetValue(culture, segment);
return val?.ToString().Split(new[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)
diff --git a/src/Umbraco.Web/PropertyEditors/MultipleValueEditor.cs b/src/Umbraco.Web/PropertyEditors/MultipleValueEditor.cs
index bbeaff184e..4c59a8e3c5 100644
--- a/src/Umbraco.Web/PropertyEditors/MultipleValueEditor.cs
+++ b/src/Umbraco.Web/PropertyEditors/MultipleValueEditor.cs
@@ -33,7 +33,7 @@ namespace Umbraco.Web.PropertyEditors
///
///
///
- public override object ToEditor(Property property, IDataTypeService dataTypeService, string culture = null, string segment = null)
+ public override object ToEditor(IProperty property, IDataTypeService dataTypeService, string culture = null, string segment = null)
{
var json = base.ToEditor(property, dataTypeService, culture, segment).ToString();
return JsonConvert.DeserializeObject(json) ?? Array.Empty();
diff --git a/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs
index f511a97cac..778b69d9db 100644
--- a/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs
+++ b/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs
@@ -92,7 +92,7 @@ namespace Umbraco.Web.PropertyEditors
#region DB to String
- public override string ConvertDbToString(PropertyType propertyType, object propertyValue, IDataTypeService dataTypeService)
+ public override string ConvertDbToString(IPropertyType propertyType, object propertyValue, IDataTypeService dataTypeService)
{
if (propertyValue == null || string.IsNullOrWhiteSpace(propertyValue.ToString()))
return string.Empty;
@@ -152,7 +152,7 @@ namespace Umbraco.Web.PropertyEditors
// note: there is NO variant support here
- public override object ToEditor(Property property, IDataTypeService dataTypeService, string culture = null, string segment = null)
+ public override object ToEditor(IProperty property, IDataTypeService dataTypeService, string culture = null, string segment = null)
{
var val = property.GetValue(culture, segment);
if (val == null || string.IsNullOrWhiteSpace(val.ToString()))
diff --git a/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs
index 5743e9c1d5..03345bee3c 100644
--- a/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs
+++ b/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs
@@ -92,7 +92,7 @@ namespace Umbraco.Web.PropertyEditors
///
///
///
- public override object ToEditor(Property property, IDataTypeService dataTypeService, string culture = null, string segment = null)
+ public override object ToEditor(IProperty property, IDataTypeService dataTypeService, string culture = null, string segment = null)
{
var val = property.GetValue(culture, segment);
if (val == null)
diff --git a/src/Umbraco.Web/PropertyEditors/TextOnlyValueEditor.cs b/src/Umbraco.Web/PropertyEditors/TextOnlyValueEditor.cs
index 754cef1f31..f925daba30 100644
--- a/src/Umbraco.Web/PropertyEditors/TextOnlyValueEditor.cs
+++ b/src/Umbraco.Web/PropertyEditors/TextOnlyValueEditor.cs
@@ -26,7 +26,7 @@ namespace Umbraco.Web.PropertyEditors
///
/// The object returned will always be a string and if the database type is not a valid string type an exception is thrown
///
- public override object ToEditor(Property property, IDataTypeService dataTypeService, string culture = null, string segment = null)
+ public override object ToEditor(IProperty property, IDataTypeService dataTypeService, string culture = null, string segment = null)
{
var val = property.GetValue(culture, segment);
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index 317786b970..bede1a1a6d 100755
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -41,7 +41,6 @@
-
@@ -1282,4 +1281,4 @@
-
\ No newline at end of file
+