Skip to content

Commit ac07f28

Browse files
committed
Add bulk display liquid filters.
1 parent eb787bb commit ac07f28

5 files changed

Lines changed: 124 additions & 0 deletions

File tree

Lombiq.HelpfulExtensions/Extensions/Liquid/Readme.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,13 @@ Adds various Liquid tags and filters. For more information about Liquid in Orcha
1111
## Filters
1212

1313
- `is_not_empty`: Returns `true` if the input is not null and not empty.
14+
- `shapes_build_display: 'Summary'`: Behaves the same way as the built-in `shape_build_display` filter, except both the input and output are arrays for bulk operation (e.g. from queries).
15+
- `shapes_render`: Behaves the same way as the built-in `shape_render` filter, except both the input and output are arrays for bulk operation (e.g. from queries).
16+
17+
### Array filter example
18+
19+
You can use `shapes_build_display` and `shapes_render` to easily display items from a query. For example, using the query in the "blog" recipe:
20+
21+
```liquid
22+
{{ Queries['RecentBlogPosts'] | query | shapes_build_display: 'Summary' | shapes_render }}
23+
```
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using Fluid;
2+
using Fluid.Values;
3+
using OrchardCore.Liquid;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Threading.Tasks;
7+
8+
namespace Lombiq.HelpfulExtensions.Extensions.Liquid.Services;
9+
10+
public abstract class ArrayFilterBase : ILiquidFilter
11+
{
12+
private readonly ILiquidFilter _filter;
13+
14+
protected ArrayFilterBase(ILiquidFilter filter) =>
15+
_filter = filter;
16+
17+
public async ValueTask<FluidValue> ProcessAsync(
18+
FluidValue input,
19+
FilterArguments arguments,
20+
LiquidTemplateContext context)
21+
{
22+
var results = new List<FluidValue>();
23+
24+
if (input.Type == FluidValues.Array && input is ArrayValue arrayValue)
25+
{
26+
foreach (var value in arrayValue.Values)
27+
{
28+
await AddAsync(results, value, arguments, context);
29+
}
30+
}
31+
else if (input.Type == FluidValues.Object)
32+
{
33+
await AddAsync(results, input, arguments, context);
34+
}
35+
36+
return await ThenAsync(results, input, arguments, context);
37+
}
38+
39+
protected virtual ValueTask<FluidValue> ThenAsync(
40+
IList<FluidValue> results,
41+
FluidValue input,
42+
FilterArguments arguments,
43+
LiquidTemplateContext context) =>
44+
ValueTask.FromResult(FluidValue.Create(results.ToArray(), context.Options));
45+
46+
private async ValueTask AddAsync(
47+
List<FluidValue> results,
48+
FluidValue value,
49+
FilterArguments arguments,
50+
LiquidTemplateContext context)
51+
{
52+
if (!value.ToBooleanValue()) return;
53+
54+
var result = await _filter.ProcessAsync(value, arguments, context);
55+
if (result.ToBooleanValue()) results.Add(result);
56+
}
57+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using OrchardCore.Contents.Liquid;
2+
3+
namespace Lombiq.HelpfulExtensions.Extensions.Liquid.Services;
4+
5+
public class ShapesBuildDisplayFilter : ArrayFilterBase
6+
{
7+
public ShapesBuildDisplayFilter(BuildDisplayFilter buildDisplayFilter)
8+
: base(buildDisplayFilter)
9+
{
10+
}
11+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using Fluid;
2+
using Fluid.Values;
3+
using Microsoft.AspNetCore.Html;
4+
using OrchardCore.DisplayManagement.Liquid;
5+
using OrchardCore.DisplayManagement.Liquid.Filters;
6+
using OrchardCore.Liquid;
7+
using System.Collections.Generic;
8+
using System.Threading.Tasks;
9+
10+
namespace Lombiq.HelpfulExtensions.Extensions.Liquid.Services;
11+
12+
public class ShapesRenderFilter : ArrayFilterBase
13+
{
14+
public ShapesRenderFilter(ShapeRenderFilter shapeRenderFilter)
15+
: base(shapeRenderFilter)
16+
{
17+
}
18+
19+
protected override ValueTask<FluidValue> ThenAsync(
20+
IList<FluidValue> results,
21+
FluidValue input,
22+
FilterArguments arguments,
23+
LiquidTemplateContext context)
24+
{
25+
var combined = new HtmlContentBuilder();
26+
27+
foreach (var result in results)
28+
{
29+
if (result.ToObjectValue() is IHtmlContent htmlContent)
30+
{
31+
combined.AppendHtml(htmlContent);
32+
}
33+
else
34+
{
35+
combined.Append(result.ToStringValue());
36+
}
37+
38+
combined.AppendHtml("\n");
39+
}
40+
41+
return ValueTask.FromResult(FluidValue.Create(combined, context.Options));
42+
}
43+
}

Lombiq.HelpfulExtensions/Extensions/Liquid/Startup.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using Lombiq.HelpfulExtensions.Extensions.Liquid.Services;
12
using Microsoft.Extensions.DependencyInjection;
23
using OrchardCore.Liquid;
34
using OrchardCore.Modules;
@@ -12,5 +13,7 @@ public override void ConfigureServices(IServiceCollection services)
1213
services.AddLiquidParserBlock<IfNotEmptyParserBlock>("ifnotempty");
1314
services.AddLiquidFilter<IsNotEmptyFilter>("is_not_empty");
1415
services.AddLiquidParserTag<AssignArrayParserBlock>("assign_array");
16+
services.AddLiquidFilter<ShapesBuildDisplayFilter>("shapes_build_display");
17+
services.AddLiquidFilter<ShapesRenderFilter>("shapes_render");
1518
}
1619
}

0 commit comments

Comments
 (0)