diff --git a/src/Umbraco.Abstractions/Collections/DeepCloneableList.cs b/src/Umbraco.Abstractions/Collections/DeepCloneableList.cs index a21c7aae56..cc57b96f1b 100644 --- a/src/Umbraco.Abstractions/Collections/DeepCloneableList.cs +++ b/src/Umbraco.Abstractions/Collections/DeepCloneableList.cs @@ -47,8 +47,7 @@ namespace Umbraco.Core.Collections var newList = new DeepCloneableList(ListCloneBehavior.None); foreach (var item in this) { - var dc = item as IDeepCloneable; - if (dc != null) + if (item is IDeepCloneable dc) { newList.Add((T)dc.DeepClone()); } @@ -66,8 +65,7 @@ namespace Umbraco.Core.Collections var newList2 = new DeepCloneableList(ListCloneBehavior.Always); foreach (var item in this) { - var dc = item as IDeepCloneable; - if (dc != null) + if (item is IDeepCloneable dc) { newList2.Add((T)dc.DeepClone()); } @@ -121,6 +119,16 @@ namespace Umbraco.Core.Collections } } + public void DisableChangeTracking() + { + // noop + } + + public void EnableChangeTracking() + { + // noop + } + public void ResetWereDirtyProperties() { foreach (var dc in this.OfType()) diff --git a/src/Umbraco.Core/Manifest/IManifestFilter.cs b/src/Umbraco.Abstractions/Manifest/IManifestFilter.cs similarity index 99% rename from src/Umbraco.Core/Manifest/IManifestFilter.cs rename to src/Umbraco.Abstractions/Manifest/IManifestFilter.cs index 505f13d385..88e00a3966 100644 --- a/src/Umbraco.Core/Manifest/IManifestFilter.cs +++ b/src/Umbraco.Abstractions/Manifest/IManifestFilter.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; + namespace Umbraco.Core.Manifest { /// diff --git a/src/Umbraco.Abstractions/Manifest/IManifestParser.cs b/src/Umbraco.Abstractions/Manifest/IManifestParser.cs new file mode 100644 index 0000000000..eeb0c756f6 --- /dev/null +++ b/src/Umbraco.Abstractions/Manifest/IManifestParser.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using Umbraco.Core.PropertyEditors; + +namespace Umbraco.Core.Manifest +{ + public interface IManifestParser + { + string Path { get; set; } + + /// + /// Gets all manifests, merged into a single manifest object. + /// + /// + PackageManifest Manifest { get; } + + /// + /// Parses a manifest. + /// + PackageManifest ParseManifest(string text); + + IEnumerable ParseGridEditors(string text); + } +} diff --git a/src/Umbraco.Core/Manifest/ManifestContentAppDefinition.cs b/src/Umbraco.Abstractions/Manifest/ManifestContentAppDefinition.cs similarity index 92% rename from src/Umbraco.Core/Manifest/ManifestContentAppDefinition.cs rename to src/Umbraco.Abstractions/Manifest/ManifestContentAppDefinition.cs index 2aafcd8b74..35293a6377 100644 --- a/src/Umbraco.Core/Manifest/ManifestContentAppDefinition.cs +++ b/src/Umbraco.Abstractions/Manifest/ManifestContentAppDefinition.cs @@ -1,7 +1,5 @@ using System; using System.Runtime.Serialization; -using Umbraco.Core.Composing; -using Umbraco.Core.IO; namespace Umbraco.Core.Manifest { @@ -65,11 +63,7 @@ namespace Umbraco.Core.Manifest /// Gets or sets the view for rendering the content app. /// [DataMember(Name = "view")] - public string View - { - get => _view; - set => _view = Current.IOHelper.ResolveVirtualUrl(value); - } + public string View { get; set; } /// /// Gets or sets the list of 'show' conditions for the content app. diff --git a/src/Umbraco.Abstractions/Manifest/ManifestDashboard.cs b/src/Umbraco.Abstractions/Manifest/ManifestDashboard.cs new file mode 100644 index 0000000000..2d6f96b5c2 --- /dev/null +++ b/src/Umbraco.Abstractions/Manifest/ManifestDashboard.cs @@ -0,0 +1,26 @@ +using System; +using System.ComponentModel; +using System.Runtime.Serialization; +using Umbraco.Core.Dashboards; + +namespace Umbraco.Core.Manifest +{ + [DataContract] + public class ManifestDashboard : IDashboard + { + [DataMember(Name = "alias", IsRequired = true)] + public string Alias { get; set; } + + [DataMember(Name = "weight")] + public int Weight { get; set; } = 100; + + [DataMember(Name = "view", IsRequired = true)] + public string View { get; set; } + + [DataMember(Name = "sections")] + public string[] Sections { get; set; } = Array.Empty(); + + [DataMember(Name = "access")] + public IAccessRule[] AccessRules { get; set; } = Array.Empty(); + } +} diff --git a/src/Umbraco.Core/Manifest/ManifestFilterCollection.cs b/src/Umbraco.Abstractions/Manifest/ManifestFilterCollection.cs similarity index 100% rename from src/Umbraco.Core/Manifest/ManifestFilterCollection.cs rename to src/Umbraco.Abstractions/Manifest/ManifestFilterCollection.cs diff --git a/src/Umbraco.Core/Manifest/ManifestFilterCollectionBuilder.cs b/src/Umbraco.Abstractions/Manifest/ManifestFilterCollectionBuilder.cs similarity index 100% rename from src/Umbraco.Core/Manifest/ManifestFilterCollectionBuilder.cs rename to src/Umbraco.Abstractions/Manifest/ManifestFilterCollectionBuilder.cs diff --git a/src/Umbraco.Core/Manifest/ManifestSection.cs b/src/Umbraco.Abstractions/Manifest/ManifestSection.cs similarity index 100% rename from src/Umbraco.Core/Manifest/ManifestSection.cs rename to src/Umbraco.Abstractions/Manifest/ManifestSection.cs diff --git a/src/Umbraco.Core/Manifest/PackageManifest.cs b/src/Umbraco.Abstractions/Manifest/PackageManifest.cs similarity index 83% rename from src/Umbraco.Core/Manifest/PackageManifest.cs rename to src/Umbraco.Abstractions/Manifest/PackageManifest.cs index e50eb69467..5e10030693 100644 --- a/src/Umbraco.Core/Manifest/PackageManifest.cs +++ b/src/Umbraco.Abstractions/Manifest/PackageManifest.cs @@ -1,70 +1,71 @@ -using System; -using Newtonsoft.Json; -using Umbraco.Core.PropertyEditors; - -namespace Umbraco.Core.Manifest -{ - /// - /// Represents the content of a package manifest. - /// - public class PackageManifest - { - /// - /// Gets the source path of the manifest. - /// - /// - /// Gets the full absolute file path of the manifest, - /// using system directory separators. - /// - [JsonIgnore] - public string Source { get; set; } - - /// - /// Gets or sets the scripts listed in the manifest. - /// - [JsonProperty("javascript")] - public string[] Scripts { get; set; } = Array.Empty(); - - /// - /// Gets or sets the stylesheets listed in the manifest. - /// - [JsonProperty("css")] - public string[] Stylesheets { get; set; } = Array.Empty(); - - /// - /// Gets or sets the property editors listed in the manifest. - /// - [JsonProperty("propertyEditors")] - public IDataEditor[] PropertyEditors { get; set; } = Array.Empty(); - - /// - /// Gets or sets the parameter editors listed in the manifest. - /// - [JsonProperty("parameterEditors")] - public IDataEditor[] ParameterEditors { get; set; } = Array.Empty(); - - /// - /// Gets or sets the grid editors listed in the manifest. - /// - [JsonProperty("gridEditors")] - public GridEditor[] GridEditors { get; set; } = Array.Empty(); - - /// - /// Gets or sets the content apps listed in the manifest. - /// - [JsonProperty("contentApps")] - public ManifestContentAppDefinition[] ContentApps { get; set; } = Array.Empty(); - - /// - /// Gets or sets the dashboards listed in the manifest. - /// - [JsonProperty("dashboards")] - public ManifestDashboard[] Dashboards { get; set; } = Array.Empty(); - - /// - /// Gets or sets the sections listed in the manifest. - /// - [JsonProperty("sections")] - public ManifestSection[] Sections { get; set; } = Array.Empty(); - } -} +using System; +using System.Runtime.Serialization; +using Umbraco.Core.PropertyEditors; + +namespace Umbraco.Core.Manifest +{ + /// + /// Represents the content of a package manifest. + /// + [DataContract] + public class PackageManifest + { + /// + /// Gets the source path of the manifest. + /// + /// + /// Gets the full absolute file path of the manifest, + /// using system directory separators. + /// + [IgnoreDataMember] + public string Source { get; set; } + + /// + /// Gets or sets the scripts listed in the manifest. + /// + [DataMember(Name = "javascript")] + public string[] Scripts { get; set; } = Array.Empty(); + + /// + /// Gets or sets the stylesheets listed in the manifest. + /// + [DataMember(Name = "css")] + public string[] Stylesheets { get; set; } = Array.Empty(); + + /// + /// Gets or sets the property editors listed in the manifest. + /// + [DataMember(Name = "propertyEditors")] + public IDataEditor[] PropertyEditors { get; set; } = Array.Empty(); + + /// + /// Gets or sets the parameter editors listed in the manifest. + /// + [DataMember(Name = "parameterEditors")] + public IDataEditor[] ParameterEditors { get; set; } = Array.Empty(); + + /// + /// Gets or sets the grid editors listed in the manifest. + /// + [DataMember(Name = "gridEditors")] + public GridEditor[] GridEditors { get; set; } = Array.Empty(); + + /// + /// Gets or sets the content apps listed in the manifest. + /// + [DataMember(Name = "contentApps")] + public ManifestContentAppDefinition[] ContentApps { get; set; } = Array.Empty(); + + /// + /// Gets or sets the dashboards listed in the manifest. + /// + [DataMember(Name = "dashboards")] + public ManifestDashboard[] Dashboards { get; set; } = Array.Empty(); + + /// + /// Gets or sets the sections listed in the manifest. + /// + [DataMember(Name = "sections")] + public ManifestSection[] Sections { get; set; } = Array.Empty(); + } +} diff --git a/src/Umbraco.Core/Models/ContentSchedule.cs b/src/Umbraco.Abstractions/Models/ContentSchedule.cs similarity index 98% rename from src/Umbraco.Core/Models/ContentSchedule.cs rename to src/Umbraco.Abstractions/Models/ContentSchedule.cs index cac4a0fd1c..4dba0456b0 100644 --- a/src/Umbraco.Core/Models/ContentSchedule.cs +++ b/src/Umbraco.Abstractions/Models/ContentSchedule.cs @@ -36,7 +36,7 @@ namespace Umbraco.Core.Models /// Gets the unique identifier of the document targeted by the scheduled action. /// [DataMember] - public Guid Id { get; internal set; } + public Guid Id { get; set; } /// /// Gets the culture of the scheduled action. diff --git a/src/Umbraco.Core/Models/ContentScheduleAction.cs b/src/Umbraco.Abstractions/Models/ContentScheduleAction.cs similarity index 100% rename from src/Umbraco.Core/Models/ContentScheduleAction.cs rename to src/Umbraco.Abstractions/Models/ContentScheduleAction.cs diff --git a/src/Umbraco.Core/Models/ContentScheduleCollection.cs b/src/Umbraco.Abstractions/Models/ContentScheduleCollection.cs similarity index 100% rename from src/Umbraco.Core/Models/ContentScheduleCollection.cs rename to src/Umbraco.Abstractions/Models/ContentScheduleCollection.cs diff --git a/src/Umbraco.Abstractions/Models/Entities/EntitySlim.cs b/src/Umbraco.Abstractions/Models/Entities/EntitySlim.cs index b095965056..77611ebc3d 100644 --- a/src/Umbraco.Abstractions/Models/Entities/EntitySlim.cs +++ b/src/Umbraco.Abstractions/Models/Entities/EntitySlim.cs @@ -146,6 +146,16 @@ namespace Umbraco.Core.Models.Entities throw new WontImplementException(); } + public void DisableChangeTracking() + { + // noop + } + + public void EnableChangeTracking() + { + // noop + } + public bool WasDirty() { throw new WontImplementException(); diff --git a/src/Umbraco.Abstractions/Models/Entities/ICanBeDirty.cs b/src/Umbraco.Abstractions/Models/Entities/ICanBeDirty.cs index fc95161d7e..57a8a581f0 100644 --- a/src/Umbraco.Abstractions/Models/Entities/ICanBeDirty.cs +++ b/src/Umbraco.Abstractions/Models/Entities/ICanBeDirty.cs @@ -26,5 +26,15 @@ namespace Umbraco.Core.Models.Entities /// Resets dirty properties. /// void ResetDirtyProperties(); + + /// + /// Disables change tracking. + /// + void DisableChangeTracking(); + + /// + /// Enables change tracking. + /// + void EnableChangeTracking(); } } diff --git a/src/Umbraco.Core/Models/IContent.cs b/src/Umbraco.Abstractions/Models/IContent.cs similarity index 100% rename from src/Umbraco.Core/Models/IContent.cs rename to src/Umbraco.Abstractions/Models/IContent.cs diff --git a/src/Umbraco.Core/Models/IContentBase.cs b/src/Umbraco.Abstractions/Models/IContentBase.cs similarity index 99% rename from src/Umbraco.Core/Models/IContentBase.cs rename to src/Umbraco.Abstractions/Models/IContentBase.cs index 0f660181fb..1864996379 100644 --- a/src/Umbraco.Core/Models/IContentBase.cs +++ b/src/Umbraco.Abstractions/Models/IContentBase.cs @@ -98,7 +98,7 @@ namespace Umbraco.Core.Models /// List of properties, which make up all the data available for this Content object /// /// Properties are loaded as part of the Content object graph - PropertyCollection Properties { get; set; } + IPropertyCollection Properties { get; set; } /// /// Gets a value indicating whether the content entity has a property with the supplied alias. diff --git a/src/Umbraco.Core/Models/IDataValueEditor.cs b/src/Umbraco.Abstractions/Models/IDataValueEditor.cs similarity index 81% rename from src/Umbraco.Core/Models/IDataValueEditor.cs rename to src/Umbraco.Abstractions/Models/IDataValueEditor.cs index cb68531cc7..e095f3aa31 100644 --- a/src/Umbraco.Core/Models/IDataValueEditor.cs +++ b/src/Umbraco.Abstractions/Models/IDataValueEditor.cs @@ -3,7 +3,6 @@ using System.ComponentModel.DataAnnotations; using System.Xml.Linq; using Umbraco.Core.Models; using Umbraco.Core.Models.Editors; -using Umbraco.Core.Services; namespace Umbraco.Core.PropertyEditors { @@ -59,12 +58,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, 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, bool published); + XNode ConvertDbToXml(IPropertyType propertyType, object value); + string ConvertDbToString(IPropertyType propertyType, object value); } } diff --git a/src/Umbraco.Core/Models/IMedia.cs b/src/Umbraco.Abstractions/Models/IMedia.cs similarity index 100% rename from src/Umbraco.Core/Models/IMedia.cs rename to src/Umbraco.Abstractions/Models/IMedia.cs diff --git a/src/Umbraco.Abstractions/Models/IProperty.cs b/src/Umbraco.Abstractions/Models/IProperty.cs new file mode 100644 index 0000000000..35a151af10 --- /dev/null +++ b/src/Umbraco.Abstractions/Models/IProperty.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using Umbraco.Core.Models.Entities; + +namespace Umbraco.Core.Models +{ + public interface IProperty : IEntity, IRememberBeingDirty + { + + ValueStorageType ValueStorageType { get; } + /// + /// 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; } + + /// + /// 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(); + + int PropertyTypeId { get; } + void PublishValues(string culture = "*", string segment = "*"); + void UnpublishValues(string culture = "*", string segment = "*"); + } +} diff --git a/src/Umbraco.Abstractions/Models/IPropertyCollection.cs b/src/Umbraco.Abstractions/Models/IPropertyCollection.cs new file mode 100644 index 0000000000..c0a9622e6e --- /dev/null +++ b/src/Umbraco.Abstractions/Models/IPropertyCollection.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using System.Collections.Specialized; + +namespace Umbraco.Core.Models +{ + public interface IPropertyCollection : IEnumerable, IDeepCloneable, INotifyCollectionChanged + { + bool TryGetValue(string propertyTypeAlias, out IProperty property); + bool Contains(string key); + + /// + /// Ensures that the collection contains properties for the specified property types. + /// + void EnsurePropertyTypes(IEnumerable propertyTypes); + + /// + /// Ensures that the collection does not contain properties not in the specified property types. + /// + void EnsureCleanPropertyTypes(IEnumerable propertyTypes); + + /// + /// Gets the property with the specified alias. + /// + IProperty this[string name] { get; } + + /// + /// Gets the property at the specified index. + /// + IProperty this[int index] { get; } + + /// + /// Adds or updates a property. + /// + void Add(IProperty property); + + int Count { get; } + } +} diff --git a/src/Umbraco.Abstractions/Models/IPropertyType.cs b/src/Umbraco.Abstractions/Models/IPropertyType.cs new file mode 100644 index 0000000000..e70ee39933 --- /dev/null +++ b/src/Umbraco.Abstractions/Models/IPropertyType.cs @@ -0,0 +1,87 @@ +using System; +using System.Runtime.Serialization; +using Umbraco.Core.Models.Entities; + +namespace Umbraco.Core.Models +{ + public interface IPropertyType : IEntity, IRememberBeingDirty + { + /// + /// Gets of sets the name of the property type. + /// + string Name { get; } + + /// + /// Gets of sets the alias of the property type. + /// + string Alias { get; } + + /// + /// Gets of sets the description of the property type. + /// + string Description { get; } + + /// + /// Gets or sets the identifier of the datatype for this property type. + /// + int DataTypeId { get; } + + Guid DataTypeKey { get; } + + /// + /// Gets or sets the alias of the property editor for this property type. + /// + string PropertyEditorAlias { get; } + + /// + /// Gets or sets the database type for storing value for this property type. + /// + ValueStorageType ValueStorageType { get; } + + /// + /// Gets or sets the identifier of the property group this property type belongs to. + /// + /// For generic properties, the value is null. + Lazy PropertyGroupId { get; } + + /// + /// Gets of sets a value indicating whether a value for this property type is required. + /// + bool Mandatory { get; } + + /// + /// Gets of sets the sort order of the property type. + /// + int SortOrder { get; } + + /// + /// Gets or sets the regular expression validating the property values. + /// + string ValidationRegExp { get; } + + bool SupportsPublishing { get; } + + /// + /// Gets or sets the content variation of the property type. + /// + ContentVariation Variations { get; } + + /// + /// Determines whether the property type supports a combination of culture and segment. + /// + /// The culture. + /// The segment. + /// A value indicating whether wildcards are valid. + bool SupportsVariation(string culture, string segment, bool wildcards = false); + + /// + /// Converts a value assigned to a property. + /// + /// + /// The input value can be pretty much anything, and is converted to the actual CLR type + /// expected by the property (eg an integer if the property values are integers). + /// Throws if the value cannot be converted. + /// + 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/ConfigurationField.cs b/src/Umbraco.Abstractions/PropertyEditors/ConfigurationField.cs similarity index 83% rename from src/Umbraco.Core/PropertyEditors/ConfigurationField.cs rename to src/Umbraco.Abstractions/PropertyEditors/ConfigurationField.cs index ee07f8dcef..52df839712 100644 --- a/src/Umbraco.Core/PropertyEditors/ConfigurationField.cs +++ b/src/Umbraco.Abstractions/PropertyEditors/ConfigurationField.cs @@ -1,15 +1,15 @@ using System; using System.Collections.Generic; using System.Linq; -using Newtonsoft.Json; -using Umbraco.Core.Composing; -using Umbraco.Core.IO; +using System.Reflection; +using System.Runtime.Serialization; namespace Umbraco.Core.PropertyEditors { /// /// Represents a datatype configuration field for editing. /// + [DataContract] public class ConfigurationField { private string _view; @@ -50,37 +50,35 @@ namespace Umbraco.Core.PropertyEditors /// /// Gets or sets the key of the field. /// - [JsonProperty("key", Required = Required.Always)] + [DataMember(Name = "key", IsRequired = true)] public string Key { get; set; } /// /// Gets or sets the name of the field. /// - [JsonProperty("label", Required = Required.Always)] + [DataMember(Name = "label", IsRequired = true)] public string Name { get; set; } /// /// Gets or sets the property name of the field. /// - [JsonIgnore] public string PropertyName { get; set; } /// /// Gets or sets the property CLR type of the field. /// - [JsonIgnore] public Type PropertyType { get; set; } /// /// Gets or sets the description of the field. /// - [JsonProperty("description")] + [DataMember(Name = "description")] public string Description { get; set; } /// /// Gets or sets a value indicating whether to hide the label of the field. /// - [JsonProperty("hideLabel")] + [DataMember(Name = "hideLabel")] public bool HideLabel { get; set; } /// @@ -90,23 +88,19 @@ namespace Umbraco.Core.PropertyEditors /// Can be the full virtual path, or the relative path to the Umbraco folder, /// or a simple view name which will map to ~/Views/PreValueEditors/{view}.html. /// - [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; } /// /// Gets the validators of the field. /// - [JsonProperty("validation")] + [DataMember(Name = "validation")] public List Validators { get; } /// /// Gets or sets extra configuration properties for the editor. /// - [JsonProperty("config")] + [DataMember(Name = "config")] public IDictionary Config { get; set; } } } 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/PropertyEditors/IDataEditor.cs b/src/Umbraco.Abstractions/PropertyEditors/IDataEditor.cs similarity index 100% rename from src/Umbraco.Core/PropertyEditors/IDataEditor.cs rename to src/Umbraco.Abstractions/PropertyEditors/IDataEditor.cs diff --git a/src/Umbraco.Core/PropertyEditors/IManifestValueValidator.cs b/src/Umbraco.Abstractions/PropertyEditors/IManifestValueValidator.cs similarity index 100% rename from src/Umbraco.Core/PropertyEditors/IManifestValueValidator.cs rename to src/Umbraco.Abstractions/PropertyEditors/IManifestValueValidator.cs diff --git a/src/Umbraco.Core/PropertyEditors/IPropertyIndexValueFactory.cs b/src/Umbraco.Abstractions/PropertyEditors/IPropertyIndexValueFactory.cs similarity index 92% rename from src/Umbraco.Core/PropertyEditors/IPropertyIndexValueFactory.cs rename to src/Umbraco.Abstractions/PropertyEditors/IPropertyIndexValueFactory.cs index fd4e272f08..26552afc6f 100644 --- a/src/Umbraco.Core/PropertyEditors/IPropertyIndexValueFactory.cs +++ b/src/Umbraco.Abstractions/PropertyEditors/IPropertyIndexValueFactory.cs @@ -19,6 +19,6 @@ namespace Umbraco.Core.PropertyEditors /// values. By default, there would be only one object: the property value. But some implementations may return /// more than one value for a given field. /// - IEnumerable>> GetIndexValues(Property property, string culture, string segment, bool published); + IEnumerable>> GetIndexValues(IProperty property, string culture, string segment, bool published); } } diff --git a/src/Umbraco.Core/PropertyEditors/IValueFormatValidator.cs b/src/Umbraco.Abstractions/PropertyEditors/IValueFormatValidator.cs similarity index 100% rename from src/Umbraco.Core/PropertyEditors/IValueFormatValidator.cs rename to src/Umbraco.Abstractions/PropertyEditors/IValueFormatValidator.cs diff --git a/src/Umbraco.Core/PropertyEditors/IValueRequiredValidator.cs b/src/Umbraco.Abstractions/PropertyEditors/IValueRequiredValidator.cs similarity index 100% rename from src/Umbraco.Core/PropertyEditors/IValueRequiredValidator.cs rename to src/Umbraco.Abstractions/PropertyEditors/IValueRequiredValidator.cs diff --git a/src/Umbraco.Core/PropertyEditors/IValueValidator.cs b/src/Umbraco.Abstractions/PropertyEditors/IValueValidator.cs similarity index 100% rename from src/Umbraco.Core/PropertyEditors/IValueValidator.cs rename to src/Umbraco.Abstractions/PropertyEditors/IValueValidator.cs diff --git a/src/Umbraco.Core/PropertyEditors/ManifestValueValidatorCollection.cs b/src/Umbraco.Abstractions/PropertyEditors/ManifestValueValidatorCollection.cs similarity index 100% rename from src/Umbraco.Core/PropertyEditors/ManifestValueValidatorCollection.cs rename to src/Umbraco.Abstractions/PropertyEditors/ManifestValueValidatorCollection.cs diff --git a/src/Umbraco.Abstractions/PropertyEditors/ManifestValueValidatorCollectionBuilder.cs b/src/Umbraco.Abstractions/PropertyEditors/ManifestValueValidatorCollectionBuilder.cs new file mode 100644 index 0000000000..0ebda864f6 --- /dev/null +++ b/src/Umbraco.Abstractions/PropertyEditors/ManifestValueValidatorCollectionBuilder.cs @@ -0,0 +1,9 @@ +using Umbraco.Core.Composing; + +namespace Umbraco.Core.PropertyEditors +{ + public class ManifestValueValidatorCollectionBuilder : LazyCollectionBuilderBase + { + protected override ManifestValueValidatorCollectionBuilder This => this; + } +} diff --git a/src/Umbraco.Core/PropertyEditors/Validators/DecimalValidator.cs b/src/Umbraco.Abstractions/PropertyEditors/Validators/DecimalValidator.cs similarity index 92% rename from src/Umbraco.Core/PropertyEditors/Validators/DecimalValidator.cs rename to src/Umbraco.Abstractions/PropertyEditors/Validators/DecimalValidator.cs index 86db995566..f464044923 100644 --- a/src/Umbraco.Core/PropertyEditors/Validators/DecimalValidator.cs +++ b/src/Umbraco.Abstractions/PropertyEditors/Validators/DecimalValidator.cs @@ -6,7 +6,7 @@ namespace Umbraco.Core.PropertyEditors.Validators /// /// A validator that validates that the value is a valid decimal /// - internal sealed class DecimalValidator : IManifestValueValidator + public sealed class DecimalValidator : IManifestValueValidator { /// public string ValidationName => "Decimal"; diff --git a/src/Umbraco.Core/PropertyEditors/Validators/EmailValidator.cs b/src/Umbraco.Abstractions/PropertyEditors/Validators/EmailValidator.cs similarity index 92% rename from src/Umbraco.Core/PropertyEditors/Validators/EmailValidator.cs rename to src/Umbraco.Abstractions/PropertyEditors/Validators/EmailValidator.cs index 4df11e4f60..8fb6d0c31b 100644 --- a/src/Umbraco.Core/PropertyEditors/Validators/EmailValidator.cs +++ b/src/Umbraco.Abstractions/PropertyEditors/Validators/EmailValidator.cs @@ -6,7 +6,7 @@ namespace Umbraco.Core.PropertyEditors.Validators /// /// A validator that validates an email address /// - internal sealed class EmailValidator : IManifestValueValidator + public sealed class EmailValidator : IManifestValueValidator { /// public string ValidationName => "Email"; diff --git a/src/Umbraco.Core/PropertyEditors/Validators/IntegerValidator.cs b/src/Umbraco.Abstractions/PropertyEditors/Validators/IntegerValidator.cs similarity index 92% rename from src/Umbraco.Core/PropertyEditors/Validators/IntegerValidator.cs rename to src/Umbraco.Abstractions/PropertyEditors/Validators/IntegerValidator.cs index 335ddf7724..5274ff484b 100644 --- a/src/Umbraco.Core/PropertyEditors/Validators/IntegerValidator.cs +++ b/src/Umbraco.Abstractions/PropertyEditors/Validators/IntegerValidator.cs @@ -6,7 +6,7 @@ namespace Umbraco.Core.PropertyEditors.Validators /// /// A validator that validates that the value is a valid integer /// - internal sealed class IntegerValidator : IManifestValueValidator + public sealed class IntegerValidator : IManifestValueValidator { /// public string ValidationName => "Integer"; diff --git a/src/Umbraco.Abstractions/Services/ILocalizationService.cs b/src/Umbraco.Abstractions/Services/ILocalizationService.cs index 4ab71f8ea6..b8c4e21f2a 100644 --- a/src/Umbraco.Abstractions/Services/ILocalizationService.cs +++ b/src/Umbraco.Abstractions/Services/ILocalizationService.cs @@ -19,7 +19,7 @@ namespace Umbraco.Core.Services /// Adds or updates a translation for a dictionary item and language /// /// - /// + /// /// void AddOrUpdateDictionaryValue(IDictionaryItem item, ILanguage language, string value); diff --git a/src/Umbraco.Abstractions/Umbraco.Abstractions.csproj b/src/Umbraco.Abstractions/Umbraco.Abstractions.csproj index a5e5a94520..b3a1b4fa25 100644 --- a/src/Umbraco.Abstractions/Umbraco.Abstractions.csproj +++ b/src/Umbraco.Abstractions/Umbraco.Abstractions.csproj @@ -7,6 +7,7 @@ + diff --git a/src/Umbraco.Core/ContentExtensions.cs b/src/Umbraco.Core/ContentExtensions.cs index 8e404402d0..6732fd9394 100644 --- a/src/Umbraco.Core/ContentExtensions.cs +++ b/src/Umbraco.Core/ContentExtensions.cs @@ -108,7 +108,7 @@ namespace Umbraco.Core /// /// /// - public static IEnumerable GetNonGroupedProperties(this IContentBase content) + public static IEnumerable GetNonGroupedProperties(this IContentBase content) { return content.Properties .Where(x => x.PropertyType.PropertyGroupId == null) @@ -121,7 +121,7 @@ namespace Umbraco.Core /// /// /// - public static IEnumerable GetPropertiesForGroup(this IContentBase content, PropertyGroup propertyGroup) + public static IEnumerable GetPropertiesForGroup(this IContentBase content, PropertyGroup propertyGroup) { //get the properties for the current tab return content.Properties @@ -178,7 +178,7 @@ namespace Umbraco.Core } // gets or creates a property for a content item. - private static Property GetProperty(IContentBase content, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, string propertyTypeAlias) + private static IProperty GetProperty(IContentBase content, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, string propertyTypeAlias) { var property = content.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias)); if (property != null) return property; 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..437d1eb159 100644 --- a/src/Umbraco.Core/Manifest/DataEditorConverter.cs +++ b/src/Umbraco.Core/Manifest/DataEditorConverter.cs @@ -1,9 +1,12 @@ 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; +using Umbraco.Core.Services; namespace Umbraco.Core.Manifest { @@ -13,13 +16,19 @@ namespace Umbraco.Core.Manifest internal class DataEditorConverter : JsonReadConverter { private readonly ILogger _logger; + private readonly IIOHelper _ioHelper; + private readonly IDataTypeService _dataTypeService; + private readonly ILocalizationService _localizationService; /// /// Initializes a new instance of the class. /// - public DataEditorConverter(ILogger logger) + public DataEditorConverter(ILogger logger, IIOHelper ioHelper, IDataTypeService dataTypeService, ILocalizationService localizationService) { _logger = logger; + _ioHelper = ioHelper; + _dataTypeService = dataTypeService; + _localizationService = localizationService; } /// @@ -62,11 +71,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."); @@ -74,7 +83,7 @@ namespace Umbraco.Core.Manifest // explicitly assign a value editor of type ValueEditor // (else the deserializer will try to read it before setting it) // (and besides it's an interface) - target.ExplicitValueEditor = new DataValueEditor(); + target.ExplicitValueEditor = new DataValueEditor(_dataTypeService, _localizationService); // in the manifest, validators are a simple dictionary eg // { @@ -86,6 +95,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 +112,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 +133,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: // @@ -135,7 +155,7 @@ namespace Umbraco.Core.Manifest if (jobject.Property("view") != null) { // explicitly assign a value editor of type ParameterValueEditor - target.ExplicitValueEditor = new DataValueEditor(); + target.ExplicitValueEditor = new DataValueEditor(_dataTypeService, _localizationService); // move the 'view' property jobject["editor"] = new JObject { ["view"] = jobject["view"] }; @@ -148,6 +168,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/ManifestContentAppFactory.cs b/src/Umbraco.Core/Manifest/ManifestContentAppFactory.cs index 1c50a4b895..e2c3ee48fa 100644 --- a/src/Umbraco.Core/Manifest/ManifestContentAppFactory.cs +++ b/src/Umbraco.Core/Manifest/ManifestContentAppFactory.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; +using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.Models.ContentEditing; using Umbraco.Core.Models.Membership; @@ -31,10 +32,12 @@ namespace Umbraco.Core.Manifest public class ManifestContentAppFactory : IContentAppFactory { private readonly ManifestContentAppDefinition _definition; + private readonly IIOHelper _ioHelper; - public ManifestContentAppFactory(ManifestContentAppDefinition definition) + public ManifestContentAppFactory(ManifestContentAppDefinition definition, IIOHelper ioHelper) { _definition = definition; + _ioHelper = ioHelper; } private ContentApp _app; @@ -132,7 +135,7 @@ namespace Umbraco.Core.Manifest Alias = _definition.Alias, Name = _definition.Name, Icon = _definition.Icon, - View = _definition.View, + View = _ioHelper.ResolveVirtualUrl(_definition.View), Weight = _definition.Weight }); } diff --git a/src/Umbraco.Core/Manifest/ManifestDashboard.cs b/src/Umbraco.Core/Manifest/ManifestDashboard.cs deleted file mode 100644 index 33af12e3cd..0000000000 --- a/src/Umbraco.Core/Manifest/ManifestDashboard.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.ComponentModel; -using Newtonsoft.Json; -using Umbraco.Core.Composing; -using Umbraco.Core.Dashboards; -using Umbraco.Core.IO; - -namespace Umbraco.Core.Manifest -{ - public class ManifestDashboard : IDashboard - { - private string _view; - - [JsonProperty("alias", Required = Required.Always)] - public string Alias { get; set; } - - [JsonProperty("weight", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] - [DefaultValue(100)] // must be equal to DashboardCollectionBuilder.DefaultWeight - public int Weight { get; set; } - - [JsonProperty("view", Required = Required.Always)] - public string View - { - get => _view; - set => _view = Current.IOHelper.ResolveVirtualUrl(value); - } - - [JsonProperty("sections")] - public string[] Sections { get; set; } = Array.Empty(); - - [JsonProperty("access")] - public IAccessRule[] AccessRules { get; set; } = Array.Empty(); - } -} diff --git a/src/Umbraco.Core/Manifest/ManifestParser.cs b/src/Umbraco.Core/Manifest/ManifestParser.cs index cac904a520..75fdde487c 100644 --- a/src/Umbraco.Core/Manifest/ManifestParser.cs +++ b/src/Umbraco.Core/Manifest/ManifestParser.cs @@ -5,23 +5,28 @@ using System.Linq; using System.Text; using Newtonsoft.Json; using Umbraco.Core.Cache; -using Umbraco.Core.Composing; using Umbraco.Core.Exceptions; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; +using Umbraco.Core.Services; namespace Umbraco.Core.Manifest { /// /// Parses the Main.js file and replaces all tokens accordingly. /// - public class ManifestParser + public class ManifestParser : IManifestParser { + private readonly IJsonSerializer _jsonSerializer; private static readonly string Utf8Preamble = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble()); private readonly IAppPolicyCache _cache; private readonly ILogger _logger; + private readonly IIOHelper _ioHelper; + private readonly IDataTypeService _dataTypeService; + private readonly ILocalizationService _localizationService; private readonly ManifestValueValidatorCollection _validators; private readonly ManifestFilterCollection _filters; @@ -30,28 +35,35 @@ namespace Umbraco.Core.Manifest /// /// Initializes a new instance of the class. /// - public ManifestParser(AppCaches appCaches, ManifestValueValidatorCollection validators, ManifestFilterCollection filters, ILogger logger) - : this(appCaches, validators, filters, "~/App_Plugins", logger) - { } + public ManifestParser(AppCaches appCaches, ManifestValueValidatorCollection validators, ManifestFilterCollection filters, ILogger logger, IIOHelper ioHelper, IDataTypeService dataTypeService, ILocalizationService localizationService, IJsonSerializer jsonSerializer) + : this(appCaches, validators, filters, "~/App_Plugins", logger, ioHelper, dataTypeService, localizationService) + { + _jsonSerializer = jsonSerializer; + } /// /// Initializes a new instance of the class. /// - private ManifestParser(AppCaches appCaches, ManifestValueValidatorCollection validators, ManifestFilterCollection filters, string path, ILogger logger) + private ManifestParser(AppCaches appCaches, ManifestValueValidatorCollection validators, ManifestFilterCollection filters, string path, ILogger logger, IIOHelper ioHelper, IDataTypeService dataTypeService, ILocalizationService localizationService) { if (appCaches == null) throw new ArgumentNullException(nameof(appCaches)); _cache = appCaches.RuntimeCache; + _ioHelper = ioHelper; + _dataTypeService = dataTypeService; + _localizationService = localizationService; _validators = validators ?? throw new ArgumentNullException(nameof(validators)); _filters = filters ?? throw new ArgumentNullException(nameof(filters)); if (string.IsNullOrWhiteSpace(path)) throw new ArgumentNullOrEmptyException(nameof(path)); + Path = path; _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } public string Path { get => _path; - set => _path = value.StartsWith("~/") ? Current.IOHelper.MapPath(value) : value; + set => _path = value.StartsWith("~/") ? _ioHelper.MapPath(value) : value; } /// @@ -154,21 +166,34 @@ namespace Umbraco.Core.Manifest /// /// Parses a manifest. /// - internal PackageManifest ParseManifest(string text) + public PackageManifest ParseManifest(string text) { if (string.IsNullOrWhiteSpace(text)) throw new ArgumentNullOrEmptyException(nameof(text)); var manifest = JsonConvert.DeserializeObject(text, - new DataEditorConverter(_logger), + new DataEditorConverter(_logger, _ioHelper, _dataTypeService, _localizationService), new ValueValidatorConverter(_validators), new DashboardAccessRuleConverter()); // scripts and stylesheets are raw string, must process here for (var i = 0; i < manifest.Scripts.Length; i++) - manifest.Scripts[i] = Current.IOHelper.ResolveVirtualUrl(manifest.Scripts[i]); + manifest.Scripts[i] = _ioHelper.ResolveVirtualUrl(manifest.Scripts[i]); for (var i = 0; i < manifest.Stylesheets.Length; i++) - manifest.Stylesheets[i] = Current.IOHelper.ResolveVirtualUrl(manifest.Stylesheets[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) @@ -180,9 +205,9 @@ namespace Umbraco.Core.Manifest } // purely for tests - internal IEnumerable ParseGridEditors(string text) + public IEnumerable ParseGridEditors(string text) { - return JsonConvert.DeserializeObject>(text); + return _jsonSerializer.Deserialize>(text); } } } diff --git a/src/Umbraco.Core/Models/ContentBase.cs b/src/Umbraco.Core/Models/ContentBase.cs index fbb68194b7..c87cb0a370 100644 --- a/src/Umbraco.Core/Models/ContentBase.cs +++ b/src/Umbraco.Core/Models/ContentBase.cs @@ -20,7 +20,7 @@ namespace Umbraco.Core.Models { private int _contentTypeId; private int _writerId; - private PropertyCollection _properties; + private IPropertyCollection _properties; private ContentCultureInfosCollection _cultureInfos; internal IReadOnlyList AllPropertyTypes { get; } @@ -135,7 +135,7 @@ namespace Umbraco.Core.Models /// [DataMember] [DoNotClone] - public PropertyCollection Properties + public IPropertyCollection Properties { get => _properties; set @@ -490,7 +490,7 @@ namespace Umbraco.Core.Models if (clonedContent._properties != null) { clonedContent._properties.CollectionChanged -= PropertiesChanged; //clear this event handler if any - clonedContent._properties = (PropertyCollection)_properties.DeepClone(); //manually deep clone + clonedContent._properties = (IPropertyCollection)_properties.DeepClone(); //manually deep clone clonedContent._properties.CollectionChanged += clonedContent.PropertiesChanged; //re-assign correct event handler } diff --git a/src/Umbraco.Core/Models/ContentTagsExtensions.cs b/src/Umbraco.Core/Models/ContentTagsExtensions.cs index dd7a716520..7f9c012722 100644 --- a/src/Umbraco.Core/Models/ContentTagsExtensions.cs +++ b/src/Umbraco.Core/Models/ContentTagsExtensions.cs @@ -34,7 +34,7 @@ namespace Umbraco.Core.Models } // gets and validates the property - private static Property GetTagProperty(this IContentBase content, string propertyTypeAlias) + private static IProperty GetTagProperty(this IContentBase content, string propertyTypeAlias) { if (content == null) throw new ArgumentNullException(nameof(content)); diff --git a/src/Umbraco.Core/Models/Property.cs b/src/Umbraco.Core/Models/Property.cs index 76349823ac..9aa9ab4d74 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. @@ -33,7 +33,7 @@ namespace Umbraco.Core.Models /// /// Initializes a new instance of the class. /// - public Property(PropertyType propertyType) + public Property(IPropertyType propertyType) { PropertyType = propertyType; } @@ -41,7 +41,7 @@ namespace Umbraco.Core.Models /// /// Initializes a new instance of the class. /// - public Property(int id, PropertyType propertyType) + public Property(int id, IPropertyType propertyType) { Id = id; PropertyType = propertyType; @@ -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 @@ -152,7 +152,7 @@ namespace Umbraco.Core.Models /// Returns the Id of the PropertyType, which this Property is based on /// [IgnoreDataMember] - internal int PropertyTypeId => PropertyType.Id; + public int PropertyTypeId => PropertyType.Id; /// /// Returns the DatabaseType that the underlaying DataType is using to store its values @@ -161,7 +161,7 @@ namespace Umbraco.Core.Models /// Only used internally when saving the property value. /// [IgnoreDataMember] - internal ValueStorageType ValueStorageType => PropertyType.ValueStorageType; + public ValueStorageType ValueStorageType => PropertyType.ValueStorageType; /// /// Gets the value. @@ -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; @@ -191,7 +191,7 @@ namespace Umbraco.Core.Models // internal - must be invoked by the content item // does *not* validate the value - content item must validate first - internal void PublishValues(string culture = "*", string segment = "*") + public void PublishValues(string culture = "*", string segment = "*") { culture = culture.NullOrWhiteSpaceAsNull(); segment = segment.NullOrWhiteSpaceAsNull(); @@ -216,7 +216,7 @@ namespace Umbraco.Core.Models } // internal - must be invoked by the content item - internal void UnpublishValues(string culture = "*", string segment = "*") + public void UnpublishValues(string culture = "*", string segment = "*") { culture = culture.NullOrWhiteSpaceAsNull(); segment = segment.NullOrWhiteSpaceAsNull(); @@ -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/PropertyCollection.cs b/src/Umbraco.Core/Models/PropertyCollection.cs index c587a45424..b82fd71eaf 100644 --- a/src/Umbraco.Core/Models/PropertyCollection.cs +++ b/src/Umbraco.Core/Models/PropertyCollection.cs @@ -12,11 +12,9 @@ namespace Umbraco.Core.Models /// [Serializable] [DataContract(IsReference = true)] - public class PropertyCollection : KeyedCollection, INotifyCollectionChanged, IDeepCloneable + public class PropertyCollection : KeyedCollection, IPropertyCollection { private readonly object _addLocker = new object(); - - internal Func AdditionValidator { get; set; } /// /// Initializes a new instance of the class. @@ -25,16 +23,6 @@ namespace Umbraco.Core.Models : base(StringComparer.InvariantCultureIgnoreCase) { } - /// - /// Initializes a new instance of the class. - /// - /// A function validating added properties. - internal PropertyCollection(Func additionValidator) - : this() - { - AdditionValidator = additionValidator; - } - /// /// Initializes a new instance of the class. /// @@ -47,7 +35,7 @@ namespace Umbraco.Core.Models /// /// Replaces all properties, whilst maintaining validation delegates. /// - internal void Reset(IEnumerable properties) + private void Reset(IEnumerable properties) { //collection events will be raised in each of these calls Clear(); @@ -60,7 +48,7 @@ namespace Umbraco.Core.Models /// /// Replaces the property at the specified index with the specified property. /// - protected override void SetItem(int index, Property property) + protected override void SetItem(int index, IProperty property) { var oldItem = index >= 0 ? this[index] : property; base.SetItem(index, property); @@ -80,7 +68,7 @@ namespace Umbraco.Core.Models /// /// Inserts the specified property at the specified index. /// - protected override void InsertItem(int index, Property property) + protected override void InsertItem(int index, IProperty property) { base.InsertItem(index, property); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, property)); @@ -95,10 +83,8 @@ namespace Umbraco.Core.Models OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } - /// - /// Adds or updates a property. - /// - internal new void Add(Property property) + /// + public new void Add(IProperty property) { lock (_addLocker) // TODO: why are we locking here and not everywhere else?! { @@ -131,7 +117,7 @@ namespace Umbraco.Core.Models /// /// Gets the index for a specified property alias. /// - public int IndexOfKey(string key) + private int IndexOfKey(string key) { for (var i = 0; i < Count; i++) { @@ -141,7 +127,7 @@ namespace Umbraco.Core.Models return -1; } - protected override string GetKeyForItem(Property item) + protected override string GetKeyForItem(IProperty item) { return item.Alias; } @@ -149,7 +135,7 @@ namespace Umbraco.Core.Models /// /// Gets the property with the specified PropertyType. /// - internal Property this[PropertyType propertyType] + internal IProperty this[IPropertyType propertyType] { get { @@ -157,7 +143,7 @@ namespace Umbraco.Core.Models } } - public bool TryGetValue(string propertyTypeAlias, out Property property) + public bool TryGetValue(string propertyTypeAlias, out IProperty property) { property = this.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias)); return property != null; @@ -173,10 +159,9 @@ namespace Umbraco.Core.Models CollectionChanged?.Invoke(this, args); } - /// - /// Ensures that the collection contains properties for the specified property types. - /// - protected internal void EnsurePropertyTypes(IEnumerable propertyTypes) + + /// + public void EnsurePropertyTypes(IEnumerable propertyTypes) { if (propertyTypes == null) return; @@ -185,10 +170,9 @@ namespace Umbraco.Core.Models Add(new Property(propertyType)); } - /// - /// Ensures that the collection does not contain properties not in the specified property types. - /// - protected internal void EnsureCleanPropertyTypes(IEnumerable propertyTypes) + + /// + public void EnsureCleanPropertyTypes(IEnumerable propertyTypes) { if (propertyTypes == null) return; diff --git a/src/Umbraco.Core/Models/PropertyTagsExtensions.cs b/src/Umbraco.Core/Models/PropertyTagsExtensions.cs index 63cf870221..1bac5c98f1 100644 --- a/src/Umbraco.Core/Models/PropertyTagsExtensions.cs +++ b/src/Umbraco.Core/Models/PropertyTagsExtensions.cs @@ -20,7 +20,7 @@ namespace Umbraco.Core.Models // gets the tag configuration for a property // from the datatype configuration, and the editor tag configuration attribute - internal static TagConfiguration GetTagConfiguration(this Property property) + internal static TagConfiguration GetTagConfiguration(this IProperty property) { if (property == null) throw new ArgumentNullException(nameof(property)); @@ -44,7 +44,7 @@ namespace Umbraco.Core.Models /// The tags. /// A value indicating whether to merge the tags with existing tags instead of replacing them. /// A culture, for multi-lingual properties. - public static void AssignTags(this Property property, IEnumerable tags, bool merge = false, string culture = null) + public static void AssignTags(this IProperty property, IEnumerable tags, bool merge = false, string culture = null) { if (property == null) throw new ArgumentNullException(nameof(property)); @@ -56,7 +56,7 @@ namespace Umbraco.Core.Models } // assumes that parameters are consistent with the datatype configuration - private static void AssignTags(this Property property, IEnumerable tags, bool merge, TagsStorageType storageType, char delimiter, string culture) + private static void AssignTags(this IProperty property, IEnumerable tags, bool merge, TagsStorageType storageType, char delimiter, string culture) { // set the property value var trimmedTags = tags.Select(x => x.Trim()).ToArray(); @@ -97,7 +97,7 @@ namespace Umbraco.Core.Models /// The property. /// The tags. /// A culture, for multi-lingual properties. - public static void RemoveTags(this Property property, IEnumerable tags, string culture = null) + public static void RemoveTags(this IProperty property, IEnumerable tags, string culture = null) { if (property == null) throw new ArgumentNullException(nameof(property)); @@ -109,7 +109,7 @@ namespace Umbraco.Core.Models } // assumes that parameters are consistent with the datatype configuration - private static void RemoveTags(this Property property, IEnumerable tags, TagsStorageType storageType, char delimiter, string culture) + private static void RemoveTags(this IProperty property, IEnumerable tags, TagsStorageType storageType, char delimiter, string culture) { // already empty = nothing to do var value = property.GetValue(culture)?.ToString(); @@ -131,7 +131,7 @@ namespace Umbraco.Core.Models } // used by ContentRepositoryBase - internal static IEnumerable GetTagsValue(this Property property, string culture = null) + internal static IEnumerable GetTagsValue(this IProperty property, string culture = null) { if (property == null) throw new ArgumentNullException(nameof(property)); @@ -142,7 +142,7 @@ namespace Umbraco.Core.Models return property.GetTagsValue(configuration.StorageType, configuration.Delimiter, culture); } - private static IEnumerable GetTagsValue(this Property property, TagsStorageType storageType, char delimiter, string culture = null) + private static IEnumerable GetTagsValue(this IProperty property, TagsStorageType storageType, char delimiter, string culture = null) { if (property == null) throw new ArgumentNullException(nameof(property)); @@ -182,7 +182,7 @@ namespace Umbraco.Core.Models /// This is used both by the content repositories to initialize a property with some tag values, and by the /// content controllers to update a property with values received from the property editor. /// - internal static void SetTagsValue(this Property property, object value, TagConfiguration tagConfiguration, string culture) + internal static void SetTagsValue(this IProperty property, object value, TagConfiguration tagConfiguration, string culture) { if (property == null) throw new ArgumentNullException(nameof(property)); if (tagConfiguration == null) throw new ArgumentNullException(nameof(tagConfiguration)); @@ -195,7 +195,7 @@ namespace Umbraco.Core.Models // assumes that parameters are consistent with the datatype configuration // value can be an enumeration of string, or a serialized value using storageType format - private static void SetTagsValue(Property property, object value, TagsStorageType storageType, char delimiter, string culture) + private static void SetTagsValue(IProperty property, object value, TagsStorageType storageType, char delimiter, string culture) { if (value == null) value = Enumerable.Empty(); diff --git a/src/Umbraco.Core/Models/PropertyType.cs b/src/Umbraco.Core/Models/PropertyType.cs index 40af478ab8..3cbe1ab70b 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; @@ -36,7 +36,7 @@ namespace Umbraco.Core.Models { if (dataType == null) throw new ArgumentNullException(nameof(dataType)); - if(dataType.HasIdentity) + if (dataType.HasIdentity) _dataTypeId = dataType.Id; _propertyEditorAlias = dataType.EditorAlias; @@ -58,14 +58,16 @@ namespace Umbraco.Core.Models /// public PropertyType(string propertyEditorAlias, ValueStorageType valueStorageType) : this(propertyEditorAlias, valueStorageType, false) - { } + { + } /// /// Initializes a new instance of the class. /// public PropertyType(string propertyEditorAlias, ValueStorageType valueStorageType, string propertyTypeAlias) : this(propertyEditorAlias, valueStorageType, false, propertyTypeAlias) - { } + { + } /// /// Initializes a new instance of the class. @@ -99,9 +101,7 @@ namespace Umbraco.Core.Models /// public bool SupportsPublishing { get; internal set; } - /// - /// Gets of sets the name of the property type. - /// + /// [DataMember] public string Name { @@ -109,9 +109,7 @@ namespace Umbraco.Core.Models set => SetPropertyValueAndDetectChanges(value, ref _name, nameof(Name)); } - /// - /// Gets of sets the alias of the property type. - /// + /// [DataMember] public virtual string Alias { @@ -119,9 +117,7 @@ namespace Umbraco.Core.Models set => SetPropertyValueAndDetectChanges(SanitizeAlias(value), ref _alias, nameof(Alias)); } - /// - /// Gets of sets the description of the property type. - /// + /// [DataMember] public string Description { @@ -129,9 +125,7 @@ namespace Umbraco.Core.Models set => SetPropertyValueAndDetectChanges(value, ref _description, nameof(Description)); } - /// - /// Gets or sets the identifier of the datatype for this property type. - /// + /// [DataMember] public int DataTypeId { @@ -146,9 +140,7 @@ namespace Umbraco.Core.Models set => SetPropertyValueAndDetectChanges(value, ref _dataTypeKey, nameof(DataTypeKey)); } - /// - /// Gets or sets the alias of the property editor for this property type. - /// + /// [DataMember] public string PropertyEditorAlias { @@ -156,11 +148,9 @@ namespace Umbraco.Core.Models set => SetPropertyValueAndDetectChanges(value, ref _propertyEditorAlias, nameof(PropertyEditorAlias)); } - /// - /// Gets or sets the database type for storing value for this property type. - /// + /// [DataMember] - internal ValueStorageType ValueStorageType + public ValueStorageType ValueStorageType { get => _valueStorageType; set @@ -170,20 +160,16 @@ namespace Umbraco.Core.Models } } - /// - /// Gets or sets the identifier of the property group this property type belongs to. - /// - /// For generic properties, the value is null. + /// [DataMember] - internal Lazy PropertyGroupId + public Lazy PropertyGroupId { get => _propertyGroupId; set => SetPropertyValueAndDetectChanges(value, ref _propertyGroupId, nameof(PropertyGroupId)); } - /// - /// Gets of sets a value indicating whether a value for this property type is required. - /// + + /// [DataMember] public bool Mandatory { @@ -191,9 +177,8 @@ namespace Umbraco.Core.Models set => SetPropertyValueAndDetectChanges(value, ref _mandatory, nameof(Mandatory)); } - /// - /// Gets of sets the sort order of the property type. - /// + + /// [DataMember] public int SortOrder { @@ -201,9 +186,7 @@ namespace Umbraco.Core.Models set => SetPropertyValueAndDetectChanges(value, ref _sortOrder, nameof(SortOrder)); } - /// - /// Gets or sets the regular expression validating the property values. - /// + /// [DataMember] public string ValidationRegExp { @@ -211,21 +194,14 @@ namespace Umbraco.Core.Models set => SetPropertyValueAndDetectChanges(value, ref _validationRegExp, nameof(ValidationRegExp)); } - /// - /// Gets or sets the content variation of the property type. - /// + /// public ContentVariation Variations { get => _variations; set => SetPropertyValueAndDetectChanges(value, ref _variations, nameof(Variations)); } - /// - /// Determines whether the property type supports a combination of culture and segment. - /// - /// The culture. - /// The segment. - /// A value indicating whether wildcards are valid. + /// public bool SupportsVariation(string culture, string segment, bool wildcards = false) { // exact validation: cannot accept a 'null' culture if the property type varies @@ -249,7 +225,7 @@ namespace Umbraco.Core.Models /// If the value is of the expected type, it can be directly assigned to the property. /// Otherwise, some conversion is required. /// - public bool IsOfExpectedPropertyType(object value) + private bool IsOfExpectedPropertyType(object value) { // null values are assumed to be ok if (value == null) @@ -275,19 +251,7 @@ namespace Umbraco.Core.Models } } - /// - /// Determines whether a value can be assigned to a property. - /// - public bool IsValueAssignable(object value) => TryConvertAssignedValue(value, false, out _); - - /// - /// Converts a value assigned to a property. - /// - /// - /// The input value can be pretty much anything, and is converted to the actual CLR type - /// expected by the property (eg an integer if the property values are integers). - /// Throws if the value cannot be converted. - /// + /// public object ConvertAssignedValue(object value) => TryConvertAssignedValue(value, true, out var converted) ? converted : null; /// @@ -296,8 +260,6 @@ namespace Umbraco.Core.Models /// /// /// - public bool TryConvertAssignedValue(object value, out object converted) => TryConvertAssignedValue(value, false, out converted); - private bool TryConvertAssignedValue(object value, bool throwOnError, out object converted) { var isOfExpectedType = IsOfExpectedPropertyType(value); @@ -332,6 +294,7 @@ namespace Umbraco.Core.Models converted = convInt.Result; return true; } + if (throwOnError) ThrowTypeException(value, typeof(int), Alias); return false; @@ -347,6 +310,7 @@ namespace Umbraco.Core.Models converted = convDecimal.Result.Normalize(); return true; } + if (throwOnError) ThrowTypeException(value, typeof(decimal), Alias); return false; @@ -360,6 +324,7 @@ namespace Umbraco.Core.Models converted = convDateTime.Result; return true; } + if (throwOnError) ThrowTypeException(value, typeof(DateTime), Alias); return false; @@ -413,7 +378,7 @@ namespace Umbraco.Core.Models { base.PerformDeepClone(clone); - var clonedEntity = (PropertyType)clone; + var clonedEntity = (PropertyType) clone; //need to manually assign the Lazy value as it will not be automatically mapped if (PropertyGroupId != null) diff --git a/src/Umbraco.Core/Models/SimpleContentType.cs b/src/Umbraco.Core/Models/SimpleContentType.cs index 5c81017ec8..fc84d15529 100644 --- a/src/Umbraco.Core/Models/SimpleContentType.cs +++ b/src/Umbraco.Core/Models/SimpleContentType.cs @@ -105,6 +105,7 @@ namespace Umbraco.Core.Models // we have to have all this, because we're an IUmbracoEntity, because that is // required by the query expression visitor / SimpleContentTypeMapper + // TODO: Make the query expression visitor use a different common interface, or investigate removing IRememberBeingDirty from being a requirement on that interface and expliclty checking for that throughout the code? string ITreeEntity.Name { get => this.Name; set => throw new NotImplementedException(); } int IEntity.Id { get => this.Id; set => throw new NotImplementedException(); } @@ -130,5 +131,7 @@ namespace Umbraco.Core.Models bool ICanBeDirty.IsPropertyDirty(string propName) => throw new NotImplementedException(); IEnumerable ICanBeDirty.GetDirtyProperties() => throw new NotImplementedException(); void ICanBeDirty.ResetDirtyProperties() => throw new NotImplementedException(); + public void DisableChangeTracking() => throw new NotImplementedException(); + public void EnableChangeTracking() => throw new NotImplementedException(); } } diff --git a/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs b/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs index 9d9482fedb..fc31f61763 100644 --- a/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs @@ -46,7 +46,7 @@ namespace Umbraco.Core.Persistence.Factories return properties; } - private static PropertyDataDto BuildDto(int versionId, Property property, int? languageId, string segment, object value) + private static PropertyDataDto BuildDto(int versionId, IProperty property, int? languageId, string segment, object value) { var dto = new PropertyDataDto { VersionId = versionId, PropertyTypeId = property.PropertyTypeId }; @@ -109,7 +109,7 @@ namespace Umbraco.Core.Persistence.Factories /// The value of this will be used to populate the edited cultures in the umbracoDocumentCultureVariation table. /// /// - public static IEnumerable BuildDtos(ContentVariation contentVariation, int currentVersionId, int publishedVersionId, IEnumerable properties, + public static IEnumerable BuildDtos(ContentVariation contentVariation, int currentVersionId, int publishedVersionId, IEnumerable properties, ILanguageRepository languageRepository, out bool edited, out HashSet editedCultures) { diff --git a/src/Umbraco.Core/PropertyEditors/ConfigurationEditorOfTConfiguration.cs b/src/Umbraco.Core/PropertyEditors/ConfigurationEditorOfTConfiguration.cs index 7008c73433..bee923b50e 100644 --- a/src/Umbraco.Core/PropertyEditors/ConfigurationEditorOfTConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/ConfigurationEditorOfTConfiguration.cs @@ -35,6 +35,7 @@ namespace Umbraco.Core.PropertyEditors ConfigurationField field; + var attributeView = Current.IOHelper.ResolveVirtualUrl(attribute.View); // if the field does not have its own type, use the base type if (attribute.Type == null) { @@ -47,7 +48,7 @@ namespace Umbraco.Core.PropertyEditors PropertyType = property.PropertyType, Description = attribute.Description, HideLabel = attribute.HideLabel, - View = attribute.View + View = attributeView }; fields.Add(field); @@ -81,7 +82,7 @@ namespace Umbraco.Core.PropertyEditors field.Name = attribute.Name; if (!string.IsNullOrWhiteSpace(attribute.View)) - field.View = attribute.View; + field.View = attributeView; if (!string.IsNullOrWhiteSpace(attribute.Description)) field.Description = attribute.Description; 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/DataEditor.cs b/src/Umbraco.Core/PropertyEditors/DataEditor.cs index dbb2fc467e..047c0f0683 100644 --- a/src/Umbraco.Core/PropertyEditors/DataEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/DataEditor.cs @@ -165,7 +165,7 @@ namespace Umbraco.Core.PropertyEditors if (Attribute == null) throw new InvalidOperationException("The editor does not specify a view."); - return new DataValueEditor(Attribute); + return new DataValueEditor(Current.Services.DataTypeService, Current.Services.LocalizationService, Attribute); } /// diff --git a/src/Umbraco.Core/PropertyEditors/DataValueEditor.cs b/src/Umbraco.Core/PropertyEditors/DataValueEditor.cs index a9ce27d964..afd77a3479 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; @@ -21,32 +20,24 @@ namespace Umbraco.Core.PropertyEditors /// public class DataValueEditor : IDataValueEditor { - private string _view; + protected IDataTypeService DataTypeService { get; } + protected ILocalizationService LocalizationService { get; } /// /// Initializes a new instance of the class. /// - public DataValueEditor() // for tests, and manifest + public DataValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService) // for tests, and manifest { ValueType = ValueTypes.String; Validators = new List(); + DataTypeService = dataTypeService; + LocalizationService = localizationService; } /// /// Initializes a new instance of the class. /// - public DataValueEditor(string view, params IValueValidator[] validators) // not used - : this() - { - View = view; - Validators.AddRange(validators); - } - - /// - /// Initializes a new instance of the class. - /// - public DataValueEditor(DataEditorAttribute attribute) - : this() + public DataValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, DataEditorAttribute attribute) { if (attribute == null) throw new ArgumentNullException(nameof(attribute)); @@ -57,6 +48,9 @@ namespace Umbraco.Core.PropertyEditors View = view; ValueType = attribute.ValueType; HideLabel = attribute.HideLabel; + + DataTypeService = dataTypeService; + LocalizationService = localizationService; } /// @@ -72,11 +66,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 @@ -115,17 +105,17 @@ namespace Umbraco.Core.PropertyEditors /// A collection of validators for the pre value editor /// [JsonProperty("validation")] - public List Validators { get; private set; } + public List Validators { get; private set; } = new List(); /// /// Gets the validator used to validate the special property type -level "required". /// - public virtual IValueRequiredValidator RequiredValidator => new RequiredValidator(); + public virtual IValueRequiredValidator RequiredValidator => new RequiredValidator(); //TODO: Pass in the ILocalizedTextService here and not rely on Current! /// /// Gets the validator used to validate the special property type -level "format". /// - public virtual IValueFormatValidator FormatValidator => new RegexValidator(); + public virtual IValueFormatValidator FormatValidator => new RegexValidator(); //TODO: Pass in the ILocalizedTextService here and not rely on Current! /// /// If this is true than the editor will be displayed full width without a label @@ -237,7 +227,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, string culture = null, string segment = null) { var val = property.GetValue(culture, segment); if (val == null) return string.Empty; @@ -288,7 +278,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, bool published) { published &= property.PropertyType.SupportsPublishing; @@ -306,7 +296,7 @@ namespace Umbraco.Core.PropertyEditors if (pvalue.Segment != null) xElement.Add(new XAttribute("segment", pvalue.Segment)); - var xValue = ConvertDbToXml(property.PropertyType, value, dataTypeService); + var xValue = ConvertDbToXml(property.PropertyType, value); xElement.Add(xValue); yield return xElement; @@ -322,12 +312,12 @@ 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) { //check for null or empty value, we don't want to return CDATA if that is the case if (value == null || value.ToString().IsNullOrWhiteSpace()) { - return new XText(ConvertDbToString(propertyType, value, dataTypeService)); + return new XText(ConvertDbToString(propertyType, value)); } switch (ValueTypes.ToStorageType(ValueType)) @@ -335,11 +325,11 @@ namespace Umbraco.Core.PropertyEditors case ValueStorageType.Date: case ValueStorageType.Integer: case ValueStorageType.Decimal: - return new XText(ConvertDbToString(propertyType, value, dataTypeService)); + return new XText(ConvertDbToString(propertyType, value)); case ValueStorageType.Nvarchar: case ValueStorageType.Ntext: //put text in cdata - return new XCData(ConvertDbToString(propertyType, value, dataTypeService)); + return new XCData(ConvertDbToString(propertyType, value)); default: throw new ArgumentOutOfRangeException(); } @@ -348,7 +338,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) { if (value == null) return string.Empty; diff --git a/src/Umbraco.Core/PropertyEditors/DefaultPropertyIndexValueFactory.cs b/src/Umbraco.Core/PropertyEditors/DefaultPropertyIndexValueFactory.cs index 413f31d79e..0d06b59a9c 100644 --- a/src/Umbraco.Core/PropertyEditors/DefaultPropertyIndexValueFactory.cs +++ b/src/Umbraco.Core/PropertyEditors/DefaultPropertyIndexValueFactory.cs @@ -9,7 +9,7 @@ namespace Umbraco.Core.PropertyEditors public class DefaultPropertyIndexValueFactory : IPropertyIndexValueFactory { /// - public IEnumerable>> GetIndexValues(Property property, string culture, string segment, bool published) + public IEnumerable>> GetIndexValues(IProperty property, string culture, string segment, bool published) { yield return new KeyValuePair>( property.Alias, diff --git a/src/Umbraco.Core/PropertyEditors/LabelPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/LabelPropertyEditor.cs index 60b7d55c01..e47d35107a 100644 --- a/src/Umbraco.Core/PropertyEditors/LabelPropertyEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/LabelPropertyEditor.cs @@ -1,4 +1,6 @@ -using Umbraco.Core.Logging; +using Umbraco.Core.Composing; +using Umbraco.Core.Logging; +using Umbraco.Core.Services; namespace Umbraco.Core.PropertyEditors { @@ -20,7 +22,7 @@ namespace Umbraco.Core.PropertyEditors { } /// - protected override IDataValueEditor CreateValueEditor() => new LabelPropertyValueEditor(Attribute); + protected override IDataValueEditor CreateValueEditor() => new LabelPropertyValueEditor(Current.Services.DataTypeService, Current.Services.LocalizationService, Attribute); /// protected override IConfigurationEditor CreateConfigurationEditor() => new LabelConfigurationEditor(); @@ -28,8 +30,8 @@ namespace Umbraco.Core.PropertyEditors // provides the property value editor internal class LabelPropertyValueEditor : DataValueEditor { - public LabelPropertyValueEditor(DataEditorAttribute attribute) - : base(attribute) + public LabelPropertyValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, DataEditorAttribute attribute) + : base(dataTypeService, localizationService, attribute) { } /// diff --git a/src/Umbraco.Core/PropertyEditors/ManifestValueValidatorCollectionBuilder.cs b/src/Umbraco.Core/PropertyEditors/ManifestValueValidatorCollectionBuilder.cs deleted file mode 100644 index 8f7c68c813..0000000000 --- a/src/Umbraco.Core/PropertyEditors/ManifestValueValidatorCollectionBuilder.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Umbraco.Core.Composing; - -namespace Umbraco.Core.PropertyEditors -{ - internal class ManifestValueValidatorCollectionBuilder : LazyCollectionBuilderBase - { - protected override ManifestValueValidatorCollectionBuilder This => this; - } -} diff --git a/src/Umbraco.Core/PropertyEditors/Validators/RegexValidator.cs b/src/Umbraco.Core/PropertyEditors/Validators/RegexValidator.cs index e405fa3a3e..2bd3e0ab40 100644 --- a/src/Umbraco.Core/PropertyEditors/Validators/RegexValidator.cs +++ b/src/Umbraco.Core/PropertyEditors/Validators/RegexValidator.cs @@ -11,11 +11,13 @@ namespace Umbraco.Core.PropertyEditors.Validators /// /// A validator that validates that the value against a regular expression. /// - internal sealed class RegexValidator : IValueFormatValidator, IManifestValueValidator + public sealed class RegexValidator : IValueFormatValidator, IManifestValueValidator { private readonly ILocalizedTextService _textService; private string _regex; + const string ValueIsInvalid = "Value is invalid, it does not match the correct pattern"; + /// public string ValidationName => "Regex"; @@ -26,7 +28,7 @@ namespace Umbraco.Core.PropertyEditors.Validators /// and the regular expression is supplied at validation time. This constructor is also used when /// the validator is used as an and the regular expression /// is supplied via the method. - public RegexValidator() : this(Current.Services.TextService, null) + public RegexValidator() : this(Current.HasFactory ? Current.Services.TextService : null, null) { } /// @@ -68,7 +70,9 @@ namespace Umbraco.Core.PropertyEditors.Validators { if (string.IsNullOrWhiteSpace(format)) throw new ArgumentNullOrEmptyException(nameof(format)); if (value == null || !new Regex(format).IsMatch(value.ToString())) - yield return new ValidationResult(_textService.Localize("validation", "invalidPattern"), new[] { "value" }); + { + yield return new ValidationResult(_textService?.Localize("validation", "invalidPattern") ?? ValueIsInvalid, new[] { "value" }); + } } } } diff --git a/src/Umbraco.Core/PropertyEditors/Validators/RequiredValidator.cs b/src/Umbraco.Core/PropertyEditors/Validators/RequiredValidator.cs index c51f572817..30342fbf2d 100644 --- a/src/Umbraco.Core/PropertyEditors/Validators/RequiredValidator.cs +++ b/src/Umbraco.Core/PropertyEditors/Validators/RequiredValidator.cs @@ -8,11 +8,13 @@ namespace Umbraco.Core.PropertyEditors.Validators /// /// A validator that validates that the value is not null or empty (if it is a string) /// - internal sealed class RequiredValidator : IValueRequiredValidator, IManifestValueValidator + public sealed class RequiredValidator : IValueRequiredValidator, IManifestValueValidator { private readonly ILocalizedTextService _textService; + const string ValueCannotBeNull = "Value cannot be null"; + const string ValueCannotBeEmpty = "Value cannot be empty"; - public RequiredValidator() : this(Current.Services.TextService) + public RequiredValidator() : this(Current.HasFactory ? Current.Services.TextService : null) { } @@ -35,20 +37,24 @@ namespace Umbraco.Core.PropertyEditors.Validators { if (value == null) { - yield return new ValidationResult(_textService.Localize("validation", "invalidNull"), new[] {"value"}); + yield return new ValidationResult(_textService?.Localize("validation", "invalidNull") ?? ValueCannotBeNull, new[] {"value"}); yield break; } if (valueType.InvariantEquals(ValueTypes.Json)) { if (value.ToString().DetectIsEmptyJson()) - yield return new ValidationResult(_textService.Localize("validation", "invalidEmpty"), new[] { "value" }); + { + + yield return new ValidationResult(_textService?.Localize("validation", "invalidEmpty") ?? ValueCannotBeEmpty, new[] { "value" }); + } + yield break; } if (value.ToString().IsNullOrWhiteSpace()) { - yield return new ValidationResult(_textService.Localize("validation", "invalidEmpty"), new[] { "value" }); + yield return new ValidationResult(_textService?.Localize("validation", "invalidEmpty") ?? ValueCannotBeEmpty, new[] { "value" }); } } } diff --git a/src/Umbraco.Core/Services/Implement/ContentService.cs b/src/Umbraco.Core/Services/Implement/ContentService.cs index 5a43738230..2fa75e2f3f 100644 --- a/src/Umbraco.Core/Services/Implement/ContentService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentService.cs @@ -1402,7 +1402,7 @@ namespace Umbraco.Core.Services.Implement if (d.Trashed) continue; // won't publish //publish the culture values and validate the property values, if validation fails, log the invalid properties so the develeper has an idea of what has failed - Property[] invalidProperties = null; + IProperty[] invalidProperties = null; var impact = CultureImpact.Explicit(culture, IsDefaultCulture(allLangs, culture)); var tryPublish = d.PublishCulture(impact) && _propertyValidationService.Value.IsPropertyDataValid(d, out invalidProperties, impact); if (invalidProperties != null && invalidProperties.Length > 0) @@ -2602,7 +2602,7 @@ namespace Umbraco.Core.Services.Implement return new PublishResult(PublishResultType.FailedPublishContentInvalid, evtMsgs, content); //validate the property values - Property[] invalidProperties = null; + IProperty[] invalidProperties = null; if (!impactsToPublish.All(x => _propertyValidationService.Value.IsPropertyDataValid(content, out invalidProperties, x))) return new PublishResult(PublishResultType.FailedPublishContentInvalid, evtMsgs, content) { diff --git a/src/Umbraco.Core/Services/Implement/EntityXmlSerializer.cs b/src/Umbraco.Core/Services/Implement/EntityXmlSerializer.cs index bc21da15a7..f488c12657 100644 --- a/src/Umbraco.Core/Services/Implement/EntityXmlSerializer.cs +++ b/src/Umbraco.Core/Services/Implement/EntityXmlSerializer.cs @@ -77,7 +77,7 @@ namespace Umbraco.Core.Services.Implement var children = _contentService.GetPagedChildren(content.Id, page++, pageSize, out total); SerializeChildren(children, xml, published); } - + } return xml; @@ -552,7 +552,7 @@ namespace Umbraco.Core.Services.Implement } // exports a property as XElements. - private IEnumerable SerializeProperty(Property property, bool published) + private IEnumerable SerializeProperty(IProperty property, bool published) { var propertyType = property.PropertyType; @@ -560,7 +560,7 @@ namespace Umbraco.Core.Services.Implement var propertyEditor = Current.PropertyEditors[propertyType.PropertyEditorAlias]; return propertyEditor == null ? Array.Empty() - : propertyEditor.GetValueEditor().ConvertDbToXml(property, _dataTypeService, _localizationService, published); + : propertyEditor.GetValueEditor().ConvertDbToXml(property, published); } // exports an IContent item descendants. diff --git a/src/Umbraco.Core/Services/PropertyValidationService.cs b/src/Umbraco.Core/Services/PropertyValidationService.cs index a037a83920..1704d52206 100644 --- a/src/Umbraco.Core/Services/PropertyValidationService.cs +++ b/src/Umbraco.Core/Services/PropertyValidationService.cs @@ -31,7 +31,7 @@ namespace Umbraco.Core.Services /// /// Validates the content item's properties pass validation rules /// - public bool IsPropertyDataValid(IContent content, out Property[] invalidProperties, CultureImpact impact) + public bool IsPropertyDataValid(IContent content, out IProperty[] invalidProperties, CultureImpact impact) { // select invalid properties invalidProperties = content.Properties.Where(x => @@ -66,7 +66,7 @@ namespace Umbraco.Core.Services /// /// Gets a value indicating whether the property has valid values. /// - public bool IsPropertyValid(Property property, string culture = "*", string segment = "*") + public bool IsPropertyValid(IProperty property, string culture = "*", string segment = "*") { //NOTE - the pvalue and vvalues logic in here is borrowed directly from the Property.Values setter so if you are wondering what that's all about, look there. // The underlying Property._pvalue and Property._vvalues are not exposed but we can re-create these values ourselves which is what it's doing. @@ -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/Services/PublishResult.cs b/src/Umbraco.Core/Services/PublishResult.cs index 4f1ff776a2..fe11d77cf3 100644 --- a/src/Umbraco.Core/Services/PublishResult.cs +++ b/src/Umbraco.Core/Services/PublishResult.cs @@ -32,6 +32,6 @@ namespace Umbraco.Core.Services /// /// Gets or sets the invalid properties, if the status failed due to validation. /// - public IEnumerable InvalidProperties { get; set; } + public IEnumerable InvalidProperties { get; set; } } } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index ab5198f677..65776ab57c 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 @@ -182,9 +184,7 @@ - - - + @@ -218,16 +218,12 @@ - - - - @@ -262,8 +258,10 @@ - + + + @@ -271,14 +269,9 @@ - - - - - @@ -380,10 +373,7 @@ - - - @@ -419,9 +409,6 @@ - - - @@ -470,11 +457,7 @@ - - - - @@ -548,10 +531,8 @@ - - @@ -957,22 +938,13 @@ - - - - - - - - - diff --git a/src/Umbraco.Examine/BaseValueSetBuilder.cs b/src/Umbraco.Examine/BaseValueSetBuilder.cs index 93cee88231..4a306aa5ff 100644 --- a/src/Umbraco.Examine/BaseValueSetBuilder.cs +++ b/src/Umbraco.Examine/BaseValueSetBuilder.cs @@ -24,7 +24,7 @@ namespace Umbraco.Examine /// public abstract IEnumerable GetValueSets(params TContent[] content); - protected void AddPropertyValue(Property property, string culture, string segment, IDictionary> values) + protected void AddPropertyValue(IProperty property, string culture, string segment, IDictionary> values) { var editor = _propertyEditors[property.PropertyType.PropertyEditorAlias]; if (editor == null) return; @@ -61,7 +61,7 @@ namespace Umbraco.Examine else values.Add($"{keyVal.Key}{cultureSuffix}", val.Yield()); } - + break; } } 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/CoreThings/ObjectExtensionsTests.cs b/src/Umbraco.Tests/CoreThings/ObjectExtensionsTests.cs index 486d35540c..544c6335e1 100644 --- a/src/Umbraco.Tests/CoreThings/ObjectExtensionsTests.cs +++ b/src/Umbraco.Tests/CoreThings/ObjectExtensionsTests.cs @@ -7,6 +7,7 @@ using System.Web.UI.WebControls; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.PropertyEditors; +using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests.CoreThings { @@ -300,10 +301,7 @@ namespace Umbraco.Tests.CoreThings [Test] public void Value_Editor_Can_Convert_Decimal_To_Decimal_Clr_Type() { - var valueEditor = new DataValueEditor - { - ValueType = ValueTypes.Decimal - }; + var valueEditor = TestHelper.CreateDataValueEditor(ValueTypes.Decimal); var result = valueEditor.TryConvertValueToCrlType(12.34d); Assert.IsTrue(result.Success); diff --git a/src/Umbraco.Tests/Manifest/ManifestContentAppTests.cs b/src/Umbraco.Tests/Manifest/ManifestContentAppTests.cs index 1e02f562e3..fe3e8a6bdf 100644 --- a/src/Umbraco.Tests/Manifest/ManifestContentAppTests.cs +++ b/src/Umbraco.Tests/Manifest/ManifestContentAppTests.cs @@ -3,9 +3,11 @@ using System.Linq; using Moq; using Newtonsoft.Json; using NUnit.Framework; +using Umbraco.Core.IO; using Umbraco.Core.Manifest; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; +using Umbraco.Web.Composing; namespace Umbraco.Tests.Manifest { @@ -67,7 +69,7 @@ namespace Umbraco.Tests.Manifest private void AssertDefinition(object source, bool expected, string[] show, IReadOnlyUserGroup[] groups) { var definition = JsonConvert.DeserializeObject("{" + (show.Length == 0 ? "" : " \"show\": [" + string.Join(",", show.Select(x => "\"" + x + "\"")) + "] ") + "}"); - var factory = new ManifestContentAppFactory(definition); + var factory = new ManifestContentAppFactory(definition, IOHelper.Default); var app = factory.GetContentAppFor(source, groups); if (expected) Assert.IsNotNull(app); diff --git a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs index 1c90f68d62..955c7ba776 100644 --- a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs +++ b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs @@ -13,6 +13,8 @@ using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.Validators; using Umbraco.Core.Services; using Umbraco.Core.Dashboards; +using Umbraco.Core.IO; +using Umbraco.Core.Serialization; namespace Umbraco.Tests.Manifest { @@ -24,27 +26,12 @@ namespace Umbraco.Tests.Manifest [SetUp] public void Setup() { - Current.Reset(); - var factory = Mock.Of(); - Current.Factory = factory; - - var serviceContext = ServiceContext.CreatePartial( - localizedTextService: Mock.Of()); - - Mock.Get(factory) - .Setup(x => x.GetInstance(It.IsAny())) - .Returns(x => - { - if (x == typeof(ServiceContext)) return serviceContext; - throw new Exception("oops"); - }); - var validators = new IManifestValueValidator[] { new RequiredValidator(Mock.Of()), new RegexValidator(Mock.Of(), null) }; - _parser = new ManifestParser(AppCaches.Disabled, new ManifestValueValidatorCollection(validators), new ManifestFilterCollection(Array.Empty()), Mock.Of()); + _parser = new ManifestParser(AppCaches.Disabled, new ManifestValueValidatorCollection(validators), new ManifestFilterCollection(Array.Empty()), Mock.Of(), IOHelper.Default, Mock.Of(), Mock.Of(), new JsonNetSerializer()); } [Test] diff --git a/src/Umbraco.Tests/Mapping/MappingTests.cs b/src/Umbraco.Tests/Mapping/MappingTests.cs index e6a382692c..ad336168c6 100644 --- a/src/Umbraco.Tests/Mapping/MappingTests.cs +++ b/src/Umbraco.Tests/Mapping/MappingTests.cs @@ -285,10 +285,10 @@ namespace Umbraco.Tests.Mapping { public void DefineMaps(UmbracoMapper mapper) { - mapper.Define((source, context) => new ContentPropertyDto(), Map); + mapper.Define((source, context) => new ContentPropertyDto(), Map); } - private static void Map(Property source, ContentPropertyDto target, MapperContext context) + private static void Map(IProperty source, ContentPropertyDto target, MapperContext context) { } } diff --git a/src/Umbraco.Tests/Models/Collections/Item.cs b/src/Umbraco.Tests/Models/Collections/Item.cs index 5d1ab24fb0..7c7f207aa2 100644 --- a/src/Umbraco.Tests/Models/Collections/Item.cs +++ b/src/Umbraco.Tests/Models/Collections/Item.cs @@ -11,6 +11,7 @@ namespace Umbraco.Tests.Models.Collections { public abstract class Item : IEntity, ICanBeDirty { + private bool _withChanges = true; // should we track changes? private bool _hasIdentity; private int _id; private Guid _key; @@ -26,10 +27,7 @@ namespace Umbraco.Tests.Models.Collections [DataMember] public int Id { - get - { - return _id; - } + get => _id; set { _id = value; @@ -45,14 +43,8 @@ namespace Umbraco.Tests.Models.Collections [DataMember] public Guid Key { - get - { - if (_key == Guid.Empty) - return _id.ToGuid(); - - return _key; - } - set { _key = value; } + get => _key == Guid.Empty ? _id.ToGuid() : _key; + set => _key = value; } /// @@ -93,12 +85,12 @@ namespace Umbraco.Tests.Models.Collections /// The property info. protected virtual void OnPropertyChanged(PropertyInfo propertyInfo) { + if (_withChanges == false) + return; + _propertyChangedInfo[propertyInfo.Name] = true; - if (PropertyChanged != null) - { - PropertyChanged(this, new PropertyChangedEventArgs(propertyInfo.Name)); - } + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyInfo.Name)); } internal virtual void ResetIdentity() @@ -128,7 +120,7 @@ namespace Umbraco.Tests.Models.Collections /// Tracks the properties that have changed /// //private readonly IDictionary _propertyChangedInfo = new Dictionary(); - private IDictionary _propertyChangedInfo; + private readonly IDictionary _propertyChangedInfo; /// /// Indicates whether a specific property on the current entity is dirty. @@ -166,19 +158,29 @@ namespace Umbraco.Tests.Models.Collections _propertyChangedInfo.Clear(); } + /// + /// Disables change tracking. + /// + public void DisableChangeTracking() + { + _withChanges = false; + } + + /// + /// Enables change tracking. + /// + public void EnableChangeTracking() + { + _withChanges = true; + } + /// /// Indicates whether the current entity has an identity, eg. Id. /// public virtual bool HasIdentity { - get - { - return _hasIdentity; - } - protected set - { - _hasIdentity = value; - } + get => _hasIdentity; + protected set => _hasIdentity = value; } public static bool operator ==(Item left, Item right) diff --git a/src/Umbraco.Tests/Models/ContentExtensionsTests.cs b/src/Umbraco.Tests/Models/ContentExtensionsTests.cs index 42d7f0e01b..52cf5ddef5 100644 --- a/src/Umbraco.Tests/Models/ContentExtensionsTests.cs +++ b/src/Umbraco.Tests/Models/ContentExtensionsTests.cs @@ -32,7 +32,7 @@ namespace Umbraco.Tests.Models Composition.Register(_ => Mock.Of()); // all this is required so we can validate properties... - var editor = new TextboxPropertyEditor(Mock.Of()) { Alias = "test" }; + var editor = new TextboxPropertyEditor(Mock.Of(), Mock.Of(), Mock.Of()) { Alias = "test" }; Composition.Register(_ => new DataEditorCollection(new[] { editor })); Composition.Register(); var dataType = Mock.Of(); diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index ffbf462b8e..ee6649dd2b 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -43,7 +43,7 @@ namespace Umbraco.Tests.Models Composition.Register(_ => Mock.Of()); // all this is required so we can validate properties... - var editor = new TextboxPropertyEditor(Mock.Of()) { Alias = "test" }; + var editor = new TextboxPropertyEditor(Mock.Of(), Mock.Of(), Mock.Of()) { Alias = "test" }; Composition.Register(_ => new DataEditorCollection(new [] { editor })); Composition.Register(); var dataType = Mock.Of(); @@ -57,7 +57,7 @@ namespace Umbraco.Tests.Models var mediaTypeService = Mock.Of(); var memberTypeService = Mock.Of(); Composition.Register(_ => ServiceContext.CreatePartial(dataTypeService: dataTypeService, contentTypeBaseServiceProvider: new ContentTypeBaseServiceProvider(_contentTypeService, mediaTypeService, memberTypeService))); - + } [Test] diff --git a/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs b/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs index 21180ce51b..968e51ab97 100644 --- a/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs @@ -24,6 +24,7 @@ namespace Umbraco.Tests.Models.Mapping private readonly Mock _dataTypeService = new Mock(); private readonly Mock _entityService = new Mock(); private readonly Mock _fileService = new Mock(); + private readonly Mock _localizationService = new Mock(); private Mock _editorsMock; protected override void Compose() @@ -31,7 +32,7 @@ namespace Umbraco.Tests.Models.Mapping base.Compose(); // create and register a fake property editor collection to return fake property editors - var editors = new DataEditor[] { new TextboxPropertyEditor(Mock.Of()), }; + var editors = new DataEditor[] { new TextboxPropertyEditor(Mock.Of(), _dataTypeService.Object, _localizationService.Object), }; var dataEditors = new DataEditorCollection(editors); _editorsMock = new Mock(dataEditors); _editorsMock.Setup(x => x[It.IsAny()]).Returns(editors[0]); diff --git a/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs b/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs index 6a4054d5ae..9a47ad1b4a 100644 --- a/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs @@ -40,7 +40,7 @@ namespace Umbraco.Tests.Models.Mapping Composition.Register(_ => Mock.Of()); // all this is required so we can validate properties... - var editor = new TextboxPropertyEditor(Mock.Of()) { Alias = "test" }; + var editor = new TextboxPropertyEditor(Mock.Of(), Mock.Of(), Mock.Of()) { Alias = "test" }; Composition.Register(_ => new DataEditorCollection(new[] { editor })); Composition.Register(); var dataType = Mock.Of(); @@ -261,7 +261,7 @@ namespace Umbraco.Tests.Models.Mapping #region Assertions - private void AssertDisplayProperty(IContentProperties result, Property p) + private void AssertDisplayProperty(IContentProperties result, IProperty p) where T : ContentPropertyBasic { var pDto = result.Properties.SingleOrDefault(x => x.Alias == p.Alias); @@ -325,7 +325,7 @@ namespace Umbraco.Tests.Models.Mapping Assert.AreEqual(content.Properties.Count(), result.Properties.Count(x => x.Alias.StartsWith("_umb_") == false)); } - private void AssertBasicProperty(IContentProperties result, Property p) + private void AssertBasicProperty(IContentProperties result, IProperty p) where T : ContentPropertyBasic { var pDto = result.Properties.SingleOrDefault(x => x.Alias == p.Alias); @@ -341,7 +341,7 @@ namespace Umbraco.Tests.Models.Mapping Assert.AreEqual(pDto.Value, p.GetValue().ToString()); } - private void AssertProperty(IContentProperties result, Property p) + private void AssertProperty(IContentProperties result, IProperty p) { AssertBasicProperty(result, p); diff --git a/src/Umbraco.Tests/Models/MediaXmlTest.cs b/src/Umbraco.Tests/Models/MediaXmlTest.cs index 3ae9414dc1..4b4b333e74 100644 --- a/src/Umbraco.Tests/Models/MediaXmlTest.cs +++ b/src/Umbraco.Tests/Models/MediaXmlTest.cs @@ -33,9 +33,11 @@ namespace Umbraco.Tests.Models var logger = Mock.Of(); var scheme = Mock.Of(); var config = Mock.Of(); + var dataTypeService = Mock.Of(); + var localizationService = Mock.Of(); var mediaFileSystem = new MediaFileSystem(Mock.Of(), config, scheme, logger); - var ignored = new FileUploadPropertyEditor(Mock.Of(), mediaFileSystem, config); + var ignored = new FileUploadPropertyEditor(Mock.Of(), mediaFileSystem, config, dataTypeService, localizationService); var media = MockedMedia.CreateMediaImage(mediaType, -1); media.WriterId = -1; // else it's zero and that's not a user and it breaks the tests 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/Models/VariationTests.cs b/src/Umbraco.Tests/Models/VariationTests.cs index ab5f726894..c7ebb9ef71 100644 --- a/src/Umbraco.Tests/Models/VariationTests.cs +++ b/src/Umbraco.Tests/Models/VariationTests.cs @@ -8,6 +8,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; +using Umbraco.Core.Services.Implement; using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests.Models @@ -35,9 +36,12 @@ namespace Umbraco.Tests.Models var factory = Mock.Of(); Current.Factory = factory; + var dataTypeService = Mock.Of(); + var localizationService = Mock.Of(); + var dataEditors = new DataEditorCollection(new IDataEditor[] { - new DataEditor(Mock.Of()) { Alias = "editor", ExplicitValueEditor = new DataValueEditor("view") } + new DataEditor(Mock.Of()) { Alias = "editor", ExplicitValueEditor = TestHelper.CreateDataValueEditor("view") } }); var propertyEditors = new PropertyEditorCollection(dataEditors); @@ -46,7 +50,6 @@ namespace Umbraco.Tests.Models .Setup(x => x.Configuration) .Returns(null); - var dataTypeService = Mock.Of(); Mock.Get(dataTypeService) .Setup(x => x.GetDataType(It.IsAny())) .Returns(x => dataType); @@ -75,7 +78,7 @@ namespace Umbraco.Tests.Models // 1. if exact is set to true: culture cannot be null when the ContentVariation.Culture flag is set // 2. if wildcards is set to false: fail when "*" is passed in as either culture or segment. // 3. ContentVariation flag is ignored when wildcards are used. - // 4. Empty string is considered the same as null + // 4. Empty string is considered the same as null #region Nothing @@ -141,7 +144,7 @@ namespace Umbraco.Tests.Models #endregion #region CultureAndSegment - + Assert4B(ContentVariation.CultureAndSegment, null, null, false, true, false, true); Assert4B(ContentVariation.CultureAndSegment, null, "", false, true, false, true); Assert4B(ContentVariation.CultureAndSegment, null, "*", false, false, false, true); @@ -163,7 +166,7 @@ namespace Umbraco.Tests.Models } /// - /// Asserts the result of + /// Asserts the result of /// /// /// diff --git a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs index 5bea491973..885aaeefb9 100644 --- a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs +++ b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs @@ -83,7 +83,7 @@ namespace Umbraco.Tests.PropertyEditors var mediaFileSystem = new MediaFileSystem(Mock.Of(), config, scheme, logger); var dataTypeService = new TestObjects.TestDataTypeService( - new DataType(new ImageCropperPropertyEditor(Mock.Of(), mediaFileSystem, Mock.Of(), Mock.Of())) { Id = 1 }); + new DataType(new ImageCropperPropertyEditor(Mock.Of(), mediaFileSystem, Mock.Of(), Mock.Of(), Mock.Of())) { Id = 1 }); var factory = new PublishedContentTypeFactory(Mock.Of(), new PropertyValueConverterCollection(Array.Empty()), dataTypeService); diff --git a/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs b/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs index b7037eb192..5579395b7e 100644 --- a/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs +++ b/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs @@ -25,12 +25,12 @@ namespace Umbraco.Tests.PropertyEditors /// to cache. Now we always just deal with strings and we'll keep the tests that show that. /// [TestFixture] - public class MultiValuePropertyEditorTests + public class MultiValuePropertyEditorTests { [Test] public void DropDownMultipleValueEditor_Format_Data_For_Cache() { - var dataType = new DataType(new CheckBoxListPropertyEditor(Mock.Of(), Mock.Of())) + var dataType = new DataType(new CheckBoxListPropertyEditor(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of())) { Configuration = new ValueListConfiguration { @@ -51,7 +51,7 @@ namespace Umbraco.Tests.PropertyEditors var valueEditor = dataType.Editor.GetValueEditor(); ((DataValueEditor) valueEditor).Configuration = dataType.Configuration; - var result = valueEditor.ConvertDbToString(prop.PropertyType, prop.GetValue(), dataTypeService); + var result = valueEditor.ConvertDbToString(prop.PropertyType, prop.GetValue()); Assert.AreEqual("Value 1,Value 2,Value 3", result); } @@ -59,7 +59,7 @@ namespace Umbraco.Tests.PropertyEditors [Test] public void DropDownValueEditor_Format_Data_For_Cache() { - var dataType = new DataType(new CheckBoxListPropertyEditor(Mock.Of(), Mock.Of())) + var dataType = new DataType(new CheckBoxListPropertyEditor(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of())) { Configuration = new ValueListConfiguration { @@ -78,7 +78,7 @@ namespace Umbraco.Tests.PropertyEditors var prop = new Property(1, new PropertyType(dataType)); prop.SetValue("Value 2"); - var result = dataType.Editor.GetValueEditor().ConvertDbToString(prop.PropertyType, prop.GetValue(), dataTypeService); + var result = dataType.Editor.GetValueEditor().ConvertDbToString(prop.PropertyType, prop.GetValue()); Assert.AreEqual("Value 2", result); } diff --git a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs index eda6d4f5bb..bb1b0e4b10 100644 --- a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs +++ b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs @@ -47,12 +47,9 @@ namespace Umbraco.Tests.PropertyEditors var prop = new Property(1, new PropertyType("test", ValueStorageType.Nvarchar)); prop.SetValue(value); - var valueEditor = new DataValueEditor - { - ValueType = ValueTypes.String - }; + var valueEditor = TestHelper.CreateDataValueEditor(ValueTypes.String); - var result = valueEditor.ToEditor(prop, new Mock().Object); + var result = valueEditor.ToEditor(prop); Assert.AreEqual(isOk, !(result is string)); } @@ -63,10 +60,7 @@ namespace Umbraco.Tests.PropertyEditors [TestCase("DATETIME", "", null)] //test empty string for date public void Value_Editor_Can_Convert_To_Clr_Type(string valueType, string val, object expected) { - var valueEditor = new DataValueEditor - { - ValueType = valueType - }; + var valueEditor = TestHelper.CreateDataValueEditor(valueType); var result = valueEditor.TryConvertValueToCrlType(val); Assert.IsTrue(result.Success); @@ -78,10 +72,7 @@ namespace Umbraco.Tests.PropertyEditors [Test] public void Value_Editor_Can_Convert_To_Decimal_Clr_Type() { - var valueEditor = new DataValueEditor - { - ValueType = ValueTypes.Decimal - }; + var valueEditor = TestHelper.CreateDataValueEditor(ValueTypes.Decimal); var result = valueEditor.TryConvertValueToCrlType("12.34"); Assert.IsTrue(result.Success); @@ -91,10 +82,7 @@ namespace Umbraco.Tests.PropertyEditors [Test] public void Value_Editor_Can_Convert_To_Decimal_Clr_Type_With_Other_Separator() { - var valueEditor = new DataValueEditor - { - ValueType = ValueTypes.Decimal - }; + var valueEditor = TestHelper.CreateDataValueEditor(ValueTypes.Decimal); var result = valueEditor.TryConvertValueToCrlType("12,34"); Assert.IsTrue(result.Success); @@ -104,10 +92,7 @@ namespace Umbraco.Tests.PropertyEditors [Test] public void Value_Editor_Can_Convert_To_Decimal_Clr_Type_With_Empty_String() { - var valueEditor = new DataValueEditor - { - ValueType = ValueTypes.Decimal - }; + var valueEditor = TestHelper.CreateDataValueEditor(ValueTypes.Decimal); var result = valueEditor.TryConvertValueToCrlType(string.Empty); Assert.IsTrue(result.Success); @@ -117,10 +102,7 @@ namespace Umbraco.Tests.PropertyEditors [Test] public void Value_Editor_Can_Convert_To_Date_Clr_Type() { - var valueEditor = new DataValueEditor - { - ValueType = ValueTypes.Date - }; + var valueEditor = TestHelper.CreateDataValueEditor(ValueTypes.Date); var result = valueEditor.TryConvertValueToCrlType("2010-02-05"); Assert.IsTrue(result.Success); @@ -137,12 +119,9 @@ namespace Umbraco.Tests.PropertyEditors var prop = new Property(1, new PropertyType("test", ValueStorageType.Nvarchar)); prop.SetValue(val); - var valueEditor = new DataValueEditor - { - ValueType = valueType - }; + var valueEditor = TestHelper.CreateDataValueEditor(valueType); - var result = valueEditor.ToEditor(prop, new Mock().Object); + var result = valueEditor.ToEditor(prop); Assert.AreEqual(expected, result); } @@ -150,30 +129,24 @@ namespace Umbraco.Tests.PropertyEditors public void Value_Editor_Can_Serialize_Decimal_Value() { var value = 12.34M; - var valueEditor = new DataValueEditor - { - ValueType = ValueTypes.Decimal - }; + var valueEditor = TestHelper.CreateDataValueEditor(ValueTypes.Decimal); var prop = new Property(1, new PropertyType("test", ValueStorageType.Decimal)); prop.SetValue(value); - var result = valueEditor.ToEditor(prop, new Mock().Object); + var result = valueEditor.ToEditor(prop); Assert.AreEqual("12.34", result); } [Test] public void Value_Editor_Can_Serialize_Decimal_Value_With_Empty_String() { - var valueEditor = new DataValueEditor - { - ValueType = ValueTypes.Decimal - }; + var valueEditor = TestHelper.CreateDataValueEditor(ValueTypes.Decimal); var prop = new Property(1, new PropertyType("test", ValueStorageType.Decimal)); prop.SetValue(string.Empty); - var result = valueEditor.ToEditor(prop, new Mock().Object); + var result = valueEditor.ToEditor(prop); Assert.AreEqual(string.Empty, result); } @@ -181,15 +154,12 @@ namespace Umbraco.Tests.PropertyEditors public void Value_Editor_Can_Serialize_Date_Value() { var now = DateTime.Now; - var valueEditor = new DataValueEditor - { - ValueType = ValueTypes.Date - }; + var valueEditor = TestHelper.CreateDataValueEditor(ValueTypes.Date); var prop = new Property(1, new PropertyType("test", ValueStorageType.Date)); prop.SetValue(now); - var result = valueEditor.ToEditor(prop, new Mock().Object); + var result = valueEditor.ToEditor(prop); Assert.AreEqual(now.ToIsoString(), result); } } diff --git a/src/Umbraco.Tests/Published/NestedContentTests.cs b/src/Umbraco.Tests/Published/NestedContentTests.cs index 9385b8955a..4d99aa86d8 100644 --- a/src/Umbraco.Tests/Published/NestedContentTests.cs +++ b/src/Umbraco.Tests/Published/NestedContentTests.cs @@ -11,6 +11,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; using Umbraco.Tests.PublishedContent; using Umbraco.Tests.TestHelpers; using Umbraco.Web; @@ -31,9 +32,10 @@ namespace Umbraco.Tests.Published var logger = Mock.Of(); var profiler = Mock.Of(); var proflog = new ProfilingLogger(logger, profiler); + var localizationService = Mock.Of(); PropertyEditorCollection editors = null; - var editor = new NestedContentPropertyEditor(logger, new Lazy(() => editors)); + var editor = new NestedContentPropertyEditor(logger, new Lazy(() => editors), Mock.Of(), localizationService); editors = new PropertyEditorCollection(new DataEditorCollection(new DataEditor[] { editor })); var dataType1 = new DataType(editor) @@ -64,7 +66,7 @@ namespace Umbraco.Tests.Published } }; - var dataType3 = new DataType(new TextboxPropertyEditor(logger)) + var dataType3 = new DataType(new TextboxPropertyEditor(logger, Mock.Of(), localizationService)) { Id = 3 }; diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs index f1e2bf20d6..bf55f1783f 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs @@ -40,7 +40,13 @@ namespace Umbraco.Tests.PublishedContent var converters = Factory.GetInstance(); var dataTypeService = new TestObjects.TestDataTypeService( - new DataType(new RichTextPropertyEditor(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of())) { Id = 1 }); + new DataType(new RichTextPropertyEditor( + Mock.Of(), + Mock.Of(), + Mock.Of(), + Mock.Of(), + Mock.Of(), + Mock.Of())) { Id = 1 }); var publishedContentTypeFactory = new PublishedContentTypeFactory(Mock.Of(), converters, dataTypeService); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index b42dc32b24..7c70e82047 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -47,13 +47,14 @@ namespace Umbraco.Tests.PublishedContent var mediaService = Mock.Of(); var contentTypeBaseServiceProvider = Mock.Of(); var umbracoContextAccessor = Mock.Of(); + var localizationService = Mock.Of(); var dataTypeService = new TestObjects.TestDataTypeService( new DataType(new VoidEditor(logger)) { Id = 1 }, new DataType(new TrueFalsePropertyEditor(logger)) { Id = 1001 }, - new DataType(new RichTextPropertyEditor(logger, mediaService, contentTypeBaseServiceProvider, umbracoContextAccessor)) { Id = 1002 }, + new DataType(new RichTextPropertyEditor(logger, mediaService, contentTypeBaseServiceProvider, umbracoContextAccessor, Mock.Of(), localizationService)) { Id = 1002 }, new DataType(new IntegerPropertyEditor(logger)) { Id = 1003 }, - new DataType(new TextboxPropertyEditor(logger)) { Id = 1004 }, + new DataType(new TextboxPropertyEditor(logger, Mock.Of(), localizationService)) { Id = 1004 }, new DataType(new MediaPickerPropertyEditor(logger)) { Id = 1005 }); Composition.RegisterUnique(f => dataTypeService); } diff --git a/src/Umbraco.Tests/Services/PropertyValidationServiceTests.cs b/src/Umbraco.Tests/Services/PropertyValidationServiceTests.cs index 425c03a9b4..746190d67f 100644 --- a/src/Umbraco.Tests/Services/PropertyValidationServiceTests.cs +++ b/src/Umbraco.Tests/Services/PropertyValidationServiceTests.cs @@ -32,7 +32,7 @@ namespace Umbraco.Tests.Services x => x.Type == EditorType.PropertyValue && x.Alias == Constants.PropertyEditors.Aliases.TextBox); Mock.Get(dataEditor).Setup(x => x.GetValueEditor(It.IsAny())) - .Returns(new CustomTextOnlyValueEditor(new DataEditorAttribute(Constants.PropertyEditors.Aliases.TextBox, "Test Textbox", "textbox"), textService.Object)); + .Returns(new CustomTextOnlyValueEditor(Mock.Of(), Mock.Of(), new DataEditorAttribute(Constants.PropertyEditors.Aliases.TextBox, "Test Textbox", "textbox"), textService.Object)); var propEditors = new PropertyEditorCollection(new DataEditorCollection(new[] { dataEditor })); @@ -164,7 +164,7 @@ namespace Umbraco.Tests.Services { private readonly ILocalizedTextService _textService; - public CustomTextOnlyValueEditor(DataEditorAttribute attribute, ILocalizedTextService textService) : base(attribute) + public CustomTextOnlyValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, DataEditorAttribute attribute, ILocalizedTextService textService) : base(dataTypeService, localizationService, attribute) { _textService = textService; } diff --git a/src/Umbraco.Tests/TestHelpers/TestHelper.cs b/src/Umbraco.Tests/TestHelpers/TestHelper.cs index 838d3686ab..975cf72bfb 100644 --- a/src/Umbraco.Tests/TestHelpers/TestHelper.cs +++ b/src/Umbraco.Tests/TestHelpers/TestHelper.cs @@ -18,6 +18,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; using File = System.IO.File; namespace Umbraco.Tests.TestHelpers @@ -248,5 +249,20 @@ namespace Umbraco.Tests.TestHelpers } } } + + public static DataValueEditor CreateDataValueEditor(string name) + { + var valueType = (ValueTypes.IsValue(name)) ? name : ValueTypes.String; + + return new DataValueEditor( + Mock.Of(), + Mock.Of(), + new DataEditorAttribute(name, name, name) + { + ValueType = valueType + } + + ); + } } } 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/ContentApps/ContentAppFactoryCollectionBuilder.cs b/src/Umbraco.Web/ContentApps/ContentAppFactoryCollectionBuilder.cs index 170b9169ef..4e86b407b5 100644 --- a/src/Umbraco.Web/ContentApps/ContentAppFactoryCollectionBuilder.cs +++ b/src/Umbraco.Web/ContentApps/ContentAppFactoryCollectionBuilder.cs @@ -2,6 +2,7 @@ using System.Linq; using Umbraco.Core; using Umbraco.Core.Composing; +using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Manifest; using Umbraco.Core.Models.ContentEditing; @@ -28,7 +29,7 @@ namespace Umbraco.Web.ContentApps // its dependencies too, and that can create cycles or other oddities var manifestParser = factory.GetInstance(); - return base.CreateItems(factory).Concat(manifestParser.Manifest.ContentApps.Select(x => new ManifestContentAppFactory(x))); + return base.CreateItems(factory).Concat(manifestParser.Manifest.ContentApps.Select(x => new ManifestContentAppFactory(x, Current.IOHelper))); } } } diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index 5c8e6fc2b5..11cc59a464 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -1837,7 +1837,7 @@ namespace Umbraco.Web.Editors private void MapValuesForPersistence(ContentItemSave contentSave) { // inline method to determine if a property type varies - bool Varies(Property property) => property.PropertyType.VariesByCulture(); + bool Varies(IProperty property) => property.PropertyType.VariesByCulture(); var variantIndex = 0; diff --git a/src/Umbraco.Web/Editors/ContentControllerBase.cs b/src/Umbraco.Web/Editors/ContentControllerBase.cs index 300c777b3a..83167eb9ae 100644 --- a/src/Umbraco.Web/Editors/ContentControllerBase.cs +++ b/src/Umbraco.Web/Editors/ContentControllerBase.cs @@ -50,8 +50,8 @@ namespace Umbraco.Web.Editors internal void MapPropertyValuesForPersistence( TSaved contentItem, ContentPropertyCollectionDto dto, - Func getPropertyValue, - Action savePropertyValue, + Func getPropertyValue, + Action savePropertyValue, string culture) where TPersisted : IContentBase where TSaved : IContentSave diff --git a/src/Umbraco.Web/Editors/Filters/ContentModelValidator.cs b/src/Umbraco.Web/Editors/Filters/ContentModelValidator.cs index 4acf0c948e..14531227e1 100644 --- a/src/Umbraco.Web/Editors/Filters/ContentModelValidator.cs +++ b/src/Umbraco.Web/Editors/Filters/ContentModelValidator.cs @@ -46,7 +46,7 @@ namespace Umbraco.Web.Editors.Filters protected ContentModelValidator(ILogger logger, IUmbracoContextAccessor umbracoContextAccessor) : base(logger, umbracoContextAccessor) { } - + /// /// Ensure the content exists /// @@ -85,7 +85,7 @@ namespace Umbraco.Web.Editors.Filters /// /// /// - protected bool ValidateProperties(List postedProperties, List persistedProperties, HttpActionContext actionContext) + protected bool ValidateProperties(List postedProperties, List persistedProperties, HttpActionContext actionContext) { foreach (var p in postedProperties) { @@ -142,7 +142,7 @@ namespace Umbraco.Web.Editors.Filters var postedValue = postedProp.Value; ValidatePropertyValue(model, modelWithProperties, editor, p, postedValue, modelState); - + } return modelState.IsValid; diff --git a/src/Umbraco.Web/Macros/PublishedContentHashtableConverter.cs b/src/Umbraco.Web/Macros/PublishedContentHashtableConverter.cs index 41f0e2fb65..cab20926ff 100644 --- a/src/Umbraco.Web/Macros/PublishedContentHashtableConverter.cs +++ b/src/Umbraco.Web/Macros/PublishedContentHashtableConverter.cs @@ -147,7 +147,7 @@ namespace Umbraco.Web.Macros _content = content; } - public PagePublishedProperty(IPublishedPropertyType propertyType, IPublishedContent content, Umbraco.Core.Models.Property property) + public PagePublishedProperty(IPublishedPropertyType propertyType, IPublishedContent content, IProperty property) : base(propertyType, PropertyCacheLevel.Unknown) // cache level is ignored { _sourceValue = property.GetValue(); diff --git a/src/Umbraco.Web/Models/Mapping/ContentMapDefinition.cs b/src/Umbraco.Web/Models/Mapping/ContentMapDefinition.cs index dc0df4ca96..d3b4353f2f 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentMapDefinition.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentMapDefinition.cs @@ -64,7 +64,7 @@ namespace Umbraco.Web.Models.Mapping // Umbraco.Code.MapAll private static void Map(IContent source, ContentPropertyCollectionDto target, MapperContext context) { - target.Properties = context.MapEnumerable(source.Properties); + target.Properties = context.MapEnumerable(source.Properties); } // Umbraco.Code.MapAll -AllowPreview -Errors -PersistedContent @@ -99,7 +99,7 @@ namespace Umbraco.Web.Models.Mapping target.Variants = _contentVariantMapper.Map(source, context); target.ContentDto = new ContentPropertyCollectionDto(); - target.ContentDto.Properties = context.MapEnumerable(source.Properties); + target.ContentDto.Properties = context.MapEnumerable(source.Properties); } // Umbraco.Code.MapAll -Segment -Language @@ -129,7 +129,7 @@ namespace Umbraco.Web.Models.Mapping target.Owner = _commonMapper.GetOwner(source, context); target.ParentId = source.ParentId; target.Path = source.Path; - target.Properties = context.MapEnumerable(source.Properties); + target.Properties = context.MapEnumerable(source.Properties); target.SortOrder = source.SortOrder; target.State = _basicStateMapper.Map(source, context); target.Trashed = source.Trashed; diff --git a/src/Umbraco.Web/Models/Mapping/ContentPropertyBasicMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentPropertyBasicMapper.cs index 36c1b360b2..cddcfc6d1c 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentPropertyBasicMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentPropertyBasicMapper.cs @@ -33,7 +33,7 @@ namespace Umbraco.Web.Models.Mapping /// Assigns the PropertyEditor, Id, Alias and Value to the property /// /// - public virtual void Map(Property property, TDestination dest, MapperContext context) + public virtual void Map(IProperty property, TDestination dest, MapperContext context) { var editor = _propertyEditors[property.PropertyType.PropertyEditorAlias]; if (editor == null) @@ -71,7 +71,7 @@ namespace Umbraco.Web.Models.Mapping dest.Culture = culture; // if no 'IncludeProperties' were specified or this property is set to be included - we will map the value and return. - dest.Value = editor.GetValueEditor().ToEditor(property, DataTypeService, culture); + dest.Value = editor.GetValueEditor().ToEditor(property, culture); } } } diff --git a/src/Umbraco.Web/Models/Mapping/ContentPropertyDisplayMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentPropertyDisplayMapper.cs index f68c5d8b44..12278e97ea 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentPropertyDisplayMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentPropertyDisplayMapper.cs @@ -19,7 +19,7 @@ namespace Umbraco.Web.Models.Mapping { _textService = textService; } - public override void Map(Property originalProp, ContentPropertyDisplay dest, MapperContext context) + public override void Map(IProperty originalProp, ContentPropertyDisplay dest, MapperContext context) { base.Map(originalProp, dest, context); diff --git a/src/Umbraco.Web/Models/Mapping/ContentPropertyDtoMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentPropertyDtoMapper.cs index 72107c6201..f481ad445c 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentPropertyDtoMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentPropertyDtoMapper.cs @@ -16,7 +16,7 @@ namespace Umbraco.Web.Models.Mapping : base(dataTypeService, entityService, logger, propertyEditors) { } - public override void Map(Property property, ContentPropertyDto dest, MapperContext context) + public override void Map(IProperty property, ContentPropertyDto dest, MapperContext context) { base.Map(property, dest, context); diff --git a/src/Umbraco.Web/Models/Mapping/ContentPropertyMapDefinition.cs b/src/Umbraco.Web/Models/Mapping/ContentPropertyMapDefinition.cs index e6290cc19e..5d659fbf9e 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentPropertyMapDefinition.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentPropertyMapDefinition.cs @@ -27,9 +27,9 @@ namespace Umbraco.Web.Models.Mapping public void DefineMaps(UmbracoMapper mapper) { mapper.Define>((source, context) => new Tab(), Map); - mapper.Define((source, context) => new ContentPropertyBasic(), Map); - mapper.Define((source, context) => new ContentPropertyDto(), Map); - mapper.Define((source, context) => new ContentPropertyDisplay(), Map); + mapper.Define((source, context) => new ContentPropertyBasic(), Map); + mapper.Define((source, context) => new ContentPropertyDto(), Map); + mapper.Define((source, context) => new ContentPropertyDisplay(), Map); } // Umbraco.Code.MapAll -Properties -Alias -Expanded @@ -40,19 +40,19 @@ namespace Umbraco.Web.Models.Mapping target.Label = source.Name; } - private void Map(Property source, ContentPropertyBasic target, MapperContext context) + private void Map(IProperty source, ContentPropertyBasic target, MapperContext context) { // assume this is mapping everything and no MapAll is required _contentPropertyBasicConverter.Map(source, target, context); } - private void Map(Property source, ContentPropertyDto target, MapperContext context) + private void Map(IProperty source, ContentPropertyDto target, MapperContext context) { // assume this is mapping everything and no MapAll is required _contentPropertyDtoConverter.Map(source, target, context); } - private void Map(Property source, ContentPropertyDisplay target, MapperContext context) + private void Map(IProperty source, ContentPropertyDisplay target, MapperContext context) { // assume this is mapping everything and no MapAll is required _contentPropertyDisplayMapper.Map(source, target, context); diff --git a/src/Umbraco.Web/Models/Mapping/MediaMapDefinition.cs b/src/Umbraco.Web/Models/Mapping/MediaMapDefinition.cs index 05c006ec41..80bdc7ade4 100644 --- a/src/Umbraco.Web/Models/Mapping/MediaMapDefinition.cs +++ b/src/Umbraco.Web/Models/Mapping/MediaMapDefinition.cs @@ -42,7 +42,7 @@ namespace Umbraco.Web.Models.Mapping // Umbraco.Code.MapAll private static void Map(IMedia source, ContentPropertyCollectionDto target, MapperContext context) { - target.Properties = context.MapEnumerable(source.Properties); + target.Properties = context.MapEnumerable(source.Properties); } // Umbraco.Code.MapAll -Properties -Errors -Edited -Updater -Alias -IsContainer @@ -86,7 +86,7 @@ namespace Umbraco.Web.Models.Mapping target.Owner = _commonMapper.GetOwner(source, context); target.ParentId = source.ParentId; target.Path = source.Path; - target.Properties = context.MapEnumerable(source.Properties); + target.Properties = context.MapEnumerable(source.Properties); target.SortOrder = source.SortOrder; target.State = null; target.Trashed = source.Trashed; diff --git a/src/Umbraco.Web/Models/Mapping/MemberMapDefinition.cs b/src/Umbraco.Web/Models/Mapping/MemberMapDefinition.cs index 8671bfe538..fd295803c1 100644 --- a/src/Umbraco.Web/Models/Mapping/MemberMapDefinition.cs +++ b/src/Umbraco.Web/Models/Mapping/MemberMapDefinition.cs @@ -113,7 +113,7 @@ namespace Umbraco.Web.Models.Mapping target.Owner = _commonMapper.GetOwner(source, context); target.ParentId = source.ParentId; target.Path = source.Path; - target.Properties = context.MapEnumerable(source.Properties); + target.Properties = context.MapEnumerable(source.Properties); target.SortOrder = source.SortOrder; target.State = null; target.Udi = Udi.Create(Constants.UdiEntityType.Member, source.Key); @@ -151,7 +151,7 @@ namespace Umbraco.Web.Models.Mapping // Umbraco.Code.MapAll private static void Map(IMember source, ContentPropertyCollectionDto target, MapperContext context) { - target.Properties = context.MapEnumerable(source.Properties); + target.Properties = context.MapEnumerable(source.Properties); } private MembershipScenario GetMembershipScenario() diff --git a/src/Umbraco.Web/Models/Mapping/MemberTabsAndPropertiesMapper.cs b/src/Umbraco.Web/Models/Mapping/MemberTabsAndPropertiesMapper.cs index 8744b068a7..81d75de498 100644 --- a/src/Umbraco.Web/Models/Mapping/MemberTabsAndPropertiesMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/MemberTabsAndPropertiesMapper.cs @@ -176,7 +176,7 @@ namespace Umbraco.Web.Models.Mapping /// /// /// - protected override List MapProperties(IContentBase content, List properties, MapperContext context) + protected override List MapProperties(IContentBase content, List properties, MapperContext context) { var result = base.MapProperties(content, properties, context); var member = (IMember)content; diff --git a/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesMapper.cs b/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesMapper.cs index b8d76572fb..70a001735a 100644 --- a/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesMapper.cs @@ -103,9 +103,9 @@ namespace Umbraco.Web.Models.Mapping /// /// /// - protected virtual List MapProperties(IContentBase content, List properties, MapperContext context) + protected virtual List MapProperties(IContentBase content, List properties, MapperContext context) { - return context.MapEnumerable(properties.OrderBy(x => x.PropertyType.SortOrder)); + return context.MapEnumerable(properties.OrderBy(x => x.PropertyType.SortOrder)); } } @@ -132,7 +132,7 @@ namespace Umbraco.Web.Models.Mapping var groupsGroupsByName = contentType.CompositionPropertyGroups.OrderBy(x => x.SortOrder).GroupBy(x => x.Name); foreach (var groupsByName in groupsGroupsByName) { - var properties = new List(); + var properties = new List(); // merge properties for groups with the same name foreach (var group in groupsByName) diff --git a/src/Umbraco.Web/PropertyEditors/CheckBoxListPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/CheckBoxListPropertyEditor.cs index d81b63f2ad..f28acd5e90 100644 --- a/src/Umbraco.Web/PropertyEditors/CheckBoxListPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/CheckBoxListPropertyEditor.cs @@ -17,20 +17,24 @@ namespace Umbraco.Web.PropertyEditors public class CheckBoxListPropertyEditor : DataEditor { private readonly ILocalizedTextService _textService; + private readonly IDataTypeService _dataTypeService; + private readonly ILocalizationService _localizationService; /// /// The constructor will setup the property editor based on the attribute if one is found /// - public CheckBoxListPropertyEditor(ILogger logger, ILocalizedTextService textService) + public CheckBoxListPropertyEditor(ILogger logger, ILocalizedTextService textService, IDataTypeService dataTypeService, ILocalizationService localizationService) : base(logger) { _textService = textService; + _dataTypeService = dataTypeService; + _localizationService = localizationService; } /// protected override IConfigurationEditor CreateConfigurationEditor() => new ValueListConfigurationEditor(_textService); /// - protected override IDataValueEditor CreateValueEditor() => new MultipleValueEditor(Logger, Attribute); + protected override IDataValueEditor CreateValueEditor() => new MultipleValueEditor(Logger, _dataTypeService, _localizationService, Attribute); } } diff --git a/src/Umbraco.Web/PropertyEditors/DateValueEditor.cs b/src/Umbraco.Web/PropertyEditors/DateValueEditor.cs index a03ad4aa00..b8dada173f 100644 --- a/src/Umbraco.Web/PropertyEditors/DateValueEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/DateValueEditor.cs @@ -12,13 +12,13 @@ namespace Umbraco.Web.PropertyEditors /// internal class DateValueEditor : DataValueEditor { - public DateValueEditor(DataEditorAttribute attribute) - : base(attribute) + public DateValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, DataEditorAttribute attribute) + : base(dataTypeService, localizationService, attribute) { Validators.Add(new DateTimeValidator()); } - public override object ToEditor(Property property, IDataTypeService dataTypeService, string culture= null, string segment = null) + public override object ToEditor(IProperty property, 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/DropDownFlexiblePropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/DropDownFlexiblePropertyEditor.cs index 98a19f39ad..0b0a0f6d06 100644 --- a/src/Umbraco.Web/PropertyEditors/DropDownFlexiblePropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/DropDownFlexiblePropertyEditor.cs @@ -14,16 +14,20 @@ namespace Umbraco.Web.PropertyEditors public class DropDownFlexiblePropertyEditor : DataEditor { private readonly ILocalizedTextService _textService; + private readonly IDataTypeService _dataTypeService; + private readonly ILocalizationService _localizationService; - public DropDownFlexiblePropertyEditor(ILocalizedTextService textService, ILogger logger) + public DropDownFlexiblePropertyEditor(ILocalizedTextService textService, ILogger logger, IDataTypeService dataTypeService, ILocalizationService localizationService) : base(logger) { _textService = textService; + _dataTypeService = dataTypeService; + _localizationService = localizationService; } protected override IDataValueEditor CreateValueEditor() { - return new MultipleValueEditor(Logger, Attribute); + return new MultipleValueEditor(Logger, _dataTypeService, _localizationService, Attribute); } protected override IConfigurationEditor CreateConfigurationEditor() => new DropDownFlexibleConfigurationEditor(_textService); diff --git a/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs index a3396a5fb3..366f3938a6 100644 --- a/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs @@ -8,6 +8,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; +using Umbraco.Core.Services.Implement; using Umbraco.Web.Media; namespace Umbraco.Web.PropertyEditors @@ -23,12 +24,16 @@ namespace Umbraco.Web.PropertyEditors private readonly IMediaFileSystem _mediaFileSystem; private readonly IContentSection _contentSection; private readonly UploadAutoFillProperties _uploadAutoFillProperties; + private readonly IDataTypeService _dataTypeService; + private readonly ILocalizationService _localizationService; - public FileUploadPropertyEditor(ILogger logger, IMediaFileSystem mediaFileSystem, IContentSection contentSection) + public FileUploadPropertyEditor(ILogger logger, IMediaFileSystem mediaFileSystem, IContentSection contentSection, IDataTypeService dataTypeService, ILocalizationService localizationService) : base(logger) { _mediaFileSystem = mediaFileSystem ?? throw new ArgumentNullException(nameof(mediaFileSystem)); _contentSection = contentSection; + _dataTypeService = dataTypeService; + _localizationService = localizationService; _uploadAutoFillProperties = new UploadAutoFillProperties(_mediaFileSystem, logger, contentSection); } @@ -38,7 +43,7 @@ namespace Umbraco.Web.PropertyEditors /// The corresponding property value editor. protected override IDataValueEditor CreateValueEditor() { - var editor = new FileUploadPropertyValueEditor(Attribute, _mediaFileSystem); + var editor = new FileUploadPropertyValueEditor(Attribute, _mediaFileSystem, _dataTypeService, _localizationService); editor.Validators.Add(new UploadFileTypeValidator()); return editor; } @@ -48,7 +53,7 @@ namespace Umbraco.Web.PropertyEditors /// /// The property. /// A value indicating whether a property is an upload field, and (optionally) has a non-empty value. - private static bool IsUploadField(Property property) + private static bool IsUploadField(IProperty property) { return property.PropertyType.PropertyEditorAlias == Constants.PropertyEditors.Aliases.UploadField; } @@ -70,7 +75,7 @@ namespace Umbraco.Web.PropertyEditors /// /// /// - private IEnumerable GetFilePathsFromPropertyValues(Property prop) + private IEnumerable GetFilePathsFromPropertyValues(IProperty prop) { var propVals = prop.Values; foreach (var propertyValue in propVals) diff --git a/src/Umbraco.Web/PropertyEditors/FileUploadPropertyValueEditor.cs b/src/Umbraco.Web/PropertyEditors/FileUploadPropertyValueEditor.cs index 942f53b561..172d8070af 100644 --- a/src/Umbraco.Web/PropertyEditors/FileUploadPropertyValueEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/FileUploadPropertyValueEditor.cs @@ -7,6 +7,7 @@ using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.Models.Editors; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; namespace Umbraco.Web.PropertyEditors { @@ -17,8 +18,8 @@ namespace Umbraco.Web.PropertyEditors { private readonly IMediaFileSystem _mediaFileSystem; - public FileUploadPropertyValueEditor(DataEditorAttribute attribute, IMediaFileSystem mediaFileSystem) - : base(attribute) + public FileUploadPropertyValueEditor(DataEditorAttribute attribute, IMediaFileSystem mediaFileSystem, IDataTypeService dataTypeService, ILocalizationService localizationService) + : base(dataTypeService, localizationService, attribute) { _mediaFileSystem = mediaFileSystem ?? throw new ArgumentNullException(nameof(mediaFileSystem)); } @@ -92,7 +93,7 @@ namespace Umbraco.Web.PropertyEditors if (editorFile == null) return null; return filepath == null ? string.Empty : _mediaFileSystem.GetUrl(filepath); - + } private string ProcessFile(ContentPropertyData editorValue, ContentPropertyFile file, string currentPath, Guid cuid, Guid puid) diff --git a/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs index 24e2fc29a5..6f6f1d911d 100644 --- a/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs @@ -28,14 +28,18 @@ namespace Umbraco.Web.PropertyEditors private IMediaService _mediaService; private IContentTypeBaseServiceProvider _contentTypeBaseServiceProvider; private IUmbracoContextAccessor _umbracoContextAccessor; + private readonly IDataTypeService _dataTypeService; + private readonly ILocalizationService _localizationService; private ILogger _logger; - public GridPropertyEditor(ILogger logger, IMediaService mediaService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, IUmbracoContextAccessor umbracoContextAccessor) + public GridPropertyEditor(ILogger logger, IMediaService mediaService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, IUmbracoContextAccessor umbracoContextAccessor, IDataTypeService dataTypeService, ILocalizationService localizationService) : base(logger) { _mediaService = mediaService; _contentTypeBaseServiceProvider = contentTypeBaseServiceProvider; _umbracoContextAccessor = umbracoContextAccessor; + _dataTypeService = dataTypeService; + _localizationService = localizationService; _logger = logger; } @@ -45,7 +49,7 @@ namespace Umbraco.Web.PropertyEditors /// Overridden to ensure that the value is validated /// /// - protected override IDataValueEditor CreateValueEditor() => new GridPropertyValueEditor(Attribute, _mediaService, _contentTypeBaseServiceProvider, _umbracoContextAccessor, _logger); + protected override IDataValueEditor CreateValueEditor() => new GridPropertyValueEditor(Attribute, _mediaService, _contentTypeBaseServiceProvider, _umbracoContextAccessor, _logger, _dataTypeService, _localizationService); protected override IConfigurationEditor CreateConfigurationEditor() => new GridConfigurationEditor(); @@ -56,8 +60,8 @@ namespace Umbraco.Web.PropertyEditors private IUmbracoContextAccessor _umbracoContextAccessor; private ILogger _logger; - public GridPropertyValueEditor(DataEditorAttribute attribute, IMediaService mediaService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, IUmbracoContextAccessor umbracoContextAccessor, ILogger logger) - : base(attribute) + public GridPropertyValueEditor(DataEditorAttribute attribute, IMediaService mediaService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, IUmbracoContextAccessor umbracoContextAccessor, ILogger logger, IDataTypeService dataTypeService, ILocalizationService localizationService) + : base(dataTypeService, localizationService, attribute) { _mediaService = mediaService; _contentTypeBaseServiceProvider = contentTypeBaseServiceProvider; @@ -115,7 +119,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, 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/GridPropertyIndexValueFactory.cs b/src/Umbraco.Web/PropertyEditors/GridPropertyIndexValueFactory.cs index 0cf36122d7..af72f0b819 100644 --- a/src/Umbraco.Web/PropertyEditors/GridPropertyIndexValueFactory.cs +++ b/src/Umbraco.Web/PropertyEditors/GridPropertyIndexValueFactory.cs @@ -18,7 +18,7 @@ namespace Umbraco.Web.PropertyEditors /// public class GridPropertyIndexValueFactory : IPropertyIndexValueFactory { - public IEnumerable>> GetIndexValues(Property property, string culture, string segment, bool published) + public IEnumerable>> GetIndexValues(IProperty property, string culture, string segment, bool published) { var result = new List>>(); diff --git a/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs index 1d7c1eef65..fe1f026417 100644 --- a/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs @@ -32,17 +32,19 @@ namespace Umbraco.Web.PropertyEditors private readonly IMediaFileSystem _mediaFileSystem; private readonly IContentSection _contentSettings; private readonly IDataTypeService _dataTypeService; + private readonly ILocalizationService _localizationService; private readonly UploadAutoFillProperties _autoFillProperties; /// /// Initializes a new instance of the class. /// - public ImageCropperPropertyEditor(ILogger logger, IMediaFileSystem mediaFileSystem, IContentSection contentSettings, IDataTypeService dataTypeService) + public ImageCropperPropertyEditor(ILogger logger, IMediaFileSystem mediaFileSystem, IContentSection contentSettings, IDataTypeService dataTypeService, ILocalizationService localizationService) : base(logger) { _mediaFileSystem = mediaFileSystem ?? throw new ArgumentNullException(nameof(mediaFileSystem)); _contentSettings = contentSettings ?? throw new ArgumentNullException(nameof(contentSettings)); _dataTypeService = dataTypeService; + _localizationService = localizationService; // TODO: inject? _autoFillProperties = new UploadAutoFillProperties(_mediaFileSystem, logger, _contentSettings); @@ -52,7 +54,7 @@ namespace Umbraco.Web.PropertyEditors /// Creates the corresponding property value editor. /// /// The corresponding property value editor. - protected override IDataValueEditor CreateValueEditor() => new ImageCropperPropertyValueEditor(Attribute, Logger, _mediaFileSystem); + protected override IDataValueEditor CreateValueEditor() => new ImageCropperPropertyValueEditor(Attribute, Logger, _mediaFileSystem, _dataTypeService, _localizationService); /// /// Creates the corresponding preValue editor. @@ -65,7 +67,7 @@ namespace Umbraco.Web.PropertyEditors /// /// The property. /// A value indicating whether a property is an image cropper field, and (optionally) has a non-empty value. - private static bool IsCropperField(Property property) + private static bool IsCropperField(IProperty property) { return property.PropertyType.PropertyEditorAlias == Constants.PropertyEditors.Aliases.ImageCropper; } @@ -111,7 +113,7 @@ namespace Umbraco.Web.PropertyEditors /// /// /// - private IEnumerable GetFilePathsFromPropertyValues(Property prop) + private IEnumerable GetFilePathsFromPropertyValues(IProperty prop) { //parses out the src from a json string diff --git a/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyValueEditor.cs b/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyValueEditor.cs index 4aac8f54aa..1dab41d4e6 100644 --- a/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyValueEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyValueEditor.cs @@ -21,8 +21,8 @@ namespace Umbraco.Web.PropertyEditors private readonly ILogger _logger; private readonly IMediaFileSystem _mediaFileSystem; - public ImageCropperPropertyValueEditor(DataEditorAttribute attribute, ILogger logger, IMediaFileSystem mediaFileSystem) - : base(attribute) + public ImageCropperPropertyValueEditor(DataEditorAttribute attribute, ILogger logger, IMediaFileSystem mediaFileSystem, IDataTypeService dataTypeService, ILocalizationService localizationService) + : base(dataTypeService, localizationService, attribute) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _mediaFileSystem = mediaFileSystem ?? throw new ArgumentNullException(nameof(mediaFileSystem)); @@ -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, string culture = null, string segment = null) { var val = property.GetValue(culture, segment); if (val == null) return null; @@ -47,7 +47,7 @@ namespace Umbraco.Web.PropertyEditors value = new ImageCropperValue { Src = val.ToString() }; } - var dataType = dataTypeService.GetDataType(property.PropertyType.DataTypeId); + var dataType = DataTypeService.GetDataType(property.PropertyType.DataTypeId); if (dataType?.Configuration != null) value.ApplyConfiguration(dataType.ConfigurationAs()); @@ -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) { if (value == null || string.IsNullOrEmpty(value.ToString())) return null; @@ -172,7 +172,7 @@ namespace Umbraco.Web.PropertyEditors return val; // more magic here ;-( - var configuration = dataTypeService.GetDataType(propertyType.DataTypeId).ConfigurationAs(); + var configuration = DataTypeService.GetDataType(propertyType.DataTypeId).ConfigurationAs(); var crops = configuration?.Crops ?? Array.Empty(); return JsonConvert.SerializeObject(new diff --git a/src/Umbraco.Web/PropertyEditors/MultiUrlPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MultiUrlPickerPropertyEditor.cs index 95ac809576..a5da833501 100644 --- a/src/Umbraco.Web/PropertyEditors/MultiUrlPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MultiUrlPickerPropertyEditor.cs @@ -19,15 +19,19 @@ namespace Umbraco.Web.PropertyEditors { private readonly IEntityService _entityService; private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor; + private readonly IDataTypeService _dataTypeService; + private readonly ILocalizationService _localizationService; - public MultiUrlPickerPropertyEditor(ILogger logger, IEntityService entityService, IPublishedSnapshotAccessor publishedSnapshotAccessor) : base(logger, EditorType.PropertyValue) + public MultiUrlPickerPropertyEditor(ILogger logger, IEntityService entityService, IPublishedSnapshotAccessor publishedSnapshotAccessor, IDataTypeService dataTypeService, ILocalizationService localizationService) : base(logger, EditorType.PropertyValue) { _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); _publishedSnapshotAccessor = publishedSnapshotAccessor ?? throw new ArgumentNullException(nameof(publishedSnapshotAccessor)); + _dataTypeService = dataTypeService; + _localizationService = localizationService; } protected override IConfigurationEditor CreateConfigurationEditor() => new MultiUrlPickerConfigurationEditor(); - protected override IDataValueEditor CreateValueEditor() => new MultiUrlPickerValueEditor(_entityService, _publishedSnapshotAccessor, Logger, Attribute); + protected override IDataValueEditor CreateValueEditor() => new MultiUrlPickerValueEditor(_entityService, _publishedSnapshotAccessor, Logger, _dataTypeService, _localizationService, Attribute); } } diff --git a/src/Umbraco.Web/PropertyEditors/MultiUrlPickerValueEditor.cs b/src/Umbraco.Web/PropertyEditors/MultiUrlPickerValueEditor.cs index aa8fa73c7a..97d787dbba 100644 --- a/src/Umbraco.Web/PropertyEditors/MultiUrlPickerValueEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MultiUrlPickerValueEditor.cs @@ -21,14 +21,14 @@ namespace Umbraco.Web.PropertyEditors private readonly ILogger _logger; private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor; - public MultiUrlPickerValueEditor(IEntityService entityService, IPublishedSnapshotAccessor publishedSnapshotAccessor, ILogger logger, DataEditorAttribute attribute) : base(attribute) + public MultiUrlPickerValueEditor(IEntityService entityService, IPublishedSnapshotAccessor publishedSnapshotAccessor, ILogger logger, IDataTypeService dataTypeService, ILocalizationService localizationService, DataEditorAttribute attribute) : base(dataTypeService, localizationService, attribute) { _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); _publishedSnapshotAccessor = publishedSnapshotAccessor ?? throw new ArgumentNullException(nameof(publishedSnapshotAccessor)); _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, string culture = null, string segment = null) { var value = property.GetValue(culture, segment)?.ToString(); @@ -118,7 +118,7 @@ namespace Umbraco.Web.PropertyEditors _logger.Error("Error getting links", ex); } - return base.ToEditor(property, dataTypeService, culture, segment); + return base.ToEditor(property, culture, segment); } diff --git a/src/Umbraco.Web/PropertyEditors/MultipleTextStringPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MultipleTextStringPropertyEditor.cs index fa82bc555c..29ec8530d9 100644 --- a/src/Umbraco.Web/PropertyEditors/MultipleTextStringPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MultipleTextStringPropertyEditor.cs @@ -4,6 +4,7 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using Newtonsoft.Json.Linq; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Exceptions; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -34,7 +35,7 @@ namespace Umbraco.Web.PropertyEditors { } /// - protected override IDataValueEditor CreateValueEditor() => new MultipleTextStringPropertyValueEditor(Attribute); + protected override IDataValueEditor CreateValueEditor() => new MultipleTextStringPropertyValueEditor(Current.Services.DataTypeService, Current.Services.LocalizationService,Attribute); /// protected override IConfigurationEditor CreateConfigurationEditor() => new MultipleTextStringConfigurationEditor(); @@ -44,8 +45,8 @@ namespace Umbraco.Web.PropertyEditors /// internal class MultipleTextStringPropertyValueEditor : DataValueEditor { - public MultipleTextStringPropertyValueEditor(DataEditorAttribute attribute) - : base(attribute) + public MultipleTextStringPropertyValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, DataEditorAttribute attribute) + : base(dataTypeService, localizationService, attribute) { } /// @@ -95,7 +96,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, 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..f5ca6c5cfe 100644 --- a/src/Umbraco.Web/PropertyEditors/MultipleValueEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MultipleValueEditor.cs @@ -19,8 +19,8 @@ namespace Umbraco.Web.PropertyEditors { private readonly ILogger _logger; - internal MultipleValueEditor(ILogger logger, DataEditorAttribute attribute) - : base(attribute) + internal MultipleValueEditor(ILogger logger, IDataTypeService dataTypeService, ILocalizationService localizationService, DataEditorAttribute attribute) + : base(dataTypeService, localizationService, attribute) { _logger = logger; } @@ -33,9 +33,9 @@ namespace Umbraco.Web.PropertyEditors /// /// /// - public override object ToEditor(Property property, IDataTypeService dataTypeService, string culture = null, string segment = null) + public override object ToEditor(IProperty property, string culture = null, string segment = null) { - var json = base.ToEditor(property, dataTypeService, culture, segment).ToString(); + var json = base.ToEditor(property, 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..45083a12a1 100644 --- a/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs @@ -28,13 +28,17 @@ namespace Umbraco.Web.PropertyEditors public class NestedContentPropertyEditor : DataEditor { private readonly Lazy _propertyEditors; + private readonly IDataTypeService _dataTypeService; + private readonly ILocalizationService _localizationService; internal const string ContentTypeAliasPropertyKey = "ncContentTypeAlias"; - public NestedContentPropertyEditor(ILogger logger, Lazy propertyEditors) + public NestedContentPropertyEditor(ILogger logger, Lazy propertyEditors, IDataTypeService dataTypeService, ILocalizationService localizationService) : base (logger) { _propertyEditors = propertyEditors; + _dataTypeService = dataTypeService; + _localizationService = localizationService; } // has to be lazy else circular dep in ctor @@ -48,7 +52,7 @@ namespace Umbraco.Web.PropertyEditors #region Value Editor - protected override IDataValueEditor CreateValueEditor() => new NestedContentPropertyValueEditor(Attribute, PropertyEditors); + protected override IDataValueEditor CreateValueEditor() => new NestedContentPropertyValueEditor(_dataTypeService, _localizationService, Attribute, PropertyEditors); internal class NestedContentPropertyValueEditor : DataValueEditor { @@ -58,8 +62,8 @@ namespace Umbraco.Web.PropertyEditors Current.Services.ContentTypeService.GetAll().ToDictionary(c => c.Alias) ); - public NestedContentPropertyValueEditor(DataEditorAttribute attribute, PropertyEditorCollection propertyEditors) - : base(attribute) + public NestedContentPropertyValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, DataEditorAttribute attribute, PropertyEditorCollection propertyEditors) + : base(dataTypeService, localizationService, attribute) { _propertyEditors = propertyEditors; Validators.Add(new NestedContentValidator(propertyEditors, GetElementType)); @@ -92,7 +96,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) { if (propertyValue == null || string.IsNullOrWhiteSpace(propertyValue.ToString())) return string.Empty; @@ -129,9 +133,9 @@ namespace Umbraco.Web.PropertyEditors { continue; } - var tempConfig = dataTypeService.GetDataType(propType.DataTypeId).Configuration; + var tempConfig = DataTypeService.GetDataType(propType.DataTypeId).Configuration; var valEditor = propEditor.GetValueEditor(tempConfig); - var convValue = valEditor.ConvertDbToString(propType, propValues[propAlias]?.ToString(), dataTypeService); + var convValue = valEditor.ConvertDbToString(propType, propValues[propAlias]?.ToString()); propValues[propAlias] = convValue; } catch (InvalidOperationException) @@ -152,7 +156,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, string culture = null, string segment = null) { var val = property.GetValue(culture, segment); if (val == null || string.IsNullOrWhiteSpace(val.ToString())) @@ -197,9 +201,9 @@ namespace Umbraco.Web.PropertyEditors propValues[propAlias] = tempProp.GetValue()?.ToString(); continue; } - var tempConfig = dataTypeService.GetDataType(propType.DataTypeId).Configuration; + var tempConfig = DataTypeService.GetDataType(propType.DataTypeId).Configuration; var valEditor = propEditor.GetValueEditor(tempConfig); - var convValue = valEditor.ToEditor(tempProp, dataTypeService); + var convValue = valEditor.ToEditor(tempProp); propValues[propAlias] = convValue == null ? null : JToken.FromObject(convValue); } catch (InvalidOperationException) diff --git a/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs index 5743e9c1d5..aa6876df39 100644 --- a/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs @@ -27,16 +27,26 @@ namespace Umbraco.Web.PropertyEditors private IMediaService _mediaService; private IContentTypeBaseServiceProvider _contentTypeBaseServiceProvider; private IUmbracoContextAccessor _umbracoContextAccessor; + private readonly IDataTypeService _dataTypeService; + private readonly ILocalizationService _localizationService; private ILogger _logger; /// /// The constructor will setup the property editor based on the attribute if one is found /// - public RichTextPropertyEditor(ILogger logger, IMediaService mediaService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, IUmbracoContextAccessor umbracoContextAccessor) : base(logger) + public RichTextPropertyEditor( + ILogger logger, + IMediaService mediaService, + IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, + IUmbracoContextAccessor umbracoContextAccessor, + IDataTypeService dataTypeService, + ILocalizationService localizationService) : base(logger) { _mediaService = mediaService; _contentTypeBaseServiceProvider = contentTypeBaseServiceProvider; _umbracoContextAccessor = umbracoContextAccessor; + _dataTypeService = dataTypeService; + _localizationService = localizationService; _logger = logger; } @@ -44,7 +54,7 @@ namespace Umbraco.Web.PropertyEditors /// Create a custom value editor /// /// - protected override IDataValueEditor CreateValueEditor() => new RichTextPropertyValueEditor(Attribute, _mediaService, _contentTypeBaseServiceProvider, _umbracoContextAccessor, _logger); + protected override IDataValueEditor CreateValueEditor() => new RichTextPropertyValueEditor(Attribute, _mediaService, _contentTypeBaseServiceProvider, _umbracoContextAccessor, _logger, _dataTypeService, _localizationService); protected override IConfigurationEditor CreateConfigurationEditor() => new RichTextConfigurationEditor(); @@ -60,8 +70,8 @@ namespace Umbraco.Web.PropertyEditors private IUmbracoContextAccessor _umbracoContextAccessor; private ILogger _logger; - public RichTextPropertyValueEditor(DataEditorAttribute attribute, IMediaService mediaService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, IUmbracoContextAccessor umbracoContextAccessor, ILogger logger) - : base(attribute) + public RichTextPropertyValueEditor(DataEditorAttribute attribute, IMediaService mediaService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, IUmbracoContextAccessor umbracoContextAccessor, ILogger logger, IDataTypeService dataTypeService, ILocalizationService localizationService) + : base(dataTypeService, localizationService, attribute) { _mediaService = mediaService; _contentTypeBaseServiceProvider = contentTypeBaseServiceProvider; @@ -92,7 +102,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, string culture = null, string segment = null) { var val = property.GetValue(culture, segment); if (val == null) @@ -130,7 +140,7 @@ namespace Umbraco.Web.PropertyEditors internal class RichTextPropertyIndexValueFactory : IPropertyIndexValueFactory { - public IEnumerable>> GetIndexValues(Property property, string culture, string segment, bool published) + public IEnumerable>> GetIndexValues(IProperty property, string culture, string segment, bool published) { var val = property.GetValue(culture, segment, published); diff --git a/src/Umbraco.Web/PropertyEditors/TagsPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/TagsPropertyEditor.cs index fd7e8694a3..74338ba3fa 100644 --- a/src/Umbraco.Web/PropertyEditors/TagsPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/TagsPropertyEditor.cs @@ -4,10 +4,12 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using Newtonsoft.Json.Linq; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Editors; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; namespace Umbraco.Web.PropertyEditors { @@ -30,14 +32,14 @@ namespace Umbraco.Web.PropertyEditors _validators = validators; } - protected override IDataValueEditor CreateValueEditor() => new TagPropertyValueEditor(Attribute); + protected override IDataValueEditor CreateValueEditor() => new TagPropertyValueEditor(Current.Services.DataTypeService, Current.Services.LocalizationService, Attribute); protected override IConfigurationEditor CreateConfigurationEditor() => new TagConfigurationEditor(_validators); internal class TagPropertyValueEditor : DataValueEditor { - public TagPropertyValueEditor(DataEditorAttribute attribute) - : base(attribute) + public TagPropertyValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, DataEditorAttribute attribute) + : base(dataTypeService, localizationService, attribute) { } /// diff --git a/src/Umbraco.Web/PropertyEditors/TextAreaPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/TextAreaPropertyEditor.cs index c7bc2efbda..28698e2c5c 100644 --- a/src/Umbraco.Web/PropertyEditors/TextAreaPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/TextAreaPropertyEditor.cs @@ -1,6 +1,7 @@ using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; namespace Umbraco.Web.PropertyEditors { @@ -16,15 +17,21 @@ namespace Umbraco.Web.PropertyEditors Icon = "icon-application-window-alt")] public class TextAreaPropertyEditor : DataEditor { + private readonly IDataTypeService _dataTypeService; + private readonly ILocalizationService _localizationService; + /// /// Initializes a new instance of the class. /// - public TextAreaPropertyEditor(ILogger logger) + public TextAreaPropertyEditor(ILogger logger, IDataTypeService dataTypeService, ILocalizationService localizationService) : base(logger) - { } + { + _dataTypeService = dataTypeService; + _localizationService = localizationService; + } /// - protected override IDataValueEditor CreateValueEditor() => new TextOnlyValueEditor(Attribute); + protected override IDataValueEditor CreateValueEditor() => new TextOnlyValueEditor(_dataTypeService, _localizationService, Attribute); /// protected override IConfigurationEditor CreateConfigurationEditor() => new TextAreaConfigurationEditor(); diff --git a/src/Umbraco.Web/PropertyEditors/TextOnlyValueEditor.cs b/src/Umbraco.Web/PropertyEditors/TextOnlyValueEditor.cs index 754cef1f31..782e19e42d 100644 --- a/src/Umbraco.Web/PropertyEditors/TextOnlyValueEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/TextOnlyValueEditor.cs @@ -11,8 +11,8 @@ namespace Umbraco.Web.PropertyEditors /// public class TextOnlyValueEditor : DataValueEditor { - public TextOnlyValueEditor(DataEditorAttribute attribute) - : base(attribute) + public TextOnlyValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, DataEditorAttribute attribute) + : base(dataTypeService, localizationService, attribute) { } /// @@ -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, string culture = null, string segment = null) { var val = property.GetValue(culture, segment); diff --git a/src/Umbraco.Web/PropertyEditors/TextboxPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/TextboxPropertyEditor.cs index 18f8155198..c7c13b4caf 100644 --- a/src/Umbraco.Web/PropertyEditors/TextboxPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/TextboxPropertyEditor.cs @@ -1,6 +1,7 @@ using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; namespace Umbraco.Web.PropertyEditors { @@ -15,15 +16,21 @@ namespace Umbraco.Web.PropertyEditors Group = Constants.PropertyEditors.Groups.Common)] public class TextboxPropertyEditor : DataEditor { + private readonly IDataTypeService _dataTypeService; + private readonly ILocalizationService _localizationService; + /// /// Initializes a new instance of the class. /// - public TextboxPropertyEditor(ILogger logger) + public TextboxPropertyEditor(ILogger logger, IDataTypeService dataTypeService, ILocalizationService localizationService) : base(logger) - { } + { + _dataTypeService = dataTypeService; + _localizationService = localizationService; + } /// - protected override IDataValueEditor CreateValueEditor() => new TextOnlyValueEditor(Attribute); + protected override IDataValueEditor CreateValueEditor() => new TextOnlyValueEditor(_dataTypeService, _localizationService, Attribute); /// protected override IConfigurationEditor CreateConfigurationEditor() => new TextboxConfigurationEditor(); diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs index bf4975714d..6d34a2af42 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs @@ -4,6 +4,7 @@ using System.Linq; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Exceptions; +using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Web.Composing; using Umbraco.Web.Models; diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 79b0fe8744..589880f70c 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -41,7 +41,6 @@ - @@ -1284,4 +1283,4 @@ - \ No newline at end of file +