Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OSOE-795: Upgrade to latest OC preview to test System.Text.Json #161

Merged
merged 26 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
dd5a144
Update NuGet versions to pre-release.
sarahelsaig Feb 22, 2024
8dfb784
Merge remote-tracking branch 'origin/dev' into issue/OSOE-795
sarahelsaig Feb 22, 2024
7928059
Fix compilation errors.
sarahelsaig Feb 23, 2024
4a90771
Refactor CodeGenerationDisplayDriver.
sarahelsaig Feb 23, 2024
87c3db9
Fix compilation errors.
sarahelsaig Feb 23, 2024
d9d5d9c
Remove "using Newtonsoft.Json"
sarahelsaig Feb 24, 2024
8186703
Fix MenuWidgetLiquidFilter.
sarahelsaig Feb 24, 2024
2c38547
Update OC to latest (because of bug fix for WorkflowTypeStep)
sarahelsaig Mar 3, 2024
22b85a4
ISmtpService is obsolete.
sarahelsaig Mar 3, 2024
c087456
Update method name.
sarahelsaig Mar 4, 2024
dc1d164
Update OC preview version.
sarahelsaig Mar 7, 2024
68c7cf5
Update code generation test due to change in serialization.
sarahelsaig Mar 13, 2024
4a695ab
Update OC package
sarahelsaig Mar 13, 2024
aec510e
Code cleanup.
sarahelsaig Mar 13, 2024
e6a3888
Use JObject.FromObject instead of JsonSerializer.SerializeToNode wher…
sarahelsaig Apr 2, 2024
3e72269
Merge remote-tracking branch 'origin/dev' into issue/OSOE-795
sarahelsaig Apr 22, 2024
f35bde3
Fix SerializeAndDeserialize
sarahelsaig Apr 23, 2024
bfd977f
Update OC preview version.
sarahelsaig Apr 23, 2024
33639b9
Update AddCondition to AddRuleCondition
sarahelsaig Apr 23, 2024
75b5863
Update OC package version.
sarahelsaig Apr 27, 2024
3416279
Merge remote-tracking branch 'origin/dev' into issue/OSOE-795
sarahelsaig May 4, 2024
547b55e
Update OC versions
sarahelsaig May 4, 2024
eadc295
Post merge and OC update fixup
sarahelsaig May 4, 2024
5800d7b
Update OC to the latest preview.
sarahelsaig May 7, 2024
0f74d1a
Rename variable.
sarahelsaig May 8, 2024
b3e7616
Replace strange leftover `var` with `const`.
sarahelsaig May 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,39 +1,48 @@
using System;
using Shouldly;
using System.Diagnostics.CodeAnalysis;

namespace Lombiq.HelpfulExtensions.Tests.UI.Constants;

internal static class GeneratedMigrationCodes
{
// Environment.NewLine is used for this to work regardless of the mismatch of line ending style between the code
// file, the platform where it was compiled, and where it was executed.
public static string Page =
string.Join(
Environment.NewLine,
"_contentDefinitionManager.AlterTypeDefinition(\"Page\", type => type",
" .DisplayedAs(\"Page\")",
" .Creatable()",
" .Listable()",
" .Draftable()",
" .Versionable()",
" .Securable()",
" .WithPart(\"TitlePart\", part => part",
" .WithPosition(\"0\")",
" )",
" .WithPart(\"AutoroutePart\", part => part",
" .WithPosition(\"1\")",
" .WithSettings(new AutoroutePartSettings",
" {",
" AllowCustomPath = true,",
" ShowHomepageOption = true,",
" Pattern = \"{{ Model.ContentItem | display_text | slugify }}\",",
" })",
" )",
" .WithPart(\"FlowPart\", part => part",
" .WithPosition(\"2\")",
" )",
" .WithPart(\"Page\", part => part",
" .WithPosition(\"3\")",
" )",
");",
string.Empty);
[SuppressMessage(
"Usage",
"MA0136:Raw String contains an implicit end of line character",
Justification = "It's wrapped to prevent issues related to that.")]
private const string Page =
"""
_contentDefinitionManager.AlterTypeDefinition("Page", type => type
.DisplayedAs("Page")
.Creatable()
.Listable()
.Draftable()
.Versionable()
.Securable()
.WithPart("TitlePart", part => part
.WithPosition("0")
)
.WithPart("AutoroutePart", part => part
.WithPosition("1")
.WithSettings(new AutoroutePartSettings
{
AllowCustomPath = true,
Pattern = {{ Model.ContentItem | display_text | slugify }},
ShowHomepageOption = true,
AllowUpdatePath = false,
AllowDisabled = false,
AllowRouteContainedItems = false,
ManageContainedItemRoutes = false,
AllowAbsolutePath = false,
})
)
.WithPart("FlowPart", part => part
.WithPosition("2")
)
.WithPart("Page", part => part
.WithPosition("3")
)
);
""";

public static void ShouldBePage(string actual) => actual.ShouldBeByLine(Page);
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ await context.RetryIfStaleOrFailAsync(async () =>
{
await context.ClickReliablyOnAsync(By.ClassName("toggle-showing-generated-migration-code"));

context.Get(By.Id("generated-migration-code").OfAnyVisibility()).GetValue().ShouldBe(GeneratedMigrationCodes.Page);
GeneratedMigrationCodes.ShouldBePage(
context.Get(By.Id("generated-migration-code").OfAnyVisibility()).GetValue());

// Making sure that the collapsible area is open.
context.Get(By.CssSelector("#generated-migration-code-container.collapse.show"));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Microsoft.Extensions.Localization;
using Newtonsoft.Json.Linq;
using OrchardCore.ContentManagement.Metadata.Models;
using OrchardCore.ContentManagement.Metadata.Settings;
using OrchardCore.ContentTypes.Editors;
Expand All @@ -9,11 +8,15 @@
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.Json.Nodes;

namespace Lombiq.HelpfulExtensions.Extensions.CodeGeneration;

public class CodeGenerationDisplayDriver : ContentTypeDefinitionDisplayDriver
{
private const int IndentationDepth = 4;
private const string EmptyString = "\"\"";

private readonly IStringLocalizer T;

public CodeGenerationDisplayDriver(IStringLocalizer<CodeGenerationDisplayDriver> stringLocalizer) =>
Expand All @@ -37,7 +40,7 @@ public override IDisplayResult Edit(ContentTypeDefinition model) =>
codeBuilder.AppendLine(CultureInfo.InvariantCulture, $" .DisplayedAs(\"{model.DisplayName}\")");

GenerateCodeForSettings(codeBuilder, model.GetSettings<ContentTypeSettings>());
AddSettingsWithout<ContentTypeSettings>(codeBuilder, model.Settings, 4);
AddSettingsWithout<ContentTypeSettings>(codeBuilder, model.Settings);
GenerateCodeForParts(codeBuilder, model.Parts);
codeBuilder.AppendLine(");");

Expand All @@ -63,7 +66,7 @@ private void GenerateCodeForParts(StringBuilder codeBuilder, IEnumerable<Content
AddWithLine(codeBuilder, nameof(partSettings.DisplayMode), partSettings.DisplayMode);
AddWithLine(codeBuilder, nameof(partSettings.Editor), partSettings.Editor);

AddSettingsWithout<ContentTypePartSettings>(codeBuilder, part.Settings, 8);
AddSettingsWithout<ContentTypePartSettings>(codeBuilder, part.Settings, 2 * IndentationDepth);

// Checking if anything was added to the part's settings.
if (codeBuilder.Length == partStartingLength)
Expand Down Expand Up @@ -102,7 +105,7 @@ private void GenerateCodeForPartsWithFields(
AddWithLine(codeBuilder, nameof(partSettings.Description), partSettings.Description);
AddWithLine(codeBuilder, nameof(partSettings.DefaultPosition), partSettings.DefaultPosition);

AddSettingsWithout<ContentPartSettings>(codeBuilder, part.Settings, 4);
AddSettingsWithout<ContentPartSettings>(codeBuilder, part.Settings);

foreach (var field in part.Fields)
{
Expand All @@ -116,7 +119,7 @@ private void GenerateCodeForPartsWithFields(
AddWithLine(codeBuilder, nameof(fieldSettings.DisplayMode), fieldSettings.DisplayMode);
AddWithLine(codeBuilder, nameof(fieldSettings.Position), fieldSettings.Position);

AddSettingsWithout<ContentPartFieldSettings>(codeBuilder, field.Settings, 8);
AddSettingsWithout<ContentPartFieldSettings>(codeBuilder, field.Settings, 2 * IndentationDepth);

codeBuilder.AppendLine(" )");
}
Expand All @@ -125,32 +128,20 @@ private void GenerateCodeForPartsWithFields(
}
}

private string ConvertJToken(JToken jToken, int indentationDepth)
{
switch (jToken)
private string ConvertNode(JsonNode node, int indentationDepth) =>
node switch
{
case JValue jValue:
var value = jValue.Value;
return value switch
{
bool boolValue => boolValue ? "true" : "false",
string => $"\"{value}\"",
_ => value?.ToString()?.Replace(',', '.'), // Replace decimal commas.
};
case JArray jArray:
return ConvertJArray(jArray, indentationDepth);
case JObject jObject:
return ConvertJObject(jObject, indentationDepth);
default:
throw new NotSupportedException($"Settings values of type {jToken.GetType()} are not supported.");
}
}
JsonValue jsonValue => jsonValue.ToString(),
JsonArray jsonArray => ConvertJsonArray(jsonArray, indentationDepth),
JsonObject jsonObject => ConvertJsonObject(jsonObject, indentationDepth),
_ => throw new NotSupportedException($"Settings values of type {node.GetType()} are not supported."),
};

private string ConvertJArray(JArray jArray, int indentationDepth)
private string ConvertJsonArray(JsonArray jArray, int indentationDepth)
{
var indentation = new string(' ', indentationDepth + 4);
var indentation = new string(' ', indentationDepth + IndentationDepth);

var items = jArray.Select(item => ConvertJToken(item, indentationDepth + 8)).ToList();
var items = jArray.Select(item => ConvertNode(item, indentationDepth + (2 * IndentationDepth))).ToList();

// If the items are formatted (for ListValueOption) then don't inject line-by-line formatting.
if (items.Exists(item => item.ContainsOrdinalIgnoreCase(Environment.NewLine)))
Expand All @@ -164,7 +155,7 @@ private string ConvertJArray(JArray jArray, int indentationDepth)
stringArrayCodeBuilder.AppendLine();
stringArrayCodeBuilder.AppendLine(CultureInfo.InvariantCulture, $"{indentation}{{");

var itemIndentation = new string(' ', indentationDepth + 8);
var itemIndentation = new string(' ', indentationDepth + (2 * IndentationDepth));

foreach (var item in items)
{
Expand All @@ -176,17 +167,17 @@ private string ConvertJArray(JArray jArray, int indentationDepth)
return stringArrayCodeBuilder.ToString();
}

private string ConvertJObject(JObject jObject, int indentationDepth)
private string ConvertJsonObject(JsonObject jObject, int indentationDepth)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private string ConvertJsonObject(JsonObject jObject, int indentationDepth)
private string ConvertJsonObject(JsonObject jsonObject, int indentationDepth)

{
var braceIndentation = new string(' ', indentationDepth);
var propertyIndentation = new string(' ', indentationDepth + 4);
if (jObject["name"] != null && jObject["value"] != null)
var propertyIndentation = new string(' ', indentationDepth + IndentationDepth);
if (jObject["name"] is { } name && jObject["value"] is { } value)
{
var objectCodeBuilder = new StringBuilder();
objectCodeBuilder.AppendLine(CultureInfo.InvariantCulture, $"{braceIndentation}new ListValueOption");
objectCodeBuilder.AppendLine(CultureInfo.InvariantCulture, $"{braceIndentation}{{");
objectCodeBuilder.AppendLine(CultureInfo.InvariantCulture, $"{propertyIndentation}Name = \"{jObject["name"]}\",");
objectCodeBuilder.AppendLine(CultureInfo.InvariantCulture, $"{propertyIndentation}Value = \"{jObject["value"]}\",");
objectCodeBuilder.AppendLine(CultureInfo.InvariantCulture, $"{propertyIndentation}Name = \"{name}\",");
objectCodeBuilder.AppendLine(CultureInfo.InvariantCulture, $"{propertyIndentation}Value = \"{value}\",");
objectCodeBuilder.AppendLine(CultureInfo.InvariantCulture, $"{braceIndentation}}},");

return objectCodeBuilder.ToString();
Expand All @@ -196,33 +187,26 @@ private string ConvertJObject(JObject jObject, int indentationDepth)
return T["\"FIX ME! Couldn't determine the actual type to instantiate.\" {0}", jObject.ToString()];
}

private void AddSettingsWithout<T>(StringBuilder codeBuilder, JObject settings, int indentationDepth)
private void AddSettingsWithout<T>(StringBuilder codeBuilder, JsonObject settings, int indentationDepth = IndentationDepth)
{
var indentation = new string(' ', indentationDepth);

var filteredSettings = ((IEnumerable<KeyValuePair<string, JToken>>)settings)
.Where(setting => setting.Key != typeof(T).Name);
var filteredSettings = settings
.Where(pair => pair.Key != typeof(T).Name && pair.Value is JsonObject)
.Select(pair => (pair.Key, (JsonObject)pair.Value));

foreach (var setting in filteredSettings)
foreach (var (typeName, properties) in filteredSettings)
{
var properties = setting.Value.Where(property => property is JProperty).Cast<JProperty>().ToArray();
if (properties.Count == 0) continue;

if (properties.Length == 0) continue;

codeBuilder.AppendLine(CultureInfo.InvariantCulture, $"{indentation}.WithSettings(new {setting.Key}");
codeBuilder.AppendLine(CultureInfo.InvariantCulture, $"{indentation}.WithSettings(new {typeName}");
codeBuilder.AppendLine(indentation + "{");

// This doesn't support multi-level object hierarchies for settings but come on, who uses complex settings
// objects?
for (int i = 0; i < properties.Length; i++)
foreach (var (name, value) in properties)
{
var property = properties[i];

var propertyValue = ConvertJToken(property.Value, indentationDepth);

propertyValue ??= "\"\"";

codeBuilder.AppendLine(CultureInfo.InvariantCulture, $"{indentation} {property.Name} = {propertyValue},");
codeBuilder.AppendLine(
CultureInfo.InvariantCulture,
$"{indentation} {name} = {ConvertNode(value, indentationDepth) ?? EmptyString},");
}

codeBuilder.AppendLine(indentation + "})");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using OrchardCore.ContentManagement.Metadata.Settings;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Nodes;
using System.Threading.Tasks;

namespace Lombiq.HelpfulExtensions.Extensions.ContentSets.ViewModels;
Expand All @@ -33,8 +34,7 @@ public class ContentSetPartViewModel
public string DisplayName =>
Definition?
.Settings?
.Property(nameof(ContentTypePartSettings))?
.Value
.GetMaybe(nameof(ContentTypePartSettings))?
.ToObject<ContentTypePartSettings>()?
.DisplayName ?? Definition?.Name;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
using Lombiq.HelpfulExtensions.Extensions.ContentSets.Workflows.Activities;
using Lombiq.HelpfulExtensions.Extensions.ContentSets.Workflows.Models;
using Lombiq.HelpfulLibraries.OrchardCore.Workflow;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OrchardCore.ContentManagement;
using OrchardCore.ContentManagement.Metadata.Models;
using OrchardCore.Workflows.Models;
using OrchardCore.Workflows.Services;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Threading.Tasks;

namespace Lombiq.HelpfulExtensions.Extensions.ContentSets.Workflows.Handlers;
Expand Down Expand Up @@ -54,14 +54,16 @@ public async Task<IEnumerable<ContentSetLinkViewModel>> GetSupportedOptionsAsync
case ContentSetLinkViewModel viewModel:
links.Add(viewModel);
break;
case IEnumerable<object> collection when collection.CastWhere<ExpandoObject>() is { } objects && objects.Any():
links.AddRange(JToken.FromObject(objects).ToObject<IEnumerable<ContentSetLinkViewModel>>());
break;
case ExpandoObject expandoObject:
links.Add(JToken.FromObject(expandoObject).ToObject<ContentSetLinkViewModel>());
links.Add(SerializeAndDeserialize<ContentSetLinkViewModel>(expandoObject));
break;
case IEnumerable<object> collection when
collection.CastWhere<ExpandoObject>().ToList() is { } objects &&
objects.Count != 0:
links.AddRange(SerializeAndDeserialize<IEnumerable<ContentSetLinkViewModel>>(objects));
dministro marked this conversation as resolved.
Show resolved Hide resolved
break;
case string json when !string.IsNullOrWhiteSpace(json):
links.AddRange(JsonConvert.DeserializeObject<List<ContentSetLinkViewModel>>(json));
links.AddRange(JsonSerializer.Deserialize<List<ContentSetLinkViewModel>>(json));
break;
default: continue;
}
Expand All @@ -79,4 +81,7 @@ public Task CreatingAsync(
new CreatingContext(content, definition, contentSet, newKey),
$"{nameof(WorkflowContentSetEventHandler)}.{nameof(CreatingAsync)}" +
$"({content.ContentItemId}, {definition.Name}, {contentSet}, {newKey})");

private static T SerializeAndDeserialize<T>(object source) =>
JNode.FromObject(source).ToObject<T>();
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ public static class EmailSenderShellScopeExtensions
public static void SendEmailDeferred(this ShellScope shellScope, EmailParameters parameters) =>
shellScope.AddDeferredTask(async scope =>
{
var smtpService = scope.ServiceProvider.GetRequiredService<ISmtpService>();
var result = await smtpService.SendAsync(new MailMessage
var emailService = scope.ServiceProvider.GetRequiredService<IEmailService>();
var result = await emailService.SendAsync(new MailMessage
{
Sender = parameters.Sender,
To = parameters.To?.Join(","),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
using OrchardCore.DisplayManagement.Descriptors;
using System.Threading.Tasks;

namespace Lombiq.HelpfulExtensions.Extensions.Flows;

internal sealed class FlowPartShapeTableProvider : IShapeTableProvider
{
public void Discover(ShapeTableBuilder builder) => builder
.Describe("FlowPart")
.OnDisplaying(displaying => displaying.Shape.Metadata.Alternates.Add("Lombiq_HelpfulExtensions_Flows_FlowPart"));
public ValueTask DiscoverAsync(ShapeTableBuilder builder)
{
builder
.Describe("FlowPart")
.OnDisplaying(displaying => displaying.Shape.Metadata.Alternates.Add("Lombiq_HelpfulExtensions_Flows_FlowPart"));

return ValueTask.CompletedTask;
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
using Newtonsoft.Json.Linq;
using OrchardCore.ContentManagement;
using OrchardCore.ContentManagement.Metadata;
using OrchardCore.Entities;
using OrchardCore.Recipes.Models;
using OrchardCore.Users.Models;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
using System.Xml.Linq;
using System.Xml.XPath;
Expand Down Expand Up @@ -72,8 +72,8 @@ await _contentConverters
await converter.UpdateContentItemsAsync(export, contentItems);
}

var recipe = JObject.FromObject(new RecipeDescriptor());
recipe["steps"] = JArray.FromObject(new[] { new { name = "content", data = contentItems } });
var recipe = JObject.FromObject(new RecipeDescriptor())!;
recipe["steps"] = JObject.FromObject(new[] { new { name = "content", data = contentItems } });

return recipe.ToString();
}
Expand Down
2 changes: 1 addition & 1 deletion Lombiq.HelpfulExtensions/Extensions/SiteTexts/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class ContentLocalizationStartup : StartupBase
{
public override void ConfigureServices(IServiceCollection services)
{
services.RemoveImplementations<ISiteTextService>();
services.RemoveImplementationsOf<ISiteTextService>();
services.AddScoped<ISiteTextService, ContentLocalizationSiteTextService>();
}
}
Loading