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

Add Widget alternates for alias and slug #16860

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace OrchardCore.Alias.Services;

public class AliasShapeTableProvider : ShapeTableProvider
public sealed class ContentAliasShapeTableProvider : ShapeTableProvider
{
public override ValueTask DiscoverAsync(ShapeTableBuilder builder)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using OrchardCore.Alias.Models;
using OrchardCore.ContentManagement;
using OrchardCore.DisplayManagement;
using OrchardCore.DisplayManagement.Descriptors;
using OrchardCore.DisplayManagement.Utilities;

namespace OrchardCore.Alias.Services;

public sealed class WidgetAliasShapeTableProvider : ShapeTableProvider
{
public override ValueTask DiscoverAsync(ShapeTableBuilder builder)
{
builder.Describe("Widget")
.OnDisplaying(displaying =>
{
var shape = displaying.Shape;
var contentItem = shape.GetProperty<ContentItem>("ContentItem");

var aliasPart = contentItem?.As<AliasPart>();

if (aliasPart != null)
{
var encodedAlias = aliasPart.Alias.EncodeAlternateElement();

// Widget__Alias__[Alias] e.g. Widget-Alias-example, Widget-Alias-my-page
displaying.Shape.Metadata.Alternates.Add("Widget__Alias__" + encodedAlias);

// Widget_[DisplayType]__Alias__[Alias] e.g. Widget-Alias-example.Summary, Widget-Alias-my-page.Summary
displaying.Shape.Metadata.Alternates.Add("Widget_" + displaying.Shape.Metadata.DisplayType + "__Alias__" + encodedAlias);
}
});

return ValueTask.CompletedTask;
}
}
19 changes: 18 additions & 1 deletion src/OrchardCore.Modules/OrchardCore.Alias/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using OrchardCore.ContentTypes.Editors;
using OrchardCore.Data;
using OrchardCore.Data.Migration;
using OrchardCore.DisplayManagement;
using OrchardCore.DisplayManagement.Descriptors;
using OrchardCore.Indexing;
using OrchardCore.Liquid;
Expand Down Expand Up @@ -71,7 +72,23 @@ public override void ConfigureServices(IServiceCollection services)

services.AddScoped<IContentPartIndexHandler, AliasPartIndexHandler>();
services.AddScoped<IContentTypePartDefinitionDisplayDriver, AliasPartSettingsDisplayDriver>();
}
}

services.AddScoped<IShapeTableProvider, AliasShapeTableProvider>();
[RequireFeatures("OrchardCore.Contents")]
public sealed class ContentAliasStartup : StartupBase
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddShapeTableProvider<ContentAliasShapeTableProvider>();
}
}

[RequireFeatures("OrchardCore.Widgets")]
public sealed class WidgetAliasStartup : StartupBase
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddShapeTableProvider<WidgetAliasShapeTableProvider>();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace OrchardCore.Autoroute.Services;

public class AutorouteShapeTableProvider : ShapeTableProvider
public sealed class ContentAutorouteShapeTableProvider : ShapeTableProvider
{
public override ValueTask DiscoverAsync(ShapeTableBuilder builder)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using OrchardCore.Autoroute.Models;
using OrchardCore.ContentManagement;
using OrchardCore.DisplayManagement;
using OrchardCore.DisplayManagement.Descriptors;
using OrchardCore.DisplayManagement.Utilities;

namespace OrchardCore.Autoroute.Services;

public sealed class WidgetAutorouteShapeTableProvider : ShapeTableProvider
{
public override ValueTask DiscoverAsync(ShapeTableBuilder builder)
{
builder.Describe("Widget")
.OnDisplaying(displaying =>
{
var shape = displaying.Shape;
var contentItem = shape.GetProperty<ContentItem>("ContentItem");

var autoroutePart = contentItem?.As<AutoroutePart>();

if (autoroutePart != null)
{
var encodedSlug = autoroutePart.Path.EncodeAlternateElement().Replace("/", "__");

// Widget__Slug__[Slug] e.g. Widget-Slug-example, Widget-Slug-blog-my-post
displaying.Shape.Metadata.Alternates.Add("Widget__Slug__" + encodedSlug);

// Widget_[DisplayType]__Slug__[Slug] e.g. Widget-Slug-example.Summary, Widget-Slug-blog-my-post.Summary
displaying.Shape.Metadata.Alternates.Add("Widget_" + displaying.Shape.Metadata.DisplayType + "__Slug__" + encodedSlug);
}
});

return ValueTask.CompletedTask;
}
}
23 changes: 20 additions & 3 deletions src/OrchardCore.Modules/OrchardCore.Autoroute/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
using OrchardCore.ContentTypes.Editors;
using OrchardCore.Data;
using OrchardCore.Data.Migration;
using OrchardCore.DisplayManagement;
using OrchardCore.DisplayManagement.Descriptors;
using OrchardCore.Indexing;
using OrchardCore.Liquid;
Expand Down Expand Up @@ -54,7 +55,7 @@ public override void ConfigureServices(IServiceCollection services)

if (!slug.StartsWith('/'))
{
slug = "/" + slug;
slug = '/' + slug;
}

(var found, var entry) = await autorouteEntries.TryGetEntryByPathAsync(slug);
Expand Down Expand Up @@ -98,8 +99,6 @@ public override void ConfigureServices(IServiceCollection services)

services.AddSingleton<AutorouteTransformer>();
services.AddSingleton<IShellRouteValuesAddressScheme, AutorouteValuesAddressScheme>();

services.AddScoped<IShapeTableProvider, AutorouteShapeTableProvider>();
}

public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider)
Expand All @@ -117,3 +116,21 @@ public override void ConfigureServices(IServiceCollection services)
services.AddScoped<IRouteableContentTypeProvider, AutorouteContentTypeProvider>();
}
}

[RequireFeatures("OrchardCore.Contents")]
public sealed class ContentAutourouteStartup : StartupBase
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddShapeTableProvider<ContentAutorouteShapeTableProvider>();
}
}

[RequireFeatures("OrchardCore.Widgets")]
public sealed class WidgetAutourouteStartup : StartupBase
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddShapeTableProvider<WidgetAutorouteShapeTableProvider>();
}
}
36 changes: 36 additions & 0 deletions src/docs/reference/modules/Templates/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,42 @@ This template is called when a widget is rendered on a page.
| `Model.ContentItem.Content` | A JSON object containing all the data of the content item. |
| `Model.Classes` | An array of all the classes attached to the widget. |

### `Widget__Alias__[Alias]`

This template is called when displaying a widget content item with a specific alias. It needs to have the `AliasPart` attached to it.

#### Widget with Alias Examples

| Template | Filename |
|----------------------------|--------------------------------|
| `Widget__Alias__example` | `Widget-Alias-example.cshtml` |
| `Widget__Alias__my__page` | `Widget-Alias-my-page.cshtml` |

#### Widget with Alias and Display Type Examples

| Template | Filename |
|------------------------------------|----------------------------------------|
| `Widget_Summary__Alias__example` | `Widget-Alias-example.Summary.cshtml` |
| `Widget_Summary__Alias__my__page` | `Widget-Alias-my-page.Summary.cshtml` |

### `Widget__Slug__[Slug]`

This template is called when displaying a widget content item with a specific slug (i.e., a path is assigned to the item). It needs to have the `AutoroutePart` attached to it.

#### Widget with Slug Examples

| Template | Filename |
|---------------------------------|------------------------------------|
| `Widget__Slug__example` | `Widget-Slug-example.cshtml` |
| `Widget__Slug__blog__my__post` | `Widget-Slug-blog-my-post.cshtml` |

#### Widget with Slug and Display Type Examples

| Template | Filename |
|-----------------------------------|----------------------------------------|
| `Widget_Summary__Slug__example` | `Widget-Slug-example.Summary.cshtml` |
| `Widget_Summary__Slug__blog__my__post` | `Widget-Slug-blog-my-post.Summary.cshtml` |

## Content Part templates

Each driver is free to return a shape type of its choosing, but the usage is
Expand Down
4 changes: 2 additions & 2 deletions src/docs/releases/2.1.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,9 @@ Additionally, the configuration provider key for the default provider has change

### Autoroute Feature

#### Content Item Shape Alternates Based on Alias and Slug
#### Content Item Shape Alternates Based on Alias and Slug (Content and Widget shapes)

Content item shapes can be overridden by their alias if `AliasPart` is attached or by their slug if `AutoroutePart` is attached. For examples, refer to the [docs](../reference/modules/Templates/README.md).
Content item shapes (Content and Widget local zones) can be overridden by their alias if `AliasPart` is attached or by their slug if `AutoroutePart` is attached. For examples, refer to the [docs](../reference/modules/Templates/README.md).

### Recipes Feature

Expand Down