Cleanup editing

This commit is contained in:
Stephan
2018-02-14 16:55:42 +01:00
parent af7df0c6b5
commit d30842e1bf
40 changed files with 179 additions and 87 deletions

View File

@@ -20,15 +20,24 @@ namespace Umbraco.Core.Manifest
/// <inheritdoc />
protected override void Deserialize(JObject jobject, ParameterEditor target, JsonSerializer serializer)
{
// in a manifest, a parameter editor looks like:
//
// {
// "alias": "...",
// "name": "...",
// "view": "...",
// "config": { "key1": "value1", "key2": "value2" ... }
// }
//
// the view is at top level, but should be down one level to be propertly
// deserialized as a ParameterValueEditor property -> need to move it
if (jobject.Property("view") != null)
{
// the deserializer will first try to get the property, and that would throw since
// the editor would try to create a new value editor, so we have to set a
// value editor by ourselves, which will then be populated by the deserializer.
// explicitely assign a value editor of type ParameterValueEditor
target.ValueEditor = new ParameterValueEditor();
// the 'view' property in the manifest is at top-level, and needs to be moved
// down one level to the actual value editor.
// move the 'view' property
jobject["editor"] = new JObject { ["view"] = jobject["view"] };
jobject.Property("view").Remove();
}

View File

@@ -33,9 +33,9 @@ namespace Umbraco.Core.Manifest
{
if (jobject["editor"] != null)
{
// the deserializer will first try to get the property, and that would throw since
// the editor would try to create a new value editor, so we have to set a
// value editor by ourselves, which will then be populated by the deserializer.
// explicitely 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.ValueEditor = new ValueEditor();
// in the manifest, validators are a simple dictionary eg
@@ -49,14 +49,29 @@ namespace Umbraco.Core.Manifest
jobject["editor"]["validation"] = RewriteValidators(validation);
}
// see note about validators, above - same applies to field validators
if (jobject["prevalues"]?["fields"] is JArray jarray)
if (jobject["prevalues"] is JObject prevalues)
{
foreach (var field in jarray)
// explicitely assign a configuration editor of type ConfigurationEditor
// (else the deserializer will try to read it before setting it)
// (and besides it's an interface)
target.ConfigurationEditor = new ConfigurationEditor();
// see note about validators, above - same applies to field validators
if (jobject["prevalues"]?["fields"] is JArray jarray)
{
// see note above, for editor
if (field["validation"] is JObject validation)
field["validation"] = RewriteValidators(validation);
foreach (var field in jarray)
{
if (field["validation"] is JObject validation)
field["validation"] = RewriteValidators(validation);
}
}
// in the manifest, default configuration is at editor level
// move it down to configuration editor level so it can be deserialized properly
if (jobject["defaultConfig"] is JObject defaultConfig)
{
prevalues["defaultConfig"] = defaultConfig;
jobject.Remove("defaultConfig");
}
}

View File

@@ -102,7 +102,7 @@ namespace Umbraco.Core.Models.PublishedContent
_publishedDataTypes.Remove(id);
var dataTypes = _dataTypeService.GetAll(ids);
foreach (var dataType in dataTypes)
_publishedDataTypes[dataType.Id] = new PublishedDataType(dataType.Id, dataType.EditorAlias, dataType is DataType d ? d.GetLazyConfiguration() : new Lazy<object>(() => dataType.Configuration)));
_publishedDataTypes[dataType.Id] = new PublishedDataType(dataType.Id, dataType.EditorAlias, dataType is DataType d ? d.GetLazyConfiguration() : new Lazy<object>(() => dataType.Configuration));
}
}
}

View File

@@ -53,7 +53,10 @@ namespace Umbraco.Core.PropertyEditors
/// <summary>
/// Gets the default configuration.
/// </summary>
/// <remarks>The default configuration is used to initialize new datatypes.</remarks>
/// <remarks>
/// <para>The default configuration is used to initialize new datatypes.</para>
/// </remarks>
[JsonProperty("defaultConfig")]
public virtual IDictionary<string, object> DefaultConfiguration => new Dictionary<string, object>();
/// <summary>

View File

@@ -1,4 +1,10 @@
namespace Umbraco.Core.PropertyEditors
using System.Collections.Generic;
using System.Xml.Linq;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Editors;
using Umbraco.Core.Services;
namespace Umbraco.Core.PropertyEditors
{
/// <summary>
/// Represents an editor for editing values.
@@ -9,5 +15,31 @@
/// Gets the editor view.
/// </summary>
string View { get; }
/// <summary>
/// Gets the type of the value.
/// </summary>
/// <remarks>The value has to be a valid <see cref="ValueTypes"/> value.</remarks>
string ValueType { get; set; }
}
// fixme
public interface IPropertyValueEditor : IValueEditor
{
// fixme services should be injected!
object ConvertEditorToDb(ContentPropertyData editorValue, object currentValue);
object ConvertDbToEditor(Property property, PropertyType propertyType, IDataTypeService dataTypeService);
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);
List<IValueValidator> Validators { get; }
bool IsReadOnly { get; }
bool HideLabel { get; }
// fixme what are these?
ManifestValidator RequiredValidator { get; }
ManifestValidator RegexValidator { get; }
}
}

View File

@@ -53,6 +53,19 @@ namespace Umbraco.Core.PropertyEditors
[JsonProperty("config")]
public IDictionary<string, object> Configuration { get; set; }
/// <summary>
/// Gets or sets the value editor.
/// </summary>
/// <remarks>
/// <para>If an instance of a value editor is assigned to the property,
/// then this instance is returned when getting the property value. Otherwise, a
/// new instance is created by CreateValueEditor.</para>
/// <para>The instance created by CreateValueEditor is not cached, i.e.
/// a new instance is created each time the property value is retrieved.</para>
/// <para>The property is marked as a Json property with ObjectCreationHandling
/// set to Replace in order to prevent the Json deserializer to retrieve the
/// value of the property before setting it.</para>
/// </remarks>
[JsonProperty("editor")]
public ParameterValueEditor ValueEditor
{

View File

@@ -34,5 +34,8 @@ namespace Umbraco.Core.PropertyEditors
get => _view;
set => _view = IOHelper.ResolveVirtualUrl(value);
}
/// <inheritdoc />
public string ValueType { get; set; }
}
}

View File

@@ -17,7 +17,7 @@ namespace Umbraco.Core.PropertyEditors
[DebuggerDisplay("{" + nameof(DebuggerDisplay) + "(),nq}")]
public class PropertyEditor : IParameterEditor
{
private ValueEditor _valueEditorAssigned;
private IPropertyValueEditor _valueEditorAssigned;
private ConfigurationEditor _configurationEditorAssigned;
/// <summary>
@@ -105,12 +105,12 @@ namespace Umbraco.Core.PropertyEditors
/// since it depends on the datatype configuration.</para>
/// <para>Technically, it could be cached by datatype but let's keep things
/// simple enough for now.</para>
/// <para>The property is marked as a Json property with ObjectCreationHandling
/// set to Replace in order to prevent the Json deserializer to retrieve the
/// value of the property before setting it.</para>
/// <para>The property is *not* marked with json ObjectCreationHandling = ObjectCreationHandling.Replace,
/// so by default the deserializer will first try to read it before assigning it, which is why
/// all deserialization *should* set the property before anything (see manifest deserializer).</para>
/// </remarks>
[JsonProperty("editor", Required = Required.Always, ObjectCreationHandling = ObjectCreationHandling.Replace)]
public ValueEditor ValueEditor
[JsonProperty("editor", Required = Required.Always)]
public IPropertyValueEditor ValueEditor
{
// create a new value editor each time - the property editor can be a
// singleton, but the value editor will get a configuration which depends
@@ -119,8 +119,9 @@ namespace Umbraco.Core.PropertyEditors
set => _valueEditorAssigned = value;
}
/// <inheritdoc />
[JsonIgnore]
IValueEditor IParameterEditor.ValueEditor => ValueEditor; // fixme - because we must, but - bah
IValueEditor IParameterEditor.ValueEditor => ValueEditor;
/// <summary>
/// Gets or sets the configuration editor.
@@ -134,27 +135,28 @@ namespace Umbraco.Core.PropertyEditors
/// property editor is a singleton, and although the configuration editor could
/// technically be a singleton too, we'd rather not keep configuration editor
/// cached.</para>
/// <para>The property is marked as a Json property with ObjectCreationHandling
/// set to Replace in order to prevent the Json deserializer to retrieve the
/// value of the property before setting it.</para>
/// <para>The property is *not* marked with json ObjectCreationHandling = ObjectCreationHandling.Replace,
/// so by default the deserializer will first try to read it before assigning it, which is why
/// all deserialization *should* set the property before anything (see manifest deserializer).</para>
/// </remarks>
[JsonProperty("prevalues", ObjectCreationHandling = ObjectCreationHandling.Replace)] // changing the name would break manifests
[JsonProperty("prevalues")] // changing the name would break manifests
public ConfigurationEditor ConfigurationEditor
{
get => CreateConfigurationEditor();
set => _configurationEditorAssigned = value;
}
[JsonProperty("defaultConfig")]
public IDictionary<string, object> DefaultConfiguration => ConfigurationEditor.DefaultConfiguration;
[JsonIgnore] // fixme - but is parameterEditor.Configuration the same thing as preValues?
IDictionary<string, object> IParameterEditor.Configuration => DefaultConfiguration; // fixme - because we must, but - bah
// a property editor has a configuration editor which is in charge of all configuration
// a parameter editor does not have a configuration editor and directly handles its configuration
// when a property editor can also be a parameter editor it needs to expose the configuration
// fixme but that's only for some property editors
[JsonIgnore]
IDictionary<string, object> IParameterEditor.Configuration => ConfigurationEditor.DefaultConfiguration;
/// <summary>
/// Creates a value editor instance.
/// </summary>
protected virtual ValueEditor CreateValueEditor()
protected virtual IPropertyValueEditor CreateValueEditor()
{
// handle assigned editor
// or create a new editor

View File

@@ -19,6 +19,10 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
[DefaultPropertyValueConverter(typeof(JsonValueConverter))] //this shadows the JsonValueConverter
public class GridValueConverter : JsonValueConverter
{
public GridValueConverter(PropertyEditorCollection propertyEditors)
: base(propertyEditors)
{ }
public override bool IsConverter(PublishedPropertyType propertyType)
=> propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.Grid);

View File

@@ -16,14 +16,14 @@ namespace Umbraco.Core.PropertyEditors
/// <summary>
/// Represents a value editor for content properties.
/// </summary>
public class ValueEditor : IValueEditor
public class ValueEditor : IPropertyValueEditor
{
private string _view;
/// <summary>
/// Initializes a new instance of the <see cref="ValueEditor"/> class.
/// </summary>
public ValueEditor()
public ValueEditor() // for tests, and manifest
{
ValueType = ValueTypes.String;
Validators = new List<IValueValidator>();
@@ -32,7 +32,7 @@ namespace Umbraco.Core.PropertyEditors
/// <summary>
/// Initializes a new instance of the <see cref="ValueEditor"/> class.
/// </summary>
public ValueEditor(string view, params IValueValidator[] validators)
public ValueEditor(string view, params IValueValidator[] validators) // not used
: this()
{
View = view;
@@ -146,12 +146,6 @@ namespace Umbraco.Core.PropertyEditors
/// </remarks>
public virtual ManifestValidator RegexValidator => new RegexValidator();
/// <summary>
/// Gets the <see cref="ValueStorageType"/> corresponding to the value type.
/// </summary>
/// <returns></returns>
public ValueStorageType GetDatabaseType() => ValueTypes.ToStorageType(ValueType);
/// <summary>
/// If this is is true than the editor will be displayed full width without a label
/// </summary>
@@ -176,7 +170,7 @@ namespace Umbraco.Core.PropertyEditors
Type valueType;
//convert the string to a known type
switch (GetDatabaseType())
switch (ValueTypes.ToStorageType(ValueType))
{
case ValueStorageType.Ntext:
case ValueStorageType.Nvarchar:
@@ -246,7 +240,7 @@ namespace Umbraco.Core.PropertyEditors
var result = TryConvertValueToCrlType(editorValue.Value);
if (result.Success == false)
{
Current.Logger.Warn<ValueEditor>("The value " + editorValue.Value + " cannot be converted to the type " + GetDatabaseType());
Current.Logger.Warn<ValueEditor>("The value " + editorValue.Value + " cannot be converted to the type " + ValueTypes.ToStorageType(ValueType));
return null;
}
return result.Result;
@@ -267,7 +261,7 @@ namespace Umbraco.Core.PropertyEditors
{
if (property.GetValue() == null) return string.Empty;
switch (GetDatabaseType())
switch (ValueTypes.ToStorageType(ValueType))
{
case ValueStorageType.Ntext:
case ValueStorageType.Nvarchar:
@@ -359,7 +353,7 @@ namespace Umbraco.Core.PropertyEditors
return new XText(ConvertDbToString(propertyType, value, dataTypeService));
}
switch (GetDatabaseType())
switch (ValueTypes.ToStorageType(ValueType))
{
case ValueStorageType.Date:
case ValueStorageType.Integer:
@@ -382,7 +376,7 @@ namespace Umbraco.Core.PropertyEditors
if (value == null)
return string.Empty;
switch (GetDatabaseType())
switch (ValueTypes.ToStorageType(ValueType))
{
case ValueStorageType.Nvarchar:
case ValueStorageType.Ntext:

View File

@@ -102,7 +102,6 @@ namespace Umbraco.Core.PropertyEditors
default:
throw new ArgumentOutOfRangeException(nameof(valueType), $"Value \"{valueType}\" is not a valid ValueTypes.");
}
}
}
}

View File

@@ -7,6 +7,7 @@ using System.Xml.Linq;
using Newtonsoft.Json;
using Umbraco.Core.Composing;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Strings;
namespace Umbraco.Core.Services