Browse Source

Merge branch 'master' of github.com:Squidex/squidex

pull/528/head
Sebastian 6 years ago
parent
commit
8f33f6a7f4
  1. 105
      backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleEventFormatter.cs
  2. 48
      backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs

105
backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleEventFormatter.cs

@ -13,6 +13,7 @@ using System.Reflection;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json;
using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.Rules.EnrichedEvents; using Squidex.Domain.Apps.Core.Rules.EnrichedEvents;
using Squidex.Domain.Apps.Core.Scripting; using Squidex.Domain.Apps.Core.Scripting;
@ -27,9 +28,9 @@ namespace Squidex.Domain.Apps.Core.HandleRules
public class RuleEventFormatter public class RuleEventFormatter
{ {
private const string Fallback = "null"; private const string Fallback = "null";
private static readonly Regex RegexPatternOld = new Regex(@"^(?<Type>[^_]*)_(?<Path>[^\s]*)", RegexOptions.Compiled); private static readonly Regex RegexPatternOld = new Regex(@"^(?<FullPath>(?<Type>[^_]*)_(?<Path>[^\s]*))", RegexOptions.Compiled);
private static readonly Regex RegexPatternNew = new Regex(@"^\{(?<Type>[^_]*)_(?<Path>[^\s]*)\}", RegexOptions.Compiled); private static readonly Regex RegexPatternNew = new Regex(@"^\{(?<FullPath>(?<Type>[^_]*)_(?<Path>[^\s]*))([\s]*\|[\s]*(?<Transform>.*)){0,1}\}", RegexOptions.Compiled);
private readonly List<(char[] Pattern, Func<EnrichedEvent, string?> Replacer)> patterns = new List<(char[] Pattern, Func<EnrichedEvent, string?> Replacer)>(); private readonly List<(string Pattern, Func<EnrichedEvent, string?> Replacer)> patterns = new List<(string Pattern, Func<EnrichedEvent, string?> Replacer)>();
private readonly IJsonSerializer jsonSerializer; private readonly IJsonSerializer jsonSerializer;
private readonly IUrlGenerator urlGenerator; private readonly IUrlGenerator urlGenerator;
private readonly IScriptEngine scriptEngine; private readonly IScriptEngine scriptEngine;
@ -63,7 +64,7 @@ namespace Squidex.Domain.Apps.Core.HandleRules
private void AddPattern(string placeholder, Func<EnrichedEvent, string?> generator) private void AddPattern(string placeholder, Func<EnrichedEvent, string?> generator)
{ {
patterns.Add((placeholder.ToCharArray(), generator)); patterns.Add((placeholder, generator));
} }
public virtual string ToPayload<T>(T @event) public virtual string ToPayload<T>(T @event)
@ -107,7 +108,7 @@ namespace Squidex.Domain.Apps.Core.HandleRules
{ {
parts.Add((currentOffset, i - currentOffset, default)); parts.Add((currentOffset, i - currentOffset, default));
var (replacement, length) = GetReplacement(span.Slice(i + 1), @event); var (replacement, length) = GetReplacement(span.Slice(i + 1).ToString(), @event);
if (length > 0) if (length > 0)
{ {
@ -139,35 +140,61 @@ namespace Squidex.Domain.Apps.Core.HandleRules
return sb.ToString(); return sb.ToString();
} }
private (string Result, int Length) GetReplacement(ReadOnlySpan<char> test, EnrichedEvent @event) private (string Result, int Length) GetReplacement(string test, EnrichedEvent @event)
{ {
for (var j = 0; j < patterns.Count; j++) var (isNewRegex, match) = Match(test);
if (match.Success)
{ {
var (pattern, replacer) = patterns[j]; var (length, text) = ResolveOldPatterns(match, isNewRegex, @event);
if (test.StartsWith(pattern, StringComparison.OrdinalIgnoreCase)) if (length == 0)
{ {
return (replacer(@event) ?? Fallback, pattern.Length); (length, text) = ResolveFromPath(match, @event);
} }
return (TransformText(text, match.Groups["Transform"]?.Value), length);
} }
var currentString = test.ToString(); return (Fallback, 0);
}
var match = RegexPatternNew.Match(currentString); private (bool IsNew, Match) Match(string test)
{
var match = RegexPatternNew.Match(test);
if (!match.Success) if (match.Success)
{ {
match = RegexPatternOld.Match(currentString); return (true, match);
} }
if (match.Success) return (false, RegexPatternOld.Match(test));
}
private (int Length, string? Result) ResolveOldPatterns(Match match, bool isNewRegex, EnrichedEvent @event)
{
var fullPath = match.Groups["FullPath"].Value;
for (var j = 0; j < patterns.Count; j++)
{ {
var path = match.Groups["Path"].Value.Split('.', StringSplitOptions.RemoveEmptyEntries); var (pattern, replacer) = patterns[j];
if (fullPath.StartsWith(pattern, StringComparison.OrdinalIgnoreCase))
{
var result = replacer(@event);
return (CalculateData(@event, path) ?? Fallback, match.Length); if (isNewRegex)
{
return (match.Length, result);
}
else
{
return (pattern.Length, result);
}
}
} }
return (Fallback, 0); return default;
} }
private static string TimestampDate(EnrichedEvent @event) private static string TimestampDate(EnrichedEvent @event)
@ -300,6 +327,48 @@ namespace Squidex.Domain.Apps.Core.HandleRules
return null; return null;
} }
private static string TransformText(string? text, string? transform)
{
if (text != null && !string.IsNullOrWhiteSpace(transform))
{
var transformations = transform.Split("|", StringSplitOptions.RemoveEmptyEntries);
foreach (var transformation in transformations)
{
switch (transformation.Trim().ToLowerInvariant())
{
case "lower":
text = text.ToLowerInvariant();
break;
case "upper":
text = text.ToUpperInvariant();
break;
case "escape":
text = JsonConvert.ToString(text);
text = text[1..^1];
break;
case "slugify":
text = text.Slugify();
break;
case "trim":
text = text.Trim();
break;
}
}
}
return text ?? Fallback;
}
private (int Length, string? Result) ResolveFromPath(Match match, EnrichedEvent @event)
{
var path = match.Groups["Path"].Value.Split('.', StringSplitOptions.RemoveEmptyEntries);
var result = CalculateData(@event, path);
return (match.Length, result);
}
private static string? CalculateData(object @event, string[] path) private static string? CalculateData(object @event, string[] path)
{ {
object? current = @event; object? current = @event;

48
backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs

@ -528,5 +528,53 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules
Assert.Equal("Created", result); Assert.Equal("Created", result);
} }
[Theory]
[InlineData("Found in ${ASSET_FILENAME | Upper}.docx", "Found in DONALD DUCK.docx")]
[InlineData("Found in ${ASSET_FILENAME| Upper }.docx", "Found in DONALD DUCK.docx")]
[InlineData("Found in ${ASSET_FILENAME|Upper }.docx", "Found in DONALD DUCK.docx")]
public void Should_transform_replacements_and_igore_whitepsaces(string script, string expect)
{
var @event = new EnrichedAssetEvent { FileName = "Donald Duck" };
var result = sut.Format(script, @event);
Assert.Equal(expect, result);
}
[Theory]
[InlineData("Found in ${ASSET_FILENAME | Escape | Upper}.docx", "Found in DONALD\\\"DUCK .docx")]
[InlineData("Found in ${ASSET_FILENAME | Escape}.docx", "Found in Donald\\\"Duck .docx")]
[InlineData("Found in ${ASSET_FILENAME | Upper}.docx", "Found in DONALD\"DUCK .docx")]
[InlineData("Found in ${ASSET_FILENAME | Lower}.docx", "Found in donald\"duck .docx")]
[InlineData("Found in ${ASSET_FILENAME | Slugify}.docx", "Found in donald-duck.docx")]
[InlineData("Found in ${ASSET_FILENAME | Trim}.docx", "Found in Donald\"Duck.docx")]
public void Should_transform_replacements(string script, string expect)
{
var @event = new EnrichedAssetEvent { FileName = "Donald\"Duck " };
var result = sut.Format(script, @event);
Assert.Equal(expect, result);
}
[Theory]
[InlineData("From ${USER_NAME | Escape | Upper}", "From DONALD\\\"DUCK ")]
[InlineData("From ${USER_NAME | Escape}", "From Donald\\\"Duck ")]
[InlineData("From ${USER_NAME | Upper}", "From DONALD\"DUCK ")]
[InlineData("From ${USER_NAME | Lower}", "From donald\"duck ")]
[InlineData("From ${USER_NAME | Slugify}", "From donald-duck")]
[InlineData("From ${USER_NAME | Trim}", "From Donald\"Duck")]
public void Should_transform_replacements_with_simple_pattern(string script, string expect)
{
var @event = new EnrichedContentEvent { User = user };
A.CallTo(() => user.Claims)
.Returns(new List<Claim> { new Claim(SquidexClaimTypes.DisplayName, "Donald\"Duck ") });
var result = sut.Format(script, @event);
Assert.Equal(expect, result);
}
} }
} }

Loading…
Cancel
Save