Starts wiring up the back office to the c# bits, updates controllers, mappers, models, property editors to support getting and saving data by language. The content editor now "works" with multi-lingual properties

This commit is contained in:
Shannon
2018-04-04 01:59:51 +10:00
parent e7bc4986a5
commit 7a73175aa0
39 changed files with 463 additions and 203 deletions

View File

@@ -19,6 +19,9 @@ namespace Umbraco.Core.Models
[DebuggerDisplay("Id: {Id}, Name: {Name}, Alias: {Alias}")]
public abstract class ContentTypeBase : TreeEntityBase, IContentTypeBase
{
//fixme this should be invariant by default but for demo purposes and until the UI is updated to support changing a property type we'll make this neutral by default
private const ContentVariation DefaultVaryBy = ContentVariation.CultureNeutral;
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private string _alias;
@@ -46,7 +49,7 @@ namespace Umbraco.Core.Models
_propertyTypes = new PropertyTypeCollection(IsPublishing);
_propertyTypes.CollectionChanged += PropertyTypesChanged;
_variations = ContentVariation.InvariantNeutral;
_variations = DefaultVaryBy;
}
protected ContentTypeBase(IContentTypeBase parent)
@@ -67,7 +70,7 @@ namespace Umbraco.Core.Models
_propertyTypes = new PropertyTypeCollection(IsPublishing);
_propertyTypes.CollectionChanged += PropertyTypesChanged;
_variations = ContentVariation.InvariantNeutral;
_variations = DefaultVaryBy;
}
/// <summary>

View File

@@ -167,9 +167,7 @@ namespace Umbraco.Core.Models
/// <param name="property">The property.</param>
/// <param name="value">The property value.</param>
/// <param name="tagConfiguration">The datatype configuration.</param>
/// <param name="tagPropertyEditorAttribute">The property editor tags configuration attribute.</param>
/// <remarks>
/// <para>The tags configuration is specified by the <paramref name="tagPropertyEditorAttribute"/> marking the property editor.</para>
/// <remarks>
/// <para>The value is either a string (delimited string) or an enumeration of strings (tag list).</para>
/// <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>

View File

@@ -19,7 +19,10 @@ namespace Umbraco.Core.Models
[DataContract(IsReference = true)]
[DebuggerDisplay("Id: {Id}, Name: {Name}, Alias: {Alias}")]
public class PropertyType : EntityBase, IEquatable<PropertyType>
{
{
//fixme this should be invariant by default but for demo purposes and until the UI is updated to support changing a property type we'll make this neutral by default
private const ContentVariation DefaultVaryBy = ContentVariation.CultureNeutral;
private static PropertySelectors _selectors;
private readonly bool _forceValueStorageType;
@@ -47,7 +50,7 @@ namespace Umbraco.Core.Models
_propertyEditorAlias = dataType.EditorAlias;
_valueStorageType = dataType.DatabaseType;
_variations = ContentVariation.InvariantNeutral;
_variations = DefaultVaryBy;
}
/// <summary>
@@ -84,7 +87,7 @@ namespace Umbraco.Core.Models
_valueStorageType = valueStorageType;
_forceValueStorageType = forceValueStorageType;
_alias = propertyTypeAlias == null ? null : SanitizeAlias(propertyTypeAlias);
_variations = ContentVariation.InvariantNeutral;
_variations = DefaultVaryBy;
}
private static PropertySelectors Selectors => _selectors ?? (_selectors = new PropertySelectors());
@@ -391,7 +394,9 @@ namespace Umbraco.Core.Models
{
throw new InvalidOperationException($"Cannot assign value \"{value}\" of type \"{value.GetType()}\" to property \"{alias}\" expecting type \"{expected}\".");
}
//fixme - perhaps this and other validation methods should be a service level (not a model) thing?
/// <summary>
/// Determines whether a value is valid for this property type.
/// </summary>

View File

@@ -19,8 +19,7 @@ namespace Umbraco.Core.PropertyEditors
public class DataEditor : IDataEditor
{
private IDictionary<string, object> _defaultConfiguration;
private IDataValueEditor _valueEditorAssigned;
/// <summary>
/// Initializes a new instance of the <see cref="DataEditor"/> class.
/// </summary>
@@ -160,10 +159,6 @@ namespace Umbraco.Core.PropertyEditors
/// <returns></returns>
protected virtual IDataValueEditor CreateValueEditor()
{
// handle assigned editor, or create a new one
if (_valueEditorAssigned != null)
return _valueEditorAssigned;
if (Attribute == null)
throw new InvalidOperationException("The editor does not specify a view.");

View File

@@ -232,22 +232,24 @@ namespace Umbraco.Core.PropertyEditors
// eg
// [ { "value": "hello" }, { "lang": "fr-fr", "value": "bonjour" } ]
/// <summary>
/// A method to deserialize the string value that has been saved in the content editor
/// to an object to be stored in the database.
/// </summary>
/// <param name="editorValue"></param>
/// <param name="currentValue">
/// The current value that has been persisted to the database for this editor. This value may be usesful for
/// how the value then get's deserialized again to be re-persisted. In most cases it will probably not be used.
/// </param>
/// <summary>
/// A method to deserialize the string value that has been saved in the content editor
/// to an object to be stored in the database.
/// </summary>
/// <param name="editorValue"></param>
/// <param name="currentValue">
/// The current value that has been persisted to the database for this editor. This value may be usesful for
/// how the value then get's deserialized again to be re-persisted. In most cases it will probably not be used.
/// </param>
/// <param name="languageId"></param>
/// <param name="segment"></param>
/// <returns></returns>
/// <remarks>
/// By default this will attempt to automatically convert the string value to the value type supplied by ValueType.
///
/// If overridden then the object returned must match the type supplied in the ValueType, otherwise persisting the
/// value to the DB will fail when it tries to validate the value type.
/// </remarks>
/// <remarks>
/// By default this will attempt to automatically convert the string value to the value type supplied by ValueType.
///
/// If overridden then the object returned must match the type supplied in the ValueType, otherwise persisting the
/// value to the DB will fail when it tries to validate the value type.
/// </remarks>
public virtual object FromEditor(ContentPropertyData editorValue, object currentValue)
{
//if it's json but it's empty json, then return null
@@ -269,16 +271,18 @@ namespace Umbraco.Core.PropertyEditors
/// A method used to format the database value to a value that can be used by the editor
/// </summary>
/// <param name="property"></param>
/// <param name="propertyType"></param>
/// <param name="dataTypeService"></param>
/// <param name="languageId"></param>
/// <param name="segment"></param>
/// <returns></returns>
/// <remarks>
/// 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)
public virtual object ToEditor(Property property, IDataTypeService dataTypeService, int? languageId = null, string segment = null)
{
if (property.GetValue() == null) return string.Empty;
var val = property.GetValue(languageId, segment);
if (val == null) return string.Empty;
switch (ValueTypes.ToStorageType(ValueType))
{
@@ -286,7 +290,7 @@ namespace Umbraco.Core.PropertyEditors
case ValueStorageType.Nvarchar:
//if it is a string type, we will attempt to see if it is json stored data, if it is we'll try to convert
//to a real json object so we can pass the true json object directly to angular!
var asString = property.GetValue().ToString();
var asString = val.ToString();
if (asString.DetectIsJson())
{
try
@@ -304,12 +308,12 @@ namespace Umbraco.Core.PropertyEditors
case ValueStorageType.Decimal:
//Decimals need to be formatted with invariant culture (dots, not commas)
//Anything else falls back to ToString()
var decim = property.GetValue().TryConvertTo<decimal>();
var decim = val.TryConvertTo<decimal>();
return decim.Success
? decim.Result.ToString(NumberFormatInfo.InvariantInfo)
: property.GetValue().ToString();
: val.ToString();
case ValueStorageType.Date:
var date = property.GetValue().TryConvertTo<DateTime?>();
var date = val.TryConvertTo<DateTime?>();
if (date.Success == false || date.Result == null)
{
return string.Empty;

View File

@@ -61,7 +61,7 @@ namespace Umbraco.Core.PropertyEditors
/// <summary>
/// Converts a property value to a value for the editor.
/// </summary>
object ToEditor(Property property, IDataTypeService dataTypeService);
object ToEditor(Property property, IDataTypeService dataTypeService, int? languageId = null, string segment = null);
// fixme - editing - document or remove these
// why property vs propertyType? services should be injected! etc...

View File

@@ -0,0 +1,36 @@
using System.Linq;
using Umbraco.Core.Models;
namespace Umbraco.Core.Services
{
public static class LocalizationServiceExtensions
{
/// <summary>
/// Returns the configured default variant language
/// </summary>
/// <param name="service"></param>
/// <returns></returns>
public static ILanguage GetDefaultVariantLanguage(this ILocalizationService service)
{
var langs = service.GetAllLanguages().OrderBy(x => x.Id).ToList();
//if there's only one language, by default it is the default
if (langs.Count == 1)
{
langs[0].IsDefaultVariantLanguage = true;
langs[0].Mandatory = true;
return langs[0];
}
if (langs.All(x => !x.IsDefaultVariantLanguage))
{
//if no language has the default flag, then the defaul language is the one with the lowest id
langs[0].IsDefaultVariantLanguage = true;
langs[0].Mandatory = true;
return langs[0];
}
return langs.First(x => x.IsDefaultVariantLanguage);
}
}
}

View File

@@ -1415,6 +1415,7 @@
<Compile Include="Services\IUserService.cs" />
<Compile Include="Services\Implement\LocalizationService.cs" />
<Compile Include="Services\Implement\LocalizedTextService.cs" />
<Compile Include="Services\LocalizationServiceExtensions.cs" />
<Compile Include="Services\LocalizedTextServiceExtensions.cs" />
<Compile Include="Services\Implement\LocalizedTextServiceFileSources.cs" />
<Compile Include="Services\Implement\LocalizedTextServiceSupplementaryFileSource.cs" />