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:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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.");
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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...
|
||||
|
||||
36
src/Umbraco.Core/Services/LocalizationServiceExtensions.cs
Normal file
36
src/Umbraco.Core/Services/LocalizationServiceExtensions.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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" />
|
||||
|
||||
Reference in New Issue
Block a user