From ae4bb19b6de9b9179251ab2e762a18aea17a9208 Mon Sep 17 00:00:00 2001 From: Georg von Kries Date: Thu, 12 Dec 2024 18:10:54 +0100 Subject: [PATCH] Expose properties of ITrackingConsentFeature and cookie policy in Liquid (#17148) --------- Co-authored-by: Mike Alhayek --- .../TemplateOptionsConfigurations.cs | 2 + .../Values/HttpRequestValue.cs | 3 - .../Values/TrackingConsentValue.cs | 77 +++++++++++++++++++ src/docs/reference/modules/Liquid/README.md | 30 ++++++++ 4 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 src/OrchardCore/OrchardCore.DisplayManagement.Liquid/Values/TrackingConsentValue.cs diff --git a/src/OrchardCore/OrchardCore.DisplayManagement.Liquid/TemplateOptionsConfigurations.cs b/src/OrchardCore/OrchardCore.DisplayManagement.Liquid/TemplateOptionsConfigurations.cs index bb9f2a639ae..472777e8ce6 100644 --- a/src/OrchardCore/OrchardCore.DisplayManagement.Liquid/TemplateOptionsConfigurations.cs +++ b/src/OrchardCore/OrchardCore.DisplayManagement.Liquid/TemplateOptionsConfigurations.cs @@ -46,6 +46,8 @@ public void Configure(TemplateOptions options) options.Scope.SetValue("HttpContext", new HttpContextValue()); + options.Scope.SetValue("TrackingConsent", new TrackingConsentValue()); + options.MemberAccessStrategy.Register((forms, name) => { if (name == "Keys") diff --git a/src/OrchardCore/OrchardCore.DisplayManagement.Liquid/Values/HttpRequestValue.cs b/src/OrchardCore/OrchardCore.DisplayManagement.Liquid/Values/HttpRequestValue.cs index 4e3205ec694..fab95d4c9e4 100644 --- a/src/OrchardCore/OrchardCore.DisplayManagement.Liquid/Values/HttpRequestValue.cs +++ b/src/OrchardCore/OrchardCore.DisplayManagement.Liquid/Values/HttpRequestValue.cs @@ -12,9 +12,6 @@ internal sealed class HttpRequestValue : FluidValue { public override FluidValues Type => FluidValues.Object; - /// - /// Creates a new instance of a for the specified HTTP request. - /// public override bool Equals(FluidValue other) { if (other is null) diff --git a/src/OrchardCore/OrchardCore.DisplayManagement.Liquid/Values/TrackingConsentValue.cs b/src/OrchardCore/OrchardCore.DisplayManagement.Liquid/Values/TrackingConsentValue.cs new file mode 100644 index 00000000000..93c5da2d62f --- /dev/null +++ b/src/OrchardCore/OrchardCore.DisplayManagement.Liquid/Values/TrackingConsentValue.cs @@ -0,0 +1,77 @@ +using Fluid; +using Fluid.Values; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using OrchardCore.Liquid; + +#nullable enable + +namespace OrchardCore.DisplayManagement.Liquid.Values; + +/// +/// Exposes properties to Liquid. +/// +/// +/// Exposes the following properties: +/// - CanTrack +/// - HasConsent +/// - IsConsentNeeded +/// - CookieName +/// - CookieValue +/// +internal sealed class TrackingConsentValue : FluidValue +{ + public override FluidValues Type => FluidValues.Object; + + public override bool Equals(FluidValue other) + => other is TrackingConsentValue; + + public override bool ToBooleanValue() => true; + + public override decimal ToNumberValue() => 0; + + public override object ToObjectValue() => null!; + + public override string ToStringValue() => "TrackingConsent"; + + protected override FluidValue GetValue(string name, TemplateContext context) + { + var feature = GetTrackingFeature(context); + + if (feature is null) + { + return NilValue.Instance; + } + + return name switch + { + nameof(ITrackingConsentFeature.CanTrack) => BooleanValue.Create(feature.CanTrack), + nameof(ITrackingConsentFeature.HasConsent) => BooleanValue.Create(feature.HasConsent), + nameof(ITrackingConsentFeature.IsConsentNeeded) => BooleanValue.Create(feature.IsConsentNeeded), + "CookieName" => new StringValue(GetCookiePolicyOptions(context)?.ConsentCookie?.Name ?? string.Empty), + "CookieValue" => new StringValue(GetCookiePolicyOptions(context)?.ConsentCookieValue ?? string.Empty), + _ => NilValue.Instance + }; + } + + private static ITrackingConsentFeature? GetTrackingFeature(TemplateContext context) + { + var ctx = context as LiquidTemplateContext + ?? throw new InvalidOperationException($"An implementation of '{nameof(LiquidTemplateContext)}' is required"); + + var httpContext = ctx.Services.GetRequiredService().HttpContext; + + return httpContext?.Features.Get(); + } + + private static CookiePolicyOptions? GetCookiePolicyOptions(TemplateContext context) + { + var ctx = context as LiquidTemplateContext + ?? throw new InvalidOperationException($"An implementation of '{nameof(LiquidTemplateContext)}' is required"); + + return ctx.Services.GetService>()?.Value; + } +} diff --git a/src/docs/reference/modules/Liquid/README.md b/src/docs/reference/modules/Liquid/README.md index 08732401f20..63a48b3e5cc 100644 --- a/src/docs/reference/modules/Liquid/README.md +++ b/src/docs/reference/modules/Liquid/README.md @@ -559,6 +559,36 @@ Removes key from HttpContext.Items collection `{% httpcontext_remove_items "Item1" %}` +### TrackingConsent + +Represents the tracking consent feature of the current request. + +The following properties are available on the `TrackingConsent` object. + +| Property | Example | Description | +| --------- | ---- |------------ | +| `CanTrack` | `true` | Indicates if tracking is allowed. | +| `HasConsent` | `true` | Indicates if the user has given consent for tracking. | +| `IsConsentNeeded` | `false` | Indicates if consent is needed for tracking. | +| `CookieName` | `ConsentCookie` | The name of the consent cookie. | +| `CookieValue` | `true` | The value of the consent cookie. | + +#### Usage + +Here is an example of how to use the `TrackingConsent` object in a Liquid template: + +```liquid +{% if TrackingConsent.CanTrack %} + {% if TrackingConsent.HasConsent %} +

Tracking is allowed and the user has given consent.

+ {% else %} +

Tracking is allowed but the user has not given consent.

+ {% endif %} +{% else %} +

Tracking is not allowed.

+{% endif %} +``` + ## Shape Filters These filters let you create and filter shapes.