Skip to content

Commit

Permalink
DataType migrations.
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinJump committed Apr 15, 2024
1 parent f165b05 commit 73d1880
Show file tree
Hide file tree
Showing 28 changed files with 811 additions and 22 deletions.
1 change: 1 addition & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
</PropertyGroup>

<ItemGroup>
<InternalsVisibleTo Include="uSync.Tests" />
<None Include="../assets/usync-logo.png" Pack="true" PackagePath="\" Visible="false" />
</ItemGroup>
</Project>
25 changes: 24 additions & 1 deletion uSync.Core/DataTypes/ConfigurationSerializerBase.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
namespace uSync.Core.DataTypes;
using System.Collections.Immutable;

using uSync.Core.Extensions;

namespace uSync.Core.DataTypes;

public abstract class ConfigurationSerializerBase
{
Expand All @@ -7,4 +11,23 @@ public virtual IDictionary<string, object> GetConfigurationExport(IDictionary<st

public virtual IDictionary<string, object> GetConfigurationImport(IDictionary<string, object> configuration)
=> configuration;

/// <summary>
/// renames properties that might exist in a json string (if it is one).
/// </summary>
/// <remarks>
/// will check if the string is JSON if its not, we return the source
/// </remarks>
protected static IDictionary<string, object> MigratePropertyNames(IDictionary<string, object> source, Dictionary<string, string> names, bool sort = true)
{
foreach (var keyValue in names)
{
if (source.TryGetValue(keyValue.Key, out var propertyValue) == false) continue;
source[keyValue.Value] = propertyValue;
source.Remove(keyValue.Key);
}

return sort ? source.ToImmutableSortedDictionary() : source;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,7 @@ public ConfigurationSerializerCollection(Func<IEnumerable<IConfigurationSerializ

public IConfigurationSerializer? GetSerializer(string editorAlias)
=> this.FirstOrDefault(x => x.Editors.InvariantContains(editorAlias));

public IEnumerable<IConfigurationSerializer> GetSerializers(string editorAlias)
=> this.Where(x => x.Editors.InvariantContains(editorAlias));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System.Text.Json;
using System.Text.Json.Nodes;

using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Strings;

using uSync.Core.Extensions;

using static Umbraco.Cms.Core.PropertyEditors.ColorPickerConfiguration;

namespace uSync.Core.DataTypes.DataTypeSerializers;

internal class ColourPickerMigratingConfigSerializer : ConfigurationSerializerBase, IConfigurationSerializer
{
public string Name => nameof(ColourPickerMigratingConfigSerializer);
public string[] Editors => [Constants.PropertyEditors.Aliases.ColorPicker];
public override IDictionary<string, object> GetConfigurationImport(IDictionary<string, object> configuration)
{
if (configuration.TryGetValue("items", out var items) is false || items is null)
return configuration;

if (items is JsonElement element == false) return configuration;
if (element.ValueKind != JsonValueKind.Array) return configuration;

var convertedItems = new List<ColorPickerItem>();

var array = element.EnumerateArray().Select(x => x);

foreach(var item in element.EnumerateArray())
{
if (item.ValueKind != JsonValueKind.Object) continue;
var obj = JsonSerializer.Deserialize<JsonObject>(item.ToString());
if (obj == null) continue;

var valueJson = obj.GetPropertyAsString("value");
if (string.IsNullOrEmpty(valueJson)) continue;

if (valueJson.TryDeserialize<JsonObject>(out var itemValues) is false || itemValues is null)
return configuration;

convertedItems.Add(new ColorPickerItem
{
Label = itemValues.GetPropertyAsString("label"),
Value = itemValues.GetPropertyAsString("value")
});
}

configuration.Remove("items");
configuration.Add("items", convertedItems);

return configuration;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System.Text.Json;

using Umbraco.Cms.Core;

using uSync.Core.Extensions;

namespace uSync.Core.DataTypes.DataTypeSerializers;

internal class DataListMigratingConfigSerializer : ConfigurationSerializerBase, IConfigurationSerializer
{
public string Name => nameof(DataListMigratingConfigSerializer);
public string[] Editors => [
Constants.PropertyEditors.Aliases.CheckBoxList,
Constants.PropertyEditors.Aliases.DropDownListFlexible,
Constants.PropertyEditors.Aliases.RadioButtonList
];

public override IDictionary<string, object> GetConfigurationImport(IDictionary<string, object> configuration)
{
if (configuration.TryGetValue("items", out var items) is false || items is null)
return configuration;

if (items is JsonElement element == false) return configuration;
if (element.ValueKind != JsonValueKind.Array) return configuration;

if (element.ToString().TryDeserialize<List<IdValuePair>>(out var values) is false || values is null)
return configuration;

var convertedItems = new List<string>();

foreach(var item in values.OrderBy(x => x.Id))
{
if (item?.Value is null) continue;
convertedItems.Add(item.Value);
}

configuration["items"] = convertedItems;

return configuration;
}
private class IdValuePair
{
public int? Id { get; set; }
public string? Value { get; set; }
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

using Umbraco.Cms.Core;

using uSync.Core.Extensions;

namespace uSync.Core.DataTypes.DataTypeSerializers;
internal class FileUploadMigratingConfigSerializer : ConfigurationSerializerBase, IConfigurationSerializer
{
public string Name => nameof(FileUploadMigratingConfigSerializer);

public string[] Editors => [Constants.PropertyEditors.Aliases.UploadField];

public override IDictionary<string, object> GetConfigurationImport(IDictionary<string, object> configuration)
{
if (configuration.TryGetValue("fileExtensions", out var items) is false || items is null)
return configuration;

if (items is JsonElement element == false) return configuration;
if (element.ValueKind != JsonValueKind.Array) return configuration;

if (element.ToString().TryDeserialize<List<IdValuePair>>(out var values) is false || values is null)
return configuration;

var convertedItems = new List<string>();

foreach(var item in values.OrderBy(x => x.Id))
{
if (item.Value is null) continue;
convertedItems.Add(item.Value);
}

configuration["fileExtensions"] = convertedItems;
return configuration;
}

private class IdValuePair
{
public int? Id { get; set; }
public string? Value { get; set; }
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Umbraco.Cms.Core;

namespace uSync.Core.DataTypes.DataTypeSerializers;

internal class LabelMigratingConfigSerializer : ConfigurationSerializerBase, IConfigurationSerializer
{
public string Name => nameof(LabelMigratingConfigSerializer);
public string[] Editors => [Constants.PropertyEditors.Aliases.Label];

public override IDictionary<string, object> GetConfigurationImport(IDictionary<string, object> configuration)
=> MigratePropertyNames(configuration, new()
{
{ "ValueType", "umbracoDataValueType" }
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Umbraco.Cms.Core;

namespace uSync.Core.DataTypes.DataTypeSerializers;
internal class MarkdownMigratingConfigSerializer : ConfigurationSerializerBase, IConfigurationSerializer
{
public string Name => nameof(MarkdownMigratingConfigSerializer);

public string[] Editors => [ Constants.PropertyEditors.Aliases.MarkdownEditor ];

public override IDictionary<string, object> GetConfigurationImport(IDictionary<string, object> configuration)
=> MigratePropertyNames(configuration, new()
{
{ "displayLivePreview", "preview" }
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Umbraco.Cms.Core;

namespace uSync.Core.DataTypes.DataTypeSerializers;

internal class MultipleTextMigratingConfigSerializer : ConfigurationSerializerBase, IConfigurationSerializer
{
public string Name => nameof(MultipleTextMigratingConfigSerializer);

public string[] Editors => [Constants.PropertyEditors.Aliases.MultipleTextstring];

public override IDictionary<string, object> GetConfigurationImport(IDictionary<string, object> configuration)
=> MigratePropertyNames(configuration, new()
{
{ "maximum", "max" },
{ "minimum", "min" }
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using NPoco.Linq;

using Umbraco.Cms.Core;

namespace uSync.Core.DataTypes.DataTypeSerializers;

internal class SliderMigratingConfigSerializer : ConfigurationSerializerBase, IConfigurationSerializer
{
public string Name => nameof(SliderMigratingConfigSerializer);
public string[] Editors => [Constants.PropertyEditors.Aliases.Slider];

public override IDictionary<string, object> GetConfigurationImport(IDictionary<string, object> configuration)
=> MigratePropertyNames(configuration, new()
{
{ "initialValue", "initVal1" },
{ "initialValue2", "initVal2" },
{ "maximumValue", "maxVal" },
{ "minimumValue", "minVal" },
{ "stepIncrements", "step" }
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System.Text.Json;

using Umbraco.Cms.Core;

using uSync.Core.Extensions;

namespace uSync.Core.DataTypes.DataTypeSerializers;

internal class TagMigratingConfigSerializer : ConfigurationSerializerBase, IConfigurationSerializer
{
public string Name => nameof(TagMigratingConfigSerializer);

public string[] Editors => [Constants.PropertyEditors.Aliases.Tags];

public override IDictionary<string, object> GetConfigurationImport(IDictionary<string, object> configuration)
{
if (configuration.TryGetValue("StorageType", out var storageType) is false
|| storageType == null)
{
return configuration;
}

if (configuration.ContainsKey("delimiter"))
configuration.Remove("delimiter");

if (storageType is JsonElement element == false) return configuration;
if (element.ValueKind != JsonValueKind.Number) return configuration;
var storageNumber = element.GetValueAs<int>();

var typeString = storageNumber == 0 ? "csv" : "Json";
// if storage type is a number.
configuration.Remove("StorageType");

configuration.Add("storageType", new string[] { typeString });

return configuration;


}

}
2 changes: 1 addition & 1 deletion uSync.Core/Extensions/DictionaryExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public static IDictionary<TKey, TValue> MergeIgnoreDuplicates<TKey, TValue>(this

public static IDictionary<string, TValue> ConvertToCamelCase<TValue>(this IDictionary<string, TValue> originalDictionary)
=> originalDictionary
.ToDictionary(kvp => kvp.Key.ToCamelCase(), kvp => kvp.Value);
.ToDictionary(kvp => kvp.Key.ToCamelCase(), kvp => kvp.Value, StringComparer.OrdinalIgnoreCase);

public static string ToCamelCase(this string s)
{
Expand Down
34 changes: 32 additions & 2 deletions uSync.Core/Extensions/JsonTextExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
using System.Text.Json;
using System.Text.Json.Nodes;

using Microsoft.CodeAnalysis.CSharp.Syntax;

using Org.BouncyCastle.Bcpg.Sig;

using Umbraco.Cms.Core.Security;
using Umbraco.Extensions;

using uSync.Core.Json;
Expand All @@ -13,15 +18,15 @@ namespace uSync.Core.Extensions;
/// </summary>
public static class JsonTextExtensions
{
private static readonly JsonSerializerOptions _defaultOptions = new()
internal static readonly JsonSerializerOptions _defaultOptions = new()
{
WriteIndented = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
PropertyNameCaseInsensitive = true,
TypeInfoResolver = new OrderedPropertiesJsonResolver(),
};

private static readonly JsonSerializerOptions _flatOptions = new()
internal static readonly JsonSerializerOptions _flatOptions = new()
{
WriteIndented = false,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
Expand Down Expand Up @@ -392,6 +397,9 @@ public static bool TryGetPropertyAsObject(this JsonObject jsonObject, string pro
return result != default;
}

/// <summary>
/// Gets the json property as a string, or returns string.empty
/// </summary>
public static string GetPropertyAsString(this JsonObject obj, string propertyName)
{
if (obj.TryGetPropertyValue(propertyName, out var value))
Expand All @@ -400,6 +408,28 @@ public static string GetPropertyAsString(this JsonObject obj, string propertyNam
return string.Empty;
}

public static bool GetPropertyAsBool(this JsonObject obj, string propertyName, bool defaultValue)
{
if (obj.TryGetPropertyValue(propertyName, out var value))
{
if (bool.TryParse(value?.ToString() ?? string.Empty, out var result) is false)
return defaultValue;

return result;
}

return defaultValue;
}

public static TResult GetPropertyValueOrDefault<TResult>(this JsonObject obj, string propertyName, TResult defaultValue)
{
if (obj.TryGetPropertyValue(propertyName, out var value) is false || value is null)
return defaultValue;

var attempt = value.TryConvertTo<TResult>();
return attempt.ResultOr(defaultValue);
}

public static bool TryGetPropertyAsArray(this JsonObject jsonObject, string propertyName, [MaybeNullWhen(false)] out JsonArray result)
{
result = default;
Expand Down
Loading

0 comments on commit 73d1880

Please sign in to comment.