Merge pull request #7120 from umbraco/netcore/feature/AB3649-move-manifest-stuff

Netcore: Move manifest code
This commit is contained in:
Shannon Deminick
2019-11-14 12:10:25 +11:00
committed by GitHub
129 changed files with 935 additions and 705 deletions
@@ -47,8 +47,7 @@ namespace Umbraco.Core.Collections
var newList = new DeepCloneableList<T>(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<T>(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<IRememberBeingDirty>())
@@ -1,5 +1,6 @@
using System.Collections.Generic;
namespace Umbraco.Core.Manifest
{
/// <summary>
@@ -0,0 +1,23 @@
using System.Collections.Generic;
using Umbraco.Core.PropertyEditors;
namespace Umbraco.Core.Manifest
{
public interface IManifestParser
{
string Path { get; set; }
/// <summary>
/// Gets all manifests, merged into a single manifest object.
/// </summary>
/// <returns></returns>
PackageManifest Manifest { get; }
/// <summary>
/// Parses a manifest.
/// </summary>
PackageManifest ParseManifest(string text);
IEnumerable<GridEditor> ParseGridEditors(string text);
}
}
@@ -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.
/// </summary>
[DataMember(Name = "view")]
public string View
{
get => _view;
set => _view = Current.IOHelper.ResolveVirtualUrl(value);
}
public string View { get; set; }
/// <summary>
/// Gets or sets the list of 'show' conditions for the content app.
@@ -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<string>();
[DataMember(Name = "access")]
public IAccessRule[] AccessRules { get; set; } = Array.Empty<IAccessRule>();
}
}
@@ -1,70 +1,71 @@
using System;
using Newtonsoft.Json;
using Umbraco.Core.PropertyEditors;
namespace Umbraco.Core.Manifest
{
/// <summary>
/// Represents the content of a package manifest.
/// </summary>
public class PackageManifest
{
/// <summary>
/// Gets the source path of the manifest.
/// </summary>
/// <remarks>
/// <para>Gets the full absolute file path of the manifest,
/// using system directory separators.</para>
/// </remarks>
[JsonIgnore]
public string Source { get; set; }
/// <summary>
/// Gets or sets the scripts listed in the manifest.
/// </summary>
[JsonProperty("javascript")]
public string[] Scripts { get; set; } = Array.Empty<string>();
/// <summary>
/// Gets or sets the stylesheets listed in the manifest.
/// </summary>
[JsonProperty("css")]
public string[] Stylesheets { get; set; } = Array.Empty<string>();
/// <summary>
/// Gets or sets the property editors listed in the manifest.
/// </summary>
[JsonProperty("propertyEditors")]
public IDataEditor[] PropertyEditors { get; set; } = Array.Empty<IDataEditor>();
/// <summary>
/// Gets or sets the parameter editors listed in the manifest.
/// </summary>
[JsonProperty("parameterEditors")]
public IDataEditor[] ParameterEditors { get; set; } = Array.Empty<IDataEditor>();
/// <summary>
/// Gets or sets the grid editors listed in the manifest.
/// </summary>
[JsonProperty("gridEditors")]
public GridEditor[] GridEditors { get; set; } = Array.Empty<GridEditor>();
/// <summary>
/// Gets or sets the content apps listed in the manifest.
/// </summary>
[JsonProperty("contentApps")]
public ManifestContentAppDefinition[] ContentApps { get; set; } = Array.Empty<ManifestContentAppDefinition>();
/// <summary>
/// Gets or sets the dashboards listed in the manifest.
/// </summary>
[JsonProperty("dashboards")]
public ManifestDashboard[] Dashboards { get; set; } = Array.Empty<ManifestDashboard>();
/// <summary>
/// Gets or sets the sections listed in the manifest.
/// </summary>
[JsonProperty("sections")]
public ManifestSection[] Sections { get; set; } = Array.Empty<ManifestSection>();
}
}
using System;
using System.Runtime.Serialization;
using Umbraco.Core.PropertyEditors;
namespace Umbraco.Core.Manifest
{
/// <summary>
/// Represents the content of a package manifest.
/// </summary>
[DataContract]
public class PackageManifest
{
/// <summary>
/// Gets the source path of the manifest.
/// </summary>
/// <remarks>
/// <para>Gets the full absolute file path of the manifest,
/// using system directory separators.</para>
/// </remarks>
[IgnoreDataMember]
public string Source { get; set; }
/// <summary>
/// Gets or sets the scripts listed in the manifest.
/// </summary>
[DataMember(Name = "javascript")]
public string[] Scripts { get; set; } = Array.Empty<string>();
/// <summary>
/// Gets or sets the stylesheets listed in the manifest.
/// </summary>
[DataMember(Name = "css")]
public string[] Stylesheets { get; set; } = Array.Empty<string>();
/// <summary>
/// Gets or sets the property editors listed in the manifest.
/// </summary>
[DataMember(Name = "propertyEditors")]
public IDataEditor[] PropertyEditors { get; set; } = Array.Empty<IDataEditor>();
/// <summary>
/// Gets or sets the parameter editors listed in the manifest.
/// </summary>
[DataMember(Name = "parameterEditors")]
public IDataEditor[] ParameterEditors { get; set; } = Array.Empty<IDataEditor>();
/// <summary>
/// Gets or sets the grid editors listed in the manifest.
/// </summary>
[DataMember(Name = "gridEditors")]
public GridEditor[] GridEditors { get; set; } = Array.Empty<GridEditor>();
/// <summary>
/// Gets or sets the content apps listed in the manifest.
/// </summary>
[DataMember(Name = "contentApps")]
public ManifestContentAppDefinition[] ContentApps { get; set; } = Array.Empty<ManifestContentAppDefinition>();
/// <summary>
/// Gets or sets the dashboards listed in the manifest.
/// </summary>
[DataMember(Name = "dashboards")]
public ManifestDashboard[] Dashboards { get; set; } = Array.Empty<ManifestDashboard>();
/// <summary>
/// Gets or sets the sections listed in the manifest.
/// </summary>
[DataMember(Name = "sections")]
public ManifestSection[] Sections { get; set; } = Array.Empty<ManifestSection>();
}
}
@@ -36,7 +36,7 @@ namespace Umbraco.Core.Models
/// Gets the unique identifier of the document targeted by the scheduled action.
/// </summary>
[DataMember]
public Guid Id { get; internal set; }
public Guid Id { get; set; }
/// <summary>
/// Gets the culture of the scheduled action.
@@ -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();
@@ -26,5 +26,15 @@ namespace Umbraco.Core.Models.Entities
/// Resets dirty properties.
/// </summary>
void ResetDirtyProperties();
/// <summary>
/// Disables change tracking.
/// </summary>
void DisableChangeTracking();
/// <summary>
/// Enables change tracking.
/// </summary>
void EnableChangeTracking();
}
}
@@ -98,7 +98,7 @@ namespace Umbraco.Core.Models
/// List of properties, which make up all the data available for this Content object
/// </summary>
/// <remarks>Properties are loaded as part of the Content object graph</remarks>
PropertyCollection Properties { get; set; }
IPropertyCollection Properties { get; set; }
/// <summary>
/// Gets a value indicating whether the content entity has a property with the supplied alias.
@@ -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
/// <summary>
/// Converts a property value to a value for the editor.
/// </summary>
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<XElement> 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<XElement> ConvertDbToXml(IProperty property, bool published);
XNode ConvertDbToXml(IPropertyType propertyType, object value);
string ConvertDbToString(IPropertyType propertyType, object value);
}
}
@@ -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; }
/// <summary>
/// Returns the PropertyType, which this Property is based on
/// </summary>
IPropertyType PropertyType { get; }
/// <summary>
/// Gets the list of values.
/// </summary>
IReadOnlyCollection<IPropertyValue> Values { get; set; }
/// <summary>
/// Returns the Alias of the PropertyType, which this Property is based on
/// </summary>
string Alias { get; }
/// <summary>
/// Gets the value.
/// </summary>
object GetValue(string culture = null, string segment = null, bool published = false);
/// <summary>
/// Sets a value.
/// </summary>
void SetValue(object value, string culture = null, string segment = null);
/// <summary>
/// Resets the entity identity.
/// </summary>
void ResetIdentity();
int PropertyTypeId { get; }
void PublishValues(string culture = "*", string segment = "*");
void UnpublishValues(string culture = "*", string segment = "*");
}
}
@@ -0,0 +1,38 @@
using System.Collections.Generic;
using System.Collections.Specialized;
namespace Umbraco.Core.Models
{
public interface IPropertyCollection : IEnumerable<IProperty>, IDeepCloneable, INotifyCollectionChanged
{
bool TryGetValue(string propertyTypeAlias, out IProperty property);
bool Contains(string key);
/// <summary>
/// Ensures that the collection contains properties for the specified property types.
/// </summary>
void EnsurePropertyTypes(IEnumerable<IPropertyType> propertyTypes);
/// <summary>
/// Ensures that the collection does not contain properties not in the specified property types.
/// </summary>
void EnsureCleanPropertyTypes(IEnumerable<IPropertyType> propertyTypes);
/// <summary>
/// Gets the property with the specified alias.
/// </summary>
IProperty this[string name] { get; }
/// <summary>
/// Gets the property at the specified index.
/// </summary>
IProperty this[int index] { get; }
/// <summary>
/// Adds or updates a property.
/// </summary>
void Add(IProperty property);
int Count { get; }
}
}
@@ -0,0 +1,87 @@
using System;
using System.Runtime.Serialization;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
public interface IPropertyType : IEntity, IRememberBeingDirty
{
/// <summary>
/// Gets of sets the name of the property type.
/// </summary>
string Name { get; }
/// <summary>
/// Gets of sets the alias of the property type.
/// </summary>
string Alias { get; }
/// <summary>
/// Gets of sets the description of the property type.
/// </summary>
string Description { get; }
/// <summary>
/// Gets or sets the identifier of the datatype for this property type.
/// </summary>
int DataTypeId { get; }
Guid DataTypeKey { get; }
/// <summary>
/// Gets or sets the alias of the property editor for this property type.
/// </summary>
string PropertyEditorAlias { get; }
/// <summary>
/// Gets or sets the database type for storing value for this property type.
/// </summary>
ValueStorageType ValueStorageType { get; }
/// <summary>
/// Gets or sets the identifier of the property group this property type belongs to.
/// </summary>
/// <remarks>For generic properties, the value is <c>null</c>.</remarks>
Lazy<int> PropertyGroupId { get; }
/// <summary>
/// Gets of sets a value indicating whether a value for this property type is required.
/// </summary>
bool Mandatory { get; }
/// <summary>
/// Gets of sets the sort order of the property type.
/// </summary>
int SortOrder { get; }
/// <summary>
/// Gets or sets the regular expression validating the property values.
/// </summary>
string ValidationRegExp { get; }
bool SupportsPublishing { get; }
/// <summary>
/// Gets or sets the content variation of the property type.
/// </summary>
ContentVariation Variations { get; }
/// <summary>
/// Determines whether the property type supports a combination of culture and segment.
/// </summary>
/// <param name="culture">The culture.</param>
/// <param name="segment">The segment.</param>
/// <param name="wildcards">A value indicating whether wildcards are valid.</param>
bool SupportsVariation(string culture, string segment, bool wildcards = false);
/// <summary>
/// Converts a value assigned to a property.
/// </summary>
/// <remarks>
/// <para>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).</para>
/// <para>Throws if the value cannot be converted.</para>
/// </remarks>
object ConvertAssignedValue(object value);
}
}
@@ -0,0 +1,34 @@
namespace Umbraco.Core.Models
{
public interface IPropertyValue
{
/// <summary>
/// Gets or sets the culture of the property.
/// </summary>
/// <remarks>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.</remarks>
string Culture { get; set; }
/// <summary>
/// Gets or sets the segment of the property.
/// </summary>
/// <remarks>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.</remarks>
string Segment { get; set; }
/// <summary>
/// Gets or sets the edited value of the property.
/// </summary>
object EditedValue { get; set; }
/// <summary>
/// Gets or sets the published value of the property.
/// </summary>
object PublishedValue { get; set; }
/// <summary>
/// Clones the property value.
/// </summary>
IPropertyValue Clone();
}
}
@@ -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
{
/// <summary>
/// Represents a datatype configuration field for editing.
/// </summary>
[DataContract]
public class ConfigurationField
{
private string _view;
@@ -50,37 +50,35 @@ namespace Umbraco.Core.PropertyEditors
/// <summary>
/// Gets or sets the key of the field.
/// </summary>
[JsonProperty("key", Required = Required.Always)]
[DataMember(Name = "key", IsRequired = true)]
public string Key { get; set; }
/// <summary>
/// Gets or sets the name of the field.
/// </summary>
[JsonProperty("label", Required = Required.Always)]
[DataMember(Name = "label", IsRequired = true)]
public string Name { get; set; }
/// <summary>
/// Gets or sets the property name of the field.
/// </summary>
[JsonIgnore]
public string PropertyName { get; set; }
/// <summary>
/// Gets or sets the property CLR type of the field.
/// </summary>
[JsonIgnore]
public Type PropertyType { get; set; }
/// <summary>
/// Gets or sets the description of the field.
/// </summary>
[JsonProperty("description")]
[DataMember(Name = "description")]
public string Description { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to hide the label of the field.
/// </summary>
[JsonProperty("hideLabel")]
[DataMember(Name = "hideLabel")]
public bool HideLabel { get; set; }
/// <summary>
@@ -90,23 +88,19 @@ namespace Umbraco.Core.PropertyEditors
/// <para>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.</para>
/// </remarks>
[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; }
/// <summary>
/// Gets the validators of the field.
/// </summary>
[JsonProperty("validation")]
[DataMember(Name = "validation")]
public List<IValueValidator> Validators { get; }
/// <summary>
/// Gets or sets extra configuration properties for the editor.
/// </summary>
[JsonProperty("config")]
[DataMember(Name = "config")]
public IDictionary<string, object> Config { get; set; }
}
}
@@ -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<string, object>();
}
[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<string, object> Config { get; set; }
protected bool Equals(GridEditor other)
@@ -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.</para>
/// </remarks>
IEnumerable<KeyValuePair<string, IEnumerable<object>>> GetIndexValues(Property property, string culture, string segment, bool published);
IEnumerable<KeyValuePair<string, IEnumerable<object>>> GetIndexValues(IProperty property, string culture, string segment, bool published);
}
}
@@ -0,0 +1,9 @@
using Umbraco.Core.Composing;
namespace Umbraco.Core.PropertyEditors
{
public class ManifestValueValidatorCollectionBuilder : LazyCollectionBuilderBase<ManifestValueValidatorCollectionBuilder, ManifestValueValidatorCollection, IManifestValueValidator>
{
protected override ManifestValueValidatorCollectionBuilder This => this;
}
}
@@ -6,7 +6,7 @@ namespace Umbraco.Core.PropertyEditors.Validators
/// <summary>
/// A validator that validates that the value is a valid decimal
/// </summary>
internal sealed class DecimalValidator : IManifestValueValidator
public sealed class DecimalValidator : IManifestValueValidator
{
/// <inheritdoc />
public string ValidationName => "Decimal";
@@ -6,7 +6,7 @@ namespace Umbraco.Core.PropertyEditors.Validators
/// <summary>
/// A validator that validates an email address
/// </summary>
internal sealed class EmailValidator : IManifestValueValidator
public sealed class EmailValidator : IManifestValueValidator
{
/// <inheritdoc />
public string ValidationName => "Email";
@@ -6,7 +6,7 @@ namespace Umbraco.Core.PropertyEditors.Validators
/// <summary>
/// A validator that validates that the value is a valid integer
/// </summary>
internal sealed class IntegerValidator : IManifestValueValidator
public sealed class IntegerValidator : IManifestValueValidator
{
/// <inheritdoc />
public string ValidationName => "Integer";
@@ -19,7 +19,7 @@ namespace Umbraco.Core.Services
/// Adds or updates a translation for a dictionary item and language
/// </summary>
/// <param name="item"></param>
/// <param name="language"></param>
/// <param name="language"></param
/// <param name="value"></param>
/// <returns></returns>
void AddOrUpdateDictionaryValue(IDictionaryItem item, ILanguage language, string value);
@@ -7,6 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.ComponentModel.Annotations" Version="4.6.0" />
<PackageReference Include="System.Runtime.Caching" Version="4.6.0" />
</ItemGroup>
+3 -3
View File
@@ -108,7 +108,7 @@ namespace Umbraco.Core
/// </summary>
/// <param name="content"></param>
/// <returns></returns>
public static IEnumerable<Property> GetNonGroupedProperties(this IContentBase content)
public static IEnumerable<IProperty> GetNonGroupedProperties(this IContentBase content)
{
return content.Properties
.Where(x => x.PropertyType.PropertyGroupId == null)
@@ -121,7 +121,7 @@ namespace Umbraco.Core
/// <param name="content"></param>
/// <param name="propertyGroup"></param>
/// <returns></returns>
public static IEnumerable<Property> GetPropertiesForGroup(this IContentBase content, PropertyGroup propertyGroup)
public static IEnumerable<IProperty> 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;
@@ -50,18 +50,18 @@ namespace Umbraco.Core
/// Determines whether the property type varies by culture.
/// </summary>
/// <remarks>And then it could also vary by segment.</remarks>
public static bool VariesByCulture(this PropertyType propertyType) => propertyType.Variations.VariesByCulture();
public static bool VariesByCulture(this IPropertyType propertyType) => propertyType.Variations.VariesByCulture();
/// <summary>
/// Determines whether the property type varies by segment.
/// </summary>
/// <remarks>And then it could also vary by culture.</remarks>
public static bool VariesBySegment(this PropertyType propertyType) => propertyType.Variations.VariesBySegment();
public static bool VariesBySegment(this IPropertyType propertyType) => propertyType.Variations.VariesBySegment();
/// <summary>
/// Determines whether the property type varies by culture and segment.
/// </summary>
public static bool VariesByCultureAndSegment(this PropertyType propertyType) => propertyType.Variations.VariesByCultureAndSegment();
public static bool VariesByCultureAndSegment(this IPropertyType propertyType) => propertyType.Variations.VariesByCultureAndSegment();
/// <summary>
/// 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
+2 -2
View File
@@ -52,7 +52,7 @@ namespace Umbraco.Core.IO
/// <para>If an <paramref name="oldpath"/> 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.</para>
/// </remarks>
string StoreFile(IContentBase content, PropertyType propertyType, string filename, Stream filestream, string oldpath);
string StoreFile(IContentBase content, IPropertyType propertyType, string filename, Stream filestream, string oldpath);
/// <summary>
/// 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
/// <param name="propertyType">The property type owning the copy of the media file.</param>
/// <param name="sourcepath">The filesystem-relative path to the source media file.</param>
/// <returns>The filesystem-relative path to the copy of the media file.</returns>
string CopyFile(IContentBase content, PropertyType propertyType, string sourcepath);
string CopyFile(IContentBase content, IPropertyType propertyType, string sourcepath);
}
}
+2 -2
View File
@@ -88,7 +88,7 @@ namespace Umbraco.Core.IO
#region Associated Media Files
/// <inheritoc />
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
}
/// <inheritoc />
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));
@@ -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<IDataEditor>
{
private readonly ILogger _logger;
private readonly IIOHelper _ioHelper;
private readonly IDataTypeService _dataTypeService;
private readonly ILocalizationService _localizationService;
/// <summary>
/// Initializes a new instance of the <see cref="DataEditorConverter"/> class.
/// </summary>
public DataEditorConverter(ILogger logger)
public DataEditorConverter(ILogger logger, IIOHelper ioHelper, IDataTypeService dataTypeService, ILocalizationService localizationService)
{
_logger = logger;
_ioHelper = ioHelper;
_dataTypeService = dataTypeService;
_localizationService = localizationService;
}
/// <inheritdoc />
@@ -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)
@@ -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
});
}
@@ -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<string>();
[JsonProperty("access")]
public IAccessRule[] AccessRules { get; set; } = Array.Empty<IAccessRule>();
}
}
+38 -13
View File
@@ -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
{
/// <summary>
/// Parses the Main.js file and replaces all tokens accordingly.
/// </summary>
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
/// <summary>
/// Initializes a new instance of the <see cref="ManifestParser"/> class.
/// </summary>
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;
}
/// <summary>
/// Initializes a new instance of the <see cref="ManifestParser"/> class.
/// </summary>
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;
}
/// <summary>
@@ -154,21 +166,34 @@ namespace Umbraco.Core.Manifest
/// <summary>
/// Parses a manifest.
/// </summary>
internal PackageManifest ParseManifest(string text)
public PackageManifest ParseManifest(string text)
{
if (string.IsNullOrWhiteSpace(text))
throw new ArgumentNullOrEmptyException(nameof(text));
var manifest = JsonConvert.DeserializeObject<PackageManifest>(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<GridEditor> ParseGridEditors(string text)
public IEnumerable<GridEditor> ParseGridEditors(string text)
{
return JsonConvert.DeserializeObject<IEnumerable<GridEditor>>(text);
return _jsonSerializer.Deserialize<IEnumerable<GridEditor>>(text);
}
}
}
+3 -3
View File
@@ -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<PropertyType> AllPropertyTypes { get; }
@@ -135,7 +135,7 @@ namespace Umbraco.Core.Models
/// </remarks>
[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
}
@@ -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));
+24 -24
View File
@@ -13,16 +13,16 @@ namespace Umbraco.Core.Models
/// </summary>
[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<PropertyValue> _values = new List<PropertyValue>();
private List<IPropertyValue> _values = new List<IPropertyValue>();
// _pvalue contains the invariant-neutral property value
private PropertyValue _pvalue;
private IPropertyValue _pvalue;
// _vvalues contains the (indexed) variant property values
private Dictionary<CompositeNStringNStringKey, PropertyValue> _vvalues;
private Dictionary<CompositeNStringNStringKey, IPropertyValue> _vvalues;
/// <summary>
/// Initializes a new instance of the <see cref="Property"/> class.
@@ -33,7 +33,7 @@ namespace Umbraco.Core.Models
/// <summary>
/// Initializes a new instance of the <see cref="Property"/> class.
/// </summary>
public Property(PropertyType propertyType)
public Property(IPropertyType propertyType)
{
PropertyType = propertyType;
}
@@ -41,7 +41,7 @@ namespace Umbraco.Core.Models
/// <summary>
/// Initializes a new instance of the <see cref="Property"/> class.
/// </summary>
public Property(int id, PropertyType propertyType)
public Property(int id, IPropertyType propertyType)
{
Id = id;
PropertyType = propertyType;
@@ -50,7 +50,7 @@ namespace Umbraco.Core.Models
/// <summary>
/// Represents a property value.
/// </summary>
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();
}
/// <summary>
@@ -77,23 +77,23 @@ namespace Umbraco.Core.Models
public string Segment
{
get => _segment;
internal set => _segment = value?.ToLowerInvariant();
set => _segment = value?.ToLowerInvariant();
}
/// <summary>
/// Gets or sets the edited value of the property.
/// </summary>
public object EditedValue { get; internal set; }
public object EditedValue { get; set; }
/// <summary>
/// Gets or sets the published value of the property.
/// </summary>
public object PublishedValue { get; internal set; }
public object PublishedValue { get; set; }
/// <summary>
/// Clones the property value.
/// </summary>
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
/// </summary>
[IgnoreDataMember]
public PropertyType PropertyType { get; private set; }
public IPropertyType PropertyType { get; private set; }
/// <summary>
/// Gets the list of values.
/// </summary>
[DataMember]
public IReadOnlyCollection<PropertyValue> Values
public IReadOnlyCollection<IPropertyValue> Values
{
get => _values;
set
@@ -152,7 +152,7 @@ namespace Umbraco.Core.Models
/// Returns the Id of the PropertyType, which this Property is based on
/// </summary>
[IgnoreDataMember]
internal int PropertyTypeId => PropertyType.Id;
public int PropertyTypeId => PropertyType.Id;
/// <summary>
/// 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.
/// </remarks>
[IgnoreDataMember]
internal ValueStorageType ValueStorageType => PropertyType.ValueStorageType;
public ValueStorageType ValueStorageType => PropertyType.ValueStorageType;
/// <summary>
/// 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<CompositeNStringNStringKey, PropertyValue>();
_vvalues = new Dictionary<CompositeNStringNStringKey, IPropertyValue>();
change = true;
}
var k = new CompositeNStringNStringKey(culture, segment);
+16 -32
View File
@@ -12,11 +12,9 @@ namespace Umbraco.Core.Models
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public class PropertyCollection : KeyedCollection<string, Property>, INotifyCollectionChanged, IDeepCloneable
public class PropertyCollection : KeyedCollection<string, IProperty>, IPropertyCollection
{
private readonly object _addLocker = new object();
internal Func<Property, bool> AdditionValidator { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="PropertyCollection"/> class.
@@ -25,16 +23,6 @@ namespace Umbraco.Core.Models
: base(StringComparer.InvariantCultureIgnoreCase)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="PropertyCollection"/> class.
/// </summary>
/// <param name="additionValidator">A function validating added properties.</param>
internal PropertyCollection(Func<Property, bool> additionValidator)
: this()
{
AdditionValidator = additionValidator;
}
/// <summary>
/// Initializes a new instance of the <see cref="PropertyCollection"/> class.
/// </summary>
@@ -47,7 +35,7 @@ namespace Umbraco.Core.Models
/// <summary>
/// Replaces all properties, whilst maintaining validation delegates.
/// </summary>
internal void Reset(IEnumerable<Property> properties)
private void Reset(IEnumerable<Property> properties)
{
//collection events will be raised in each of these calls
Clear();
@@ -60,7 +48,7 @@ namespace Umbraco.Core.Models
/// <summary>
/// Replaces the property at the specified index with the specified property.
/// </summary>
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
/// <summary>
/// Inserts the specified property at the specified index.
/// </summary>
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));
}
/// <summary>
/// Adds or updates a property.
/// </summary>
internal new void Add(Property property)
/// <inheritdoc />
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
/// <summary>
/// Gets the index for a specified property alias.
/// </summary>
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
/// <summary>
/// Gets the property with the specified PropertyType.
/// </summary>
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);
}
/// <summary>
/// Ensures that the collection contains properties for the specified property types.
/// </summary>
protected internal void EnsurePropertyTypes(IEnumerable<PropertyType> propertyTypes)
/// <inheritdoc />
public void EnsurePropertyTypes(IEnumerable<IPropertyType> propertyTypes)
{
if (propertyTypes == null)
return;
@@ -185,10 +170,9 @@ namespace Umbraco.Core.Models
Add(new Property(propertyType));
}
/// <summary>
/// Ensures that the collection does not contain properties not in the specified property types.
/// </summary>
protected internal void EnsureCleanPropertyTypes(IEnumerable<PropertyType> propertyTypes)
/// <inheritdoc />
public void EnsureCleanPropertyTypes(IEnumerable<IPropertyType> propertyTypes)
{
if (propertyTypes == null)
return;
@@ -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
/// <param name="tags">The tags.</param>
/// <param name="merge">A value indicating whether to merge the tags with existing tags instead of replacing them.</param>
/// <param name="culture">A culture, for multi-lingual properties.</param>
public static void AssignTags(this Property property, IEnumerable<string> tags, bool merge = false, string culture = null)
public static void AssignTags(this IProperty property, IEnumerable<string> 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<string> tags, bool merge, TagsStorageType storageType, char delimiter, string culture)
private static void AssignTags(this IProperty property, IEnumerable<string> 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
/// <param name="property">The property.</param>
/// <param name="tags">The tags.</param>
/// <param name="culture">A culture, for multi-lingual properties.</param>
public static void RemoveTags(this Property property, IEnumerable<string> tags, string culture = null)
public static void RemoveTags(this IProperty property, IEnumerable<string> 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<string> tags, TagsStorageType storageType, char delimiter, string culture)
private static void RemoveTags(this IProperty property, IEnumerable<string> 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<string> GetTagsValue(this Property property, string culture = null)
internal static IEnumerable<string> 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<string> GetTagsValue(this Property property, TagsStorageType storageType, char delimiter, string culture = null)
private static IEnumerable<string> 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
/// <para>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.</para>
/// </remarks>
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<string>();
+28 -63
View File
@@ -13,7 +13,7 @@ namespace Umbraco.Core.Models
[Serializable]
[DataContract(IsReference = true)]
[DebuggerDisplay("Id: {Id}, Name: {Name}, Alias: {Alias}")]
public class PropertyType : EntityBase, IEquatable<PropertyType>
public class PropertyType : EntityBase, IPropertyType, IEquatable<PropertyType>
{
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
/// </summary>
public PropertyType(string propertyEditorAlias, ValueStorageType valueStorageType)
: this(propertyEditorAlias, valueStorageType, false)
{ }
{
}
/// <summary>
/// Initializes a new instance of the <see cref="PropertyType"/> class.
/// </summary>
public PropertyType(string propertyEditorAlias, ValueStorageType valueStorageType, string propertyTypeAlias)
: this(propertyEditorAlias, valueStorageType, false, propertyTypeAlias)
{ }
{
}
/// <summary>
/// Initializes a new instance of the <see cref="PropertyType"/> class.
@@ -99,9 +101,7 @@ namespace Umbraco.Core.Models
/// </remarks>
public bool SupportsPublishing { get; internal set; }
/// <summary>
/// Gets of sets the name of the property type.
/// </summary>
/// <inheritdoc />
[DataMember]
public string Name
{
@@ -109,9 +109,7 @@ namespace Umbraco.Core.Models
set => SetPropertyValueAndDetectChanges(value, ref _name, nameof(Name));
}
/// <summary>
/// Gets of sets the alias of the property type.
/// </summary>
/// <inheritdoc />
[DataMember]
public virtual string Alias
{
@@ -119,9 +117,7 @@ namespace Umbraco.Core.Models
set => SetPropertyValueAndDetectChanges(SanitizeAlias(value), ref _alias, nameof(Alias));
}
/// <summary>
/// Gets of sets the description of the property type.
/// </summary>
/// <inheritdoc />
[DataMember]
public string Description
{
@@ -129,9 +125,7 @@ namespace Umbraco.Core.Models
set => SetPropertyValueAndDetectChanges(value, ref _description, nameof(Description));
}
/// <summary>
/// Gets or sets the identifier of the datatype for this property type.
/// </summary>
/// <inheritdoc />
[DataMember]
public int DataTypeId
{
@@ -146,9 +140,7 @@ namespace Umbraco.Core.Models
set => SetPropertyValueAndDetectChanges(value, ref _dataTypeKey, nameof(DataTypeKey));
}
/// <summary>
/// Gets or sets the alias of the property editor for this property type.
/// </summary>
/// <inheritdoc />
[DataMember]
public string PropertyEditorAlias
{
@@ -156,11 +148,9 @@ namespace Umbraco.Core.Models
set => SetPropertyValueAndDetectChanges(value, ref _propertyEditorAlias, nameof(PropertyEditorAlias));
}
/// <summary>
/// Gets or sets the database type for storing value for this property type.
/// </summary>
/// <inheritdoc />
[DataMember]
internal ValueStorageType ValueStorageType
public ValueStorageType ValueStorageType
{
get => _valueStorageType;
set
@@ -170,20 +160,16 @@ namespace Umbraco.Core.Models
}
}
/// <summary>
/// Gets or sets the identifier of the property group this property type belongs to.
/// </summary>
/// <remarks>For generic properties, the value is <c>null</c>.</remarks>
/// <inheritdoc />
[DataMember]
internal Lazy<int> PropertyGroupId
public Lazy<int> PropertyGroupId
{
get => _propertyGroupId;
set => SetPropertyValueAndDetectChanges(value, ref _propertyGroupId, nameof(PropertyGroupId));
}
/// <summary>
/// Gets of sets a value indicating whether a value for this property type is required.
/// </summary>
/// <inheritdoc />
[DataMember]
public bool Mandatory
{
@@ -191,9 +177,8 @@ namespace Umbraco.Core.Models
set => SetPropertyValueAndDetectChanges(value, ref _mandatory, nameof(Mandatory));
}
/// <summary>
/// Gets of sets the sort order of the property type.
/// </summary>
/// <inheritdoc />
[DataMember]
public int SortOrder
{
@@ -201,9 +186,7 @@ namespace Umbraco.Core.Models
set => SetPropertyValueAndDetectChanges(value, ref _sortOrder, nameof(SortOrder));
}
/// <summary>
/// Gets or sets the regular expression validating the property values.
/// </summary>
/// <inheritdoc />
[DataMember]
public string ValidationRegExp
{
@@ -211,21 +194,14 @@ namespace Umbraco.Core.Models
set => SetPropertyValueAndDetectChanges(value, ref _validationRegExp, nameof(ValidationRegExp));
}
/// <summary>
/// Gets or sets the content variation of the property type.
/// </summary>
/// <inheritdoc />
public ContentVariation Variations
{
get => _variations;
set => SetPropertyValueAndDetectChanges(value, ref _variations, nameof(Variations));
}
/// <summary>
/// Determines whether the property type supports a combination of culture and segment.
/// </summary>
/// <param name="culture">The culture.</param>
/// <param name="segment">The segment.</param>
/// <param name="wildcards">A value indicating whether wildcards are valid.</param>
/// <inheritdoc />
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
/// <para>If the value is of the expected type, it can be directly assigned to the property.
/// Otherwise, some conversion is required.</para>
/// </remarks>
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
}
}
/// <summary>
/// Determines whether a value can be assigned to a property.
/// </summary>
public bool IsValueAssignable(object value) => TryConvertAssignedValue(value, false, out _);
/// <summary>
/// Converts a value assigned to a property.
/// </summary>
/// <remarks>
/// <para>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).</para>
/// <para>Throws if the value cannot be converted.</para>
/// </remarks>
/// <inheritdoc />
public object ConvertAssignedValue(object value) => TryConvertAssignedValue(value, true, out var converted) ? converted : null;
/// <summary>
@@ -296,8 +260,6 @@ namespace Umbraco.Core.Models
/// <remarks>
/// <para></para>
/// </remarks>
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)
@@ -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<string> ICanBeDirty.GetDirtyProperties() => throw new NotImplementedException();
void ICanBeDirty.ResetDirtyProperties() => throw new NotImplementedException();
public void DisableChangeTracking() => throw new NotImplementedException();
public void EnableChangeTracking() => throw new NotImplementedException();
}
}
@@ -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.
/// </param>
/// <returns></returns>
public static IEnumerable<PropertyDataDto> BuildDtos(ContentVariation contentVariation, int currentVersionId, int publishedVersionId, IEnumerable<Property> properties,
public static IEnumerable<PropertyDataDto> BuildDtos(ContentVariation contentVariation, int currentVersionId, int publishedVersionId, IEnumerable<IProperty> properties,
ILanguageRepository languageRepository, out bool edited,
out HashSet<string> editedCultures)
{
@@ -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;
@@ -1,34 +0,0 @@
using System.Collections.Generic;
namespace Umbraco.Core.PropertyEditors
{
public static partial class ConfigurationFieldsExtensions
{
/// <summary>
/// Adds a configuration field.
/// </summary>
/// <param name="fields">The list of configuration fields.</param>
/// <param name="key">The key (alias) of the field.</param>
/// <param name="name">The name (label) of the field.</param>
/// <param name="description">The description for the field.</param>
/// <param name="view">The path to the editor view to be used for the field.</param>
/// <param name="config">Optional configuration used for field's editor.</param>
public static void Add(
this List<ConfigurationField> fields,
string key,
string name,
string description,
string view,
IDictionary<string, object> config = null)
{
fields.Add(new ConfigurationField
{
Key = key,
Name = name,
Description = description,
View = view,
Config = config,
});
}
}
}
@@ -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);
}
/// <summary>
@@ -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
/// </summary>
public class DataValueEditor : IDataValueEditor
{
private string _view;
protected IDataTypeService DataTypeService { get; }
protected ILocalizationService LocalizationService { get; }
/// <summary>
/// Initializes a new instance of the <see cref="DataValueEditor"/> class.
/// </summary>
public DataValueEditor() // for tests, and manifest
public DataValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService) // for tests, and manifest
{
ValueType = ValueTypes.String;
Validators = new List<IValueValidator>();
DataTypeService = dataTypeService;
LocalizationService = localizationService;
}
/// <summary>
/// Initializes a new instance of the <see cref="DataValueEditor"/> class.
/// </summary>
public DataValueEditor(string view, params IValueValidator[] validators) // not used
: this()
{
View = view;
Validators.AddRange(validators);
}
/// <summary>
/// Initializes a new instance of the <see cref="DataValueEditor"/> class.
/// </summary>
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;
}
/// <summary>
@@ -72,11 +66,7 @@ namespace Umbraco.Core.PropertyEditors
/// folder, or (3) a view name which maps to views/propertyeditors/{view}/{view}.html.</para>
/// </remarks>
[JsonProperty("view", Required = Required.Always)]
public string View
{
get => _view;
set => _view = Current.IOHelper.ResolveVirtualUrl(value);
}
public string View { get; set; }
/// <summary>
/// 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
/// </summary>
[JsonProperty("validation")]
public List<IValueValidator> Validators { get; private set; }
public List<IValueValidator> Validators { get; private set; } = new List<IValueValidator>();
/// <summary>
/// Gets the validator used to validate the special property type -level "required".
/// </summary>
public virtual IValueRequiredValidator RequiredValidator => new RequiredValidator();
public virtual IValueRequiredValidator RequiredValidator => new RequiredValidator(); //TODO: Pass in the ILocalizedTextService here and not rely on Current!
/// <summary>
/// Gets the validator used to validate the special property type -level "format".
/// </summary>
public virtual IValueFormatValidator FormatValidator => new RegexValidator();
public virtual IValueFormatValidator FormatValidator => new RegexValidator(); //TODO: Pass in the ILocalizedTextService here and not rely on Current!
/// <summary>
/// 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.
/// </remarks>
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
/// <summary>
/// Converts a property to Xml fragments.
/// </summary>
public IEnumerable<XElement> ConvertDbToXml(Property property, IDataTypeService dataTypeService, ILocalizationService localizationService, bool published)
public IEnumerable<XElement> 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
/// <para>Returns an XText or XCData instance which must be wrapped in a element.</para>
/// <para>If the value is empty we will not return as CDATA since that will just take up more space in the file.</para>
/// </remarks>
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
/// <summary>
/// Converts a property value to a string.
/// </summary>
public virtual string ConvertDbToString(PropertyType propertyType, object value, IDataTypeService dataTypeService)
public virtual string ConvertDbToString(IPropertyType propertyType, object value)
{
if (value == null)
return string.Empty;
@@ -9,7 +9,7 @@ namespace Umbraco.Core.PropertyEditors
public class DefaultPropertyIndexValueFactory : IPropertyIndexValueFactory
{
/// <inheritdoc />
public IEnumerable<KeyValuePair<string, IEnumerable<object>>> GetIndexValues(Property property, string culture, string segment, bool published)
public IEnumerable<KeyValuePair<string, IEnumerable<object>>> GetIndexValues(IProperty property, string culture, string segment, bool published)
{
yield return new KeyValuePair<string, IEnumerable<object>>(
property.Alias,
@@ -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
{ }
/// <inheritdoc />
protected override IDataValueEditor CreateValueEditor() => new LabelPropertyValueEditor(Attribute);
protected override IDataValueEditor CreateValueEditor() => new LabelPropertyValueEditor(Current.Services.DataTypeService, Current.Services.LocalizationService, Attribute);
/// <inheritdoc />
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)
{ }
/// <inheritdoc />
@@ -1,9 +0,0 @@
using Umbraco.Core.Composing;
namespace Umbraco.Core.PropertyEditors
{
internal class ManifestValueValidatorCollectionBuilder : LazyCollectionBuilderBase<ManifestValueValidatorCollectionBuilder, ManifestValueValidatorCollection, IManifestValueValidator>
{
protected override ManifestValueValidatorCollectionBuilder This => this;
}
}
@@ -11,11 +11,13 @@ namespace Umbraco.Core.PropertyEditors.Validators
/// <summary>
/// A validator that validates that the value against a regular expression.
/// </summary>
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";
/// <inheritdoc cref="IManifestValueValidator.ValidationName"/>
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 <see cref="IManifestValueValidator"/> and the regular expression
/// is supplied via the <see cref="Configuration"/> method.</remarks>
public RegexValidator() : this(Current.Services.TextService, null)
public RegexValidator() : this(Current.HasFactory ? Current.Services.TextService : null, null)
{ }
/// <summary>
@@ -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" });
}
}
}
}
@@ -8,11 +8,13 @@ namespace Umbraco.Core.PropertyEditors.Validators
/// <summary>
/// A validator that validates that the value is not null or empty (if it is a string)
/// </summary>
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" });
}
}
}
@@ -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)
{
@@ -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<XElement> SerializeProperty(Property property, bool published)
private IEnumerable<XElement> 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<XElement>()
: propertyEditor.GetValueEditor().ConvertDbToXml(property, _dataTypeService, _localizationService, published);
: propertyEditor.GetValueEditor().ConvertDbToXml(property, published);
}
// exports an IContent item descendants.
@@ -31,7 +31,7 @@ namespace Umbraco.Core.Services
/// <summary>
/// Validates the content item's properties pass validation rules
/// </summary>
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
/// <summary>
/// Gets a value indicating whether the property has valid values.
/// </summary>
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
/// <param name="property"></param>
/// <param name="value"></param>
/// <returns>True is property value is valid, otherwise false</returns>
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
/// <summary>
/// Determines whether a value is valid for this property type.
/// </summary>
private bool IsPropertyValueValid(PropertyType propertyType, object value)
private bool IsPropertyValueValid(IPropertyType propertyType, object value)
{
var editor = _propertyEditors[propertyType.PropertyEditorAlias];
if (editor == null)
+1 -1
View File
@@ -32,6 +32,6 @@ namespace Umbraco.Core.Services
/// <summary>
/// Gets or sets the invalid properties, if the status failed due to validation.
/// </summary>
public IEnumerable<Property> InvalidProperties { get; set; }
public IEnumerable<IProperty> InvalidProperties { get; set; }
}
}
+12 -40
View File
@@ -36,7 +36,6 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Configuration" />
<Reference Include="System.Data.Entity" />
<Reference Include="System.IO.Compression" />
@@ -65,11 +64,14 @@
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Serilog.Sinks.Async">
<Version>1.3.0</Version>
<Version>1.4.0</Version>
</PackageReference>
<PackageReference Include="Serilog.Sinks.Map">
<Version>1.0.0</Version>
</PackageReference>
<PackageReference Include="System.ComponentModel.Annotations">
<Version>4.6.0</Version>
</PackageReference>
<PackageReference Include="Umbraco.Code">
<Version>1.0.5</Version>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
@@ -91,19 +93,19 @@
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
<PackageReference Include="NPoco" Version="3.9.4" />
<PackageReference Include="Serilog">
<Version>2.8.0</Version>
<Version>2.9.0</Version>
</PackageReference>
<PackageReference Include="Serilog.Enrichers.Process">
<Version>2.0.1</Version>
</PackageReference>
<PackageReference Include="Serilog.Enrichers.Thread">
<Version>3.0.0</Version>
<Version>3.1.0</Version>
</PackageReference>
<PackageReference Include="Serilog.Filters.Expressions">
<Version>2.0.0</Version>
</PackageReference>
<PackageReference Include="Serilog.Formatting.Compact">
<Version>1.0.0</Version>
<Version>1.1.0</Version>
</PackageReference>
<PackageReference Include="Serilog.Formatting.Compact.Reader">
<Version>1.0.3</Version>
@@ -112,7 +114,7 @@
<Version>2.2.2</Version>
</PackageReference>
<PackageReference Include="Serilog.Sinks.File">
<Version>4.0.0</Version>
<Version>4.1.0</Version>
</PackageReference>
<PackageReference Include="Umbraco.SqlServerCE" Version="4.0.0.1" />
</ItemGroup>
@@ -182,9 +184,7 @@
<Compile Include="IO\IOHelper.cs" />
<Compile Include="IO\MediaPathSchemes\UniqueMediaPathScheme.cs" />
<Compile Include="Logging\Viewer\LogTimePeriod.cs" />
<Compile Include="Manifest\IManifestFilter.cs" />
<Compile Include="Manifest\ManifestFilterCollection.cs" />
<Compile Include="Manifest\ManifestFilterCollectionBuilder.cs" />
<Compile Include="Manifest\ManifestParser.cs" />
<Compile Include="Migrations\IMigrationBuilder.cs" />
<Compile Include="Migrations\Upgrade\Common\DeleteKeysAndIndexes.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\DataTypes\ContentPickerPreValueMigrator.cs" />
@@ -218,16 +218,12 @@
<Compile Include="Migrations\Upgrade\V_8_0_1\ChangeNuCacheJsonFormat.cs" />
<Compile Include="Migrations\Upgrade\V_8_1_0\ConvertTinyMceAndGridMediaUrlsToLocalLink.cs" />
<Compile Include="Models\ContentBaseExtensions.cs" />
<Compile Include="Models\IContent.cs" />
<Compile Include="Models\IContentBase.cs" />
<Compile Include="Models\IContentType.cs" />
<Compile Include="Models\IContentTypeBase.cs" />
<Compile Include="Models\IContentTypeComposition.cs" />
<Compile Include="Models\IDataType.cs" />
<Compile Include="Models\IDataValueEditor.cs" />
<Compile Include="Models\Identity\IdentityMapDefinition.cs" />
<Compile Include="Models\Identity\UserLoginInfoWrapper.cs" />
<Compile Include="Models\IMedia.cs" />
<Compile Include="Models\IMediaType.cs" />
<Compile Include="Models\IMember.cs" />
<Compile Include="Models\IMemberType.cs" />
@@ -262,8 +258,10 @@
<Compile Include="Models\TemplateOnDisk.cs" />
<Compile Include="Models\PublishedContent\IPublishedContentType.cs" />
<Compile Include="Models\PublishedContent\IPublishedPropertyType.cs" />
<Compile Include="PropertyEditors\ConfigurationFieldsExtensions.cs" />
<Compile Include="PropertyEditors\IIgnoreUserStartNodesConfig.cs" />
<Compile Include="PropertyEditors\Validators\DelimitedValueValidator.cs" />
<Compile Include="PropertyEditors\Validators\RegexValidator.cs" />
<Compile Include="PropertyEditors\Validators\RequiredValidator.cs" />
<Compile Include="PublishedContentExtensions.cs" />
<Compile Include="Models\PublishedContent\UrlMode.cs" />
<Compile Include="Persistence\Dtos\PropertyTypeCommonDto.cs" />
@@ -271,14 +269,9 @@
<Compile Include="Persistence\Repositories\Implement\ContentTypeCommonRepository.cs" />
<Compile Include="Persistence\Repositories\IContentTypeCommonRepository.cs" />
<Compile Include="Persistence\Repositories\Implement\LanguageRepositoryExtensions.cs" />
<Compile Include="PropertyEditors\ConfigurationField.cs" />
<Compile Include="PropertyEditors\ConfigurationFieldAttribute.cs" />
<Compile Include="PropertyEditors\DataEditorAttribute.cs" />
<Compile Include="PropertyEditors\DateTimeConfiguration.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\RenameLabelAndRichTextPropertyEditorAliases.cs" />
<Compile Include="PropertyEditors\IDataEditor.cs" />
<Compile Include="PropertyEditors\IPropertyIndexValueFactory.cs" />
<Compile Include="PropertyEditors\IValueValidator.cs" />
<Compile Include="PropertyEditors\PropertyValueConverterCollection.cs" />
<Compile Include="PropertyEditors\PropertyValueConverterCollectionBuilder.cs" />
<Compile Include="PropertyEditors\VoidEditor.cs" />
@@ -380,10 +373,7 @@
<Compile Include="Logging\Viewer\MessageTemplateFilter.cs" />
<Compile Include="Logging\Viewer\SavedLogSearch.cs" />
<Compile Include="Manifest\DashboardAccessRuleConverter.cs" />
<Compile Include="Manifest\ManifestSection.cs" />
<Compile Include="Manifest\ManifestContentAppDefinition.cs" />
<Compile Include="Manifest\ManifestContentAppFactory.cs" />
<Compile Include="Manifest\ManifestDashboard.cs" />
<Compile Include="Migrations\MergeBuilder.cs" />
<Compile Include="Migrations\MigrationBase_Extra.cs" />
<Compile Include="Migrations\PostMigrations\IPublishedSnapshotRebuilder.cs" />
@@ -419,9 +409,6 @@
<Compile Include="Migrations\Upgrade\V_8_0_0\UserForeignKeys.cs" />
<Compile Include="Migrations\Upgrade\Common\CreateKeysAndIndexes.cs" />
<Compile Include="Models\ContentRepositoryExtensions.cs" />
<Compile Include="Models\ContentSchedule.cs" />
<Compile Include="Models\ContentScheduleAction.cs" />
<Compile Include="Models\ContentScheduleCollection.cs" />
<Compile Include="Models\ContentTagsExtensions.cs" />
<Compile Include="Models\ContentTypeBaseExtensions.cs" />
<Compile Include="Models\DataTypeExtensions.cs" />
@@ -470,11 +457,7 @@
<Compile Include="PropertyEditors\ConfigurationEditor.cs" />
<Compile Include="PropertyEditors\DefaultPropertyIndexValueFactory.cs" />
<Compile Include="PropertyEditors\DropDownFlexibleConfiguration.cs" />
<Compile Include="PropertyEditors\IConfigurationEditor.cs" />
<Compile Include="PropertyEditors\ImageCropperConfiguration.cs" />
<Compile Include="PropertyEditors\IManifestValueValidator.cs" />
<Compile Include="PropertyEditors\IValueFormatValidator.cs" />
<Compile Include="PropertyEditors\IValueRequiredValidator.cs" />
<Compile Include="PropertyEditors\LabelConfiguration.cs" />
<Compile Include="PropertyEditors\LabelConfigurationEditor.cs" />
<Compile Include="PropertyEditors\LabelPropertyEditor.cs" />
@@ -548,10 +531,8 @@
<Compile Include="Logging\OwinLoggerFactory.cs" />
<Compile Include="Logging\VoidProfiler.cs" />
<Compile Include="MainDom.cs" />
<Compile Include="Manifest\ManifestParser.cs" />
<Compile Include="Manifest\ValueValidatorConverter.cs" />
<Compile Include="Manifest\ManifestWatcher.cs" />
<Compile Include="Manifest\PackageManifest.cs" />
<Compile Include="Manifest\DataEditorConverter.cs" />
<Compile Include="Migrations\MigrationBuilder.cs" />
<Compile Include="Migrations\MigrationPlan.cs" />
@@ -957,22 +938,13 @@
<Compile Include="Persistence\UmbracoDatabaseExtensions.cs" />
<Compile Include="Persistence\UmbracoDatabaseFactory.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PropertyEditors\Validators\DecimalValidator.cs" />
<Compile Include="PropertyEditors\DefaultPropertyValueConverterAttribute.cs" />
<Compile Include="PropertyEditors\Validators\DelimitedValueValidator.cs" />
<Compile Include="PropertyEditors\Validators\EmailValidator.cs" />
<Compile Include="PropertyEditors\GridEditor.cs" />
<Compile Include="PropertyEditors\Validators\IntegerValidator.cs" />
<Compile Include="PropertyEditors\IPropertyValueConverter.cs" />
<Compile Include="PropertyEditors\DataEditor.cs" />
<Compile Include="PropertyEditors\DataEditorCollection.cs" />
<Compile Include="PropertyEditors\DataEditorCollectionBuilder.cs" />
<Compile Include="PropertyEditors\PropertyValueConverterBase.cs" />
<Compile Include="PropertyEditors\DataValueEditor.cs" />
<Compile Include="PropertyEditors\Validators\RegexValidator.cs" />
<Compile Include="PropertyEditors\Validators\RequiredValidator.cs" />
<Compile Include="PropertyEditors\ManifestValueValidatorCollection.cs" />
<Compile Include="PropertyEditors\ManifestValueValidatorCollectionBuilder.cs" />
<Compile Include="PropertyEditors\ValueConverters\CheckboxListValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\ColorPickerValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\DatePickerValueConverter.cs" />
+2 -2
View File
@@ -24,7 +24,7 @@ namespace Umbraco.Examine
/// <inheritdoc />
public abstract IEnumerable<ValueSet> GetValueSets(params TContent[] content);
protected void AddPropertyValue(Property property, string culture, string segment, IDictionary<string, IEnumerable<object>> values)
protected void AddPropertyValue(IProperty property, string culture, string segment, IDictionary<string, IEnumerable<object>> 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;
}
}
@@ -34,7 +34,6 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Web" />
@@ -97,6 +96,9 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="System.ComponentModel.Annotations">
<Version>4.6.0</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Umbraco.Abstractions\Umbraco.Abstractions.csproj">
+4
View File
@@ -94,6 +94,10 @@
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.ComponentModel.Annotations" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.1.0" newVersion="4.2.1.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
@@ -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);
@@ -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<ManifestContentAppDefinition>("{" + (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);
@@ -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<IFactory>();
Current.Factory = factory;
var serviceContext = ServiceContext.CreatePartial(
localizedTextService: Mock.Of<ILocalizedTextService>());
Mock.Get(factory)
.Setup(x => x.GetInstance(It.IsAny<Type>()))
.Returns<Type>(x =>
{
if (x == typeof(ServiceContext)) return serviceContext;
throw new Exception("oops");
});
var validators = new IManifestValueValidator[]
{
new RequiredValidator(Mock.Of<ILocalizedTextService>()),
new RegexValidator(Mock.Of<ILocalizedTextService>(), null)
};
_parser = new ManifestParser(AppCaches.Disabled, new ManifestValueValidatorCollection(validators), new ManifestFilterCollection(Array.Empty<IManifestFilter>()), Mock.Of<ILogger>());
_parser = new ManifestParser(AppCaches.Disabled, new ManifestValueValidatorCollection(validators), new ManifestFilterCollection(Array.Empty<IManifestFilter>()), Mock.Of<ILogger>(), IOHelper.Default, Mock.Of<IDataTypeService>(), Mock.Of<ILocalizationService>(), new JsonNetSerializer());
}
[Test]
+2 -2
View File
@@ -285,10 +285,10 @@ namespace Umbraco.Tests.Mapping
{
public void DefineMaps(UmbracoMapper mapper)
{
mapper.Define<Property, ContentPropertyDto>((source, context) => new ContentPropertyDto(), Map);
mapper.Define<IProperty, ContentPropertyDto>((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)
{ }
}
+27 -25
View File
@@ -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;
}
/// <summary>
@@ -93,12 +85,12 @@ namespace Umbraco.Tests.Models.Collections
/// <param name="propertyInfo">The property info.</param>
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
/// </summary>
//private readonly IDictionary<string, bool> _propertyChangedInfo = new Dictionary<string, bool>();
private IDictionary<string, bool> _propertyChangedInfo;
private readonly IDictionary<string, bool> _propertyChangedInfo;
/// <summary>
/// Indicates whether a specific property on the current entity is dirty.
@@ -166,19 +158,29 @@ namespace Umbraco.Tests.Models.Collections
_propertyChangedInfo.Clear();
}
/// <summary>
/// Disables change tracking.
/// </summary>
public void DisableChangeTracking()
{
_withChanges = false;
}
/// <summary>
/// Enables change tracking.
/// </summary>
public void EnableChangeTracking()
{
_withChanges = true;
}
/// <summary>
/// Indicates whether the current entity has an identity, eg. Id.
/// </summary>
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)
@@ -32,7 +32,7 @@ namespace Umbraco.Tests.Models
Composition.Register(_ => Mock.Of<IContentSection>());
// all this is required so we can validate properties...
var editor = new TextboxPropertyEditor(Mock.Of<ILogger>()) { Alias = "test" };
var editor = new TextboxPropertyEditor(Mock.Of<ILogger>(), Mock.Of<IDataTypeService>(), Mock.Of<ILocalizationService>()) { Alias = "test" };
Composition.Register(_ => new DataEditorCollection(new[] { editor }));
Composition.Register<PropertyEditorCollection>();
var dataType = Mock.Of<IDataType>();
+2 -2
View File
@@ -43,7 +43,7 @@ namespace Umbraco.Tests.Models
Composition.Register(_ => Mock.Of<IContentSection>());
// all this is required so we can validate properties...
var editor = new TextboxPropertyEditor(Mock.Of<ILogger>()) { Alias = "test" };
var editor = new TextboxPropertyEditor(Mock.Of<ILogger>(), Mock.Of<IDataTypeService>(), Mock.Of<ILocalizationService>()) { Alias = "test" };
Composition.Register(_ => new DataEditorCollection(new [] { editor }));
Composition.Register<PropertyEditorCollection>();
var dataType = Mock.Of<IDataType>();
@@ -57,7 +57,7 @@ namespace Umbraco.Tests.Models
var mediaTypeService = Mock.Of<IMediaTypeService>();
var memberTypeService = Mock.Of<IMemberTypeService>();
Composition.Register(_ => ServiceContext.CreatePartial(dataTypeService: dataTypeService, contentTypeBaseServiceProvider: new ContentTypeBaseServiceProvider(_contentTypeService, mediaTypeService, memberTypeService)));
}
[Test]
@@ -24,6 +24,7 @@ namespace Umbraco.Tests.Models.Mapping
private readonly Mock<IDataTypeService> _dataTypeService = new Mock<IDataTypeService>();
private readonly Mock<IEntityService> _entityService = new Mock<IEntityService>();
private readonly Mock<IFileService> _fileService = new Mock<IFileService>();
private readonly Mock<ILocalizationService> _localizationService = new Mock<ILocalizationService>();
private Mock<PropertyEditorCollection> _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<ILogger>()), };
var editors = new DataEditor[] { new TextboxPropertyEditor(Mock.Of<ILogger>(), _dataTypeService.Object, _localizationService.Object), };
var dataEditors = new DataEditorCollection(editors);
_editorsMock = new Mock<PropertyEditorCollection>(dataEditors);
_editorsMock.Setup(x => x[It.IsAny<string>()]).Returns(editors[0]);
@@ -40,7 +40,7 @@ namespace Umbraco.Tests.Models.Mapping
Composition.Register(_ => Mock.Of<IContentSection>());
// all this is required so we can validate properties...
var editor = new TextboxPropertyEditor(Mock.Of<ILogger>()) { Alias = "test" };
var editor = new TextboxPropertyEditor(Mock.Of<ILogger>(), Mock.Of<IDataTypeService>(), Mock.Of<ILocalizationService>()) { Alias = "test" };
Composition.Register(_ => new DataEditorCollection(new[] { editor }));
Composition.Register<PropertyEditorCollection>();
var dataType = Mock.Of<IDataType>();
@@ -261,7 +261,7 @@ namespace Umbraco.Tests.Models.Mapping
#region Assertions
private void AssertDisplayProperty<T>(IContentProperties<T> result, Property p)
private void AssertDisplayProperty<T>(IContentProperties<T> 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<T>(IContentProperties<T> result, Property p)
private void AssertBasicProperty<T>(IContentProperties<T> 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<ContentPropertyDto> result, Property p)
private void AssertProperty(IContentProperties<ContentPropertyDto> result, IProperty p)
{
AssertBasicProperty(result, p);
+3 -1
View File
@@ -33,9 +33,11 @@ namespace Umbraco.Tests.Models
var logger = Mock.Of<ILogger>();
var scheme = Mock.Of<IMediaPathScheme>();
var config = Mock.Of<IContentSection>();
var dataTypeService = Mock.Of<IDataTypeService>();
var localizationService = Mock.Of<ILocalizationService>();
var mediaFileSystem = new MediaFileSystem(Mock.Of<IFileSystem>(), config, scheme, logger);
var ignored = new FileUploadPropertyEditor(Mock.Of<ILogger>(), mediaFileSystem, config);
var ignored = new FileUploadPropertyEditor(Mock.Of<ILogger>(), 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
@@ -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<int>))
{
expected = ((Lazy<int>) expected).Value;
actual = ((Lazy<int>) actual).Value;
}
Assert.AreEqual(expected, actual, $"Value of propery: '{propertyInfo.Name}': {expected} != {actual}");
}
}
+8 -5
View File
@@ -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<IFactory>();
Current.Factory = factory;
var dataTypeService = Mock.Of<IDataTypeService>();
var localizationService = Mock.Of<ILocalizationService>();
var dataEditors = new DataEditorCollection(new IDataEditor[]
{
new DataEditor(Mock.Of<ILogger>()) { Alias = "editor", ExplicitValueEditor = new DataValueEditor("view") }
new DataEditor(Mock.Of<ILogger>()) { 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<IDataTypeService>();
Mock.Get(dataTypeService)
.Setup(x => x.GetDataType(It.IsAny<int>()))
.Returns<int>(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
}
/// <summary>
/// Asserts the result of <see cref="ContentVariationExtensions.ValidateVariation(ContentVariation, string, string, bool, bool, bool)"/>
/// Asserts the result of <see cref="ContentVariationExtensions.ValidateVariation(ContentVariation, string, string, bool, bool, bool)"/>
/// </summary>
/// <param name="variation"></param>
/// <param name="culture"></param>
@@ -83,7 +83,7 @@ namespace Umbraco.Tests.PropertyEditors
var mediaFileSystem = new MediaFileSystem(Mock.Of<IFileSystem>(), config, scheme, logger);
var dataTypeService = new TestObjects.TestDataTypeService(
new DataType(new ImageCropperPropertyEditor(Mock.Of<ILogger>(), mediaFileSystem, Mock.Of<IContentSection>(), Mock.Of<IDataTypeService>())) { Id = 1 });
new DataType(new ImageCropperPropertyEditor(Mock.Of<ILogger>(), mediaFileSystem, Mock.Of<IContentSection>(), Mock.Of<IDataTypeService>(), Mock.Of<ILocalizationService>())) { Id = 1 });
var factory = new PublishedContentTypeFactory(Mock.Of<IPublishedModelFactory>(), new PropertyValueConverterCollection(Array.Empty<IPropertyValueConverter>()), dataTypeService);
@@ -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.
/// </remarks>
[TestFixture]
public class MultiValuePropertyEditorTests
public class MultiValuePropertyEditorTests
{
[Test]
public void DropDownMultipleValueEditor_Format_Data_For_Cache()
{
var dataType = new DataType(new CheckBoxListPropertyEditor(Mock.Of<ILogger>(), Mock.Of<ILocalizedTextService>()))
var dataType = new DataType(new CheckBoxListPropertyEditor(Mock.Of<ILogger>(), Mock.Of<ILocalizedTextService>(), Mock.Of<IDataTypeService>(), Mock.Of<ILocalizationService>()))
{
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<ILogger>(), Mock.Of<ILocalizedTextService>()))
var dataType = new DataType(new CheckBoxListPropertyEditor(Mock.Of<ILogger>(), Mock.Of<ILocalizedTextService>(), Mock.Of<IDataTypeService>(), Mock.Of<ILocalizationService>()))
{
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);
}
@@ -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<IDataTypeService>().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<IDataTypeService>().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<IDataTypeService>().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<IDataTypeService>().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<IDataTypeService>().Object);
var result = valueEditor.ToEditor(prop);
Assert.AreEqual(now.ToIsoString(), result);
}
}
@@ -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<ILogger>();
var profiler = Mock.Of<IProfiler>();
var proflog = new ProfilingLogger(logger, profiler);
var localizationService = Mock.Of<ILocalizationService>();
PropertyEditorCollection editors = null;
var editor = new NestedContentPropertyEditor(logger, new Lazy<PropertyEditorCollection>(() => editors));
var editor = new NestedContentPropertyEditor(logger, new Lazy<PropertyEditorCollection>(() => editors), Mock.Of<IDataTypeService>(), 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<IDataTypeService>(), localizationService))
{
Id = 3
};
@@ -40,7 +40,13 @@ namespace Umbraco.Tests.PublishedContent
var converters = Factory.GetInstance<PropertyValueConverterCollection>();
var dataTypeService = new TestObjects.TestDataTypeService(
new DataType(new RichTextPropertyEditor(Mock.Of<ILogger>(), Mock.Of<IMediaService>(), Mock.Of<IContentTypeBaseServiceProvider>(), Mock.Of<IUmbracoContextAccessor>())) { Id = 1 });
new DataType(new RichTextPropertyEditor(
Mock.Of<ILogger>(),
Mock.Of<IMediaService>(),
Mock.Of<IContentTypeBaseServiceProvider>(),
Mock.Of<IUmbracoContextAccessor>(),
Mock.Of<IDataTypeService>(),
Mock.Of<ILocalizationService>())) { Id = 1 });
var publishedContentTypeFactory = new PublishedContentTypeFactory(Mock.Of<IPublishedModelFactory>(), converters, dataTypeService);
@@ -47,13 +47,14 @@ namespace Umbraco.Tests.PublishedContent
var mediaService = Mock.Of<IMediaService>();
var contentTypeBaseServiceProvider = Mock.Of<IContentTypeBaseServiceProvider>();
var umbracoContextAccessor = Mock.Of<IUmbracoContextAccessor>();
var localizationService = Mock.Of<ILocalizationService>();
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<IDataTypeService>(), localizationService)) { Id = 1002 },
new DataType(new IntegerPropertyEditor(logger)) { Id = 1003 },
new DataType(new TextboxPropertyEditor(logger)) { Id = 1004 },
new DataType(new TextboxPropertyEditor(logger, Mock.Of<IDataTypeService>(), localizationService)) { Id = 1004 },
new DataType(new MediaPickerPropertyEditor(logger)) { Id = 1005 });
Composition.RegisterUnique<IDataTypeService>(f => dataTypeService);
}
@@ -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<object>()))
.Returns(new CustomTextOnlyValueEditor(new DataEditorAttribute(Constants.PropertyEditors.Aliases.TextBox, "Test Textbox", "textbox"), textService.Object));
.Returns(new CustomTextOnlyValueEditor(Mock.Of<IDataTypeService>(), Mock.Of<ILocalizationService>(), 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;
}
@@ -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<IDataTypeService>(),
Mock.Of<ILocalizationService>(),
new DataEditorAttribute(name, name, name)
{
ValueType = valueType
}
);
}
}
}
+1 -1
View File
@@ -56,7 +56,6 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Data.Entity.Design" />
@@ -107,6 +106,7 @@
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
<PackageReference Include="Owin" Version="1.0" />
<PackageReference Include="Selenium.WebDriver" Version="3.141.0" />
<PackageReference Include="System.ComponentModel.Annotations" Version="4.6.0" />
<PackageReference Include="Umbraco.SqlServerCE" Version="4.0.0.1" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.2" />
</ItemGroup>
+2 -2
View File
@@ -70,7 +70,6 @@
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Web" />
<Reference Include="System.Web.Abstractions" />
<Reference Include="System.Web.ApplicationServices" />
@@ -110,6 +109,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="System.ComponentModel.Annotations" Version="4.6.0" />
<PackageReference Include="Umbraco.SqlServerCE" Version="4.0.0.1" />
</ItemGroup>
<ItemGroup>
@@ -432,4 +432,4 @@
<Message Text="ConfigFile: $(OriginalFileName) -&gt; $(OutputFileName)" Importance="high" Condition="Exists('$(ModifiedFileName)')" />
<Copy SourceFiles="$(ModifiedFileName)" DestinationFiles="$(OutputFileName)" OverwriteReadOnlyFiles="true" SkipUnchangedFiles="false" Condition="Exists('$(ModifiedFileName)')" />
</Target>
</Project>
</Project>
@@ -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<ManifestParser>();
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)));
}
}
}
+1 -1
View File
@@ -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;
@@ -50,8 +50,8 @@ namespace Umbraco.Web.Editors
internal void MapPropertyValuesForPersistence<TPersisted, TSaved>(
TSaved contentItem,
ContentPropertyCollectionDto dto,
Func<TSaved, Property, object> getPropertyValue,
Action<TSaved, Property, object> savePropertyValue,
Func<TSaved, IProperty, object> getPropertyValue,
Action<TSaved, IProperty, object> savePropertyValue,
string culture)
where TPersisted : IContentBase
where TSaved : IContentSave<TPersisted>
@@ -46,7 +46,7 @@ namespace Umbraco.Web.Editors.Filters
protected ContentModelValidator(ILogger logger, IUmbracoContextAccessor umbracoContextAccessor) : base(logger, umbracoContextAccessor)
{
}
/// <summary>
/// Ensure the content exists
/// </summary>
@@ -85,7 +85,7 @@ namespace Umbraco.Web.Editors.Filters
/// <param name="persistedProperties"></param>
/// <param name="actionContext"></param>
/// <returns></returns>
protected bool ValidateProperties(List<ContentPropertyBasic> postedProperties, List<Property> persistedProperties, HttpActionContext actionContext)
protected bool ValidateProperties(List<ContentPropertyBasic> postedProperties, List<IProperty> 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;
@@ -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();
@@ -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<Property, ContentPropertyDto>(source.Properties);
target.Properties = context.MapEnumerable<IProperty, ContentPropertyDto>(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<Property, ContentPropertyDto>(source.Properties);
target.ContentDto.Properties = context.MapEnumerable<IProperty, ContentPropertyDto>(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<Property, ContentPropertyBasic>(source.Properties);
target.Properties = context.MapEnumerable<IProperty, ContentPropertyBasic>(source.Properties);
target.SortOrder = source.SortOrder;
target.State = _basicStateMapper.Map(source, context);
target.Trashed = source.Trashed;

Some files were not shown because too many files have changed in this diff Show More