mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 11:44:58 +08:00
Adding an array of alternate shapes to shapemetadata
ShapeMetadata.Alternates may be accumulated at any time after the shape is created Most recently added alternate has highest priority Alternates may target longer shape variations by appending something context specific to the base name The alternate may match a shape binding name that is part of a different descriptor --HG-- branch : dev extra : rebase_source : 864892c019dbf2a7bd1c33c71bb01be3068b5081
This commit is contained in:
@@ -20,7 +20,10 @@ namespace Orchard.Tests.DisplayManagement {
|
||||
WorkContext _workContext;
|
||||
|
||||
protected override void Register(Autofac.ContainerBuilder builder) {
|
||||
_defaultShapeTable = new ShapeTable { Descriptors = new Dictionary<string, ShapeDescriptor>() };
|
||||
_defaultShapeTable = new ShapeTable {
|
||||
Descriptors = new Dictionary<string, ShapeDescriptor>(),
|
||||
Bindings = new Dictionary<string, ShapeBinding>()
|
||||
};
|
||||
_workContext = new TestWorkContext {
|
||||
CurrentTheme = new Theme { ThemeName = "Hello" }
|
||||
};
|
||||
@@ -85,11 +88,10 @@ namespace Orchard.Tests.DisplayManagement {
|
||||
public IContainerProvider ContainerProvider { get; set; }
|
||||
|
||||
public override T Resolve<T>() {
|
||||
if (typeof(T) == typeof(ILifetimeScope))
|
||||
{
|
||||
return (T) ContainerProvider.RequestLifetime;
|
||||
if (typeof(T) == typeof(ILifetimeScope)) {
|
||||
return (T)ContainerProvider.RequestLifetime;
|
||||
}
|
||||
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -104,8 +106,10 @@ namespace Orchard.Tests.DisplayManagement {
|
||||
}
|
||||
|
||||
void AddShapeDescriptor(ShapeDescriptor shapeDescriptor) {
|
||||
_defaultShapeTable.Descriptors[shapeDescriptor.ShapeType] = shapeDescriptor;
|
||||
foreach (var binding in shapeDescriptor.Bindings) {
|
||||
_defaultShapeTable.Descriptors[binding.Key] = shapeDescriptor;
|
||||
binding.Value.ShapeDescriptor = shapeDescriptor;
|
||||
_defaultShapeTable.Bindings[binding.Key] = binding.Value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +167,7 @@ namespace Orchard.Tests.DisplayManagement {
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RenderAlternateShape() {
|
||||
public void RenderAlternateShapeExplicitly() {
|
||||
var displayManager = _container.Resolve<IDisplayManager>();
|
||||
|
||||
var shape = new Shape {
|
||||
@@ -188,5 +192,39 @@ namespace Orchard.Tests.DisplayManagement {
|
||||
var result = displayManager.Execute(CreateDisplayContext(shape));
|
||||
Assert.That(result.ToString(), Is.EqualTo("Hello again!"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RenderAlternateShapeByMostRecentlyAddedMatchingAlternate() {
|
||||
var displayManager = _container.Resolve<IDisplayManager>();
|
||||
|
||||
var shape = new Shape {
|
||||
Metadata = new ShapeMetadata {
|
||||
Type = "Foo"
|
||||
}
|
||||
};
|
||||
shape.Metadata.Alternates.Add("Foo__1");
|
||||
shape.Metadata.Alternates.Add("Foo__2");
|
||||
shape.Metadata.Alternates.Add("Foo__3");
|
||||
|
||||
var descriptor = new ShapeDescriptor {
|
||||
ShapeType = "Foo",
|
||||
};
|
||||
descriptor.Bindings["Foo"] = new ShapeBinding {
|
||||
BindingName = "Foo",
|
||||
Binding = ctx => new HtmlString("Hi there!"),
|
||||
};
|
||||
descriptor.Bindings["Foo__1"] = new ShapeBinding {
|
||||
BindingName = "Foo__1",
|
||||
Binding = ctx => new HtmlString("Hello (1)!"),
|
||||
};
|
||||
descriptor.Bindings["Foo__2"] = new ShapeBinding {
|
||||
BindingName = "Foo__2",
|
||||
Binding = ctx => new HtmlString("Hello (2)!"),
|
||||
};
|
||||
AddShapeDescriptor(descriptor);
|
||||
|
||||
var result = displayManager.Execute(CreateDisplayContext(shape));
|
||||
Assert.That(result.ToString(), Is.EqualTo("Hello (2)!"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -41,12 +41,13 @@ namespace Orchard.DisplayManagement.Descriptors {
|
||||
}));
|
||||
|
||||
return new ShapeTable {
|
||||
Descriptors = descriptors.ToDictionary(sd => sd.ShapeType)
|
||||
Descriptors = descriptors.ToDictionary(sd => sd.ShapeType),
|
||||
Bindings = descriptors.SelectMany(sd => sd.Bindings).ToDictionary(kv => kv.Key, kv => kv.Value),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool IsModuleOrRequestedTheme(ShapeAlteration alteration, string themeName) {
|
||||
if (alteration == null ||
|
||||
alteration.Feature == null ||
|
||||
|
@@ -3,5 +3,6 @@
|
||||
namespace Orchard.DisplayManagement.Descriptors {
|
||||
public class ShapeTable {
|
||||
public IDictionary<string, ShapeDescriptor> Descriptors { get; set; }
|
||||
public IDictionary<string, ShapeBinding> Bindings { get; set; }
|
||||
}
|
||||
}
|
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Web;
|
||||
@@ -50,7 +52,7 @@ namespace Orchard.DisplayManagement.Implementation {
|
||||
|
||||
ShapeDescriptor shapeDescriptor;
|
||||
ShapeBinding shapeBinding;
|
||||
if (TryGetDescriptor(shapeMetadata.Type, shapeTable, out shapeDescriptor, out shapeBinding)) {
|
||||
if (TryGetDescriptorBinding(shapeMetadata.Type, shapeMetadata.Alternates, shapeTable, out shapeDescriptor, out shapeBinding)) {
|
||||
shape.Metadata.ChildContent = Process(shapeDescriptor, shapeBinding, shape, context);
|
||||
}
|
||||
else {
|
||||
@@ -60,7 +62,7 @@ namespace Orchard.DisplayManagement.Implementation {
|
||||
foreach (var frameType in shape.Metadata.Wrappers) {
|
||||
ShapeDescriptor frameDescriptor;
|
||||
ShapeBinding frameBinding;
|
||||
if (TryGetDescriptor(frameType, shapeTable, out frameDescriptor, out frameBinding)) {
|
||||
if (TryGetDescriptorBinding(frameType, Enumerable.Empty<string>(), shapeTable, out frameDescriptor, out frameBinding)) {
|
||||
shape.Metadata.ChildContent = Process(frameDescriptor, frameBinding, shape, context);
|
||||
}
|
||||
}
|
||||
@@ -68,18 +70,32 @@ namespace Orchard.DisplayManagement.Implementation {
|
||||
return shape.Metadata.ChildContent;
|
||||
}
|
||||
|
||||
static bool TryGetDescriptor(string shapeType, ShapeTable shapeTable, out ShapeDescriptor shapeDescriptor, out ShapeBinding shapeBinding) {
|
||||
static bool TryGetDescriptorBinding(string shapeType, IEnumerable<string> shapeAlternates, ShapeTable shapeTable, out ShapeDescriptor shapeDescriptor, out ShapeBinding shapeBinding) {
|
||||
// shape alternates are optional, fully qualified binding names
|
||||
// the earliest added alternates have the lowest priority
|
||||
// the descriptor returned is based on the binding that is matched, so it may be an entirely
|
||||
// different descriptor if the alternate has a different base name
|
||||
foreach (var shapeAlternate in shapeAlternates.Reverse()) {
|
||||
if (shapeTable.Bindings.TryGetValue(shapeAlternate, out shapeBinding)) {
|
||||
shapeDescriptor = shapeBinding.ShapeDescriptor;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// when no alternates match, the shapeType is used to find the longest matching binding
|
||||
// the shapetype name can break itself into shorter fallbacks at double-underscore marks
|
||||
// so the shapetype itself may contain a longer alternate forms that falls back to a shorter one
|
||||
var shapeTypeScan = shapeType;
|
||||
for (; ; ) {
|
||||
if (shapeTable.Descriptors.TryGetValue(shapeTypeScan, out shapeDescriptor) &&
|
||||
shapeDescriptor.Bindings.TryGetValue(shapeTypeScan, out shapeBinding)) {
|
||||
if (shapeTable.Bindings.TryGetValue(shapeTypeScan, out shapeBinding)) {
|
||||
shapeDescriptor = shapeBinding.ShapeDescriptor;
|
||||
return true;
|
||||
}
|
||||
|
||||
var delimiterIndex = shapeTypeScan.LastIndexOf("__");
|
||||
if (delimiterIndex < 0) {
|
||||
shapeBinding = null;
|
||||
shapeDescriptor = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -6,11 +6,13 @@ namespace Orchard.DisplayManagement.Shapes {
|
||||
public class ShapeMetadata {
|
||||
public ShapeMetadata() {
|
||||
Wrappers = new List<string>();
|
||||
Alternates = new List<string>();
|
||||
}
|
||||
|
||||
public string Type { get; set; }
|
||||
public string Position { get; set; }
|
||||
public IList<string> Wrappers { get; set; }
|
||||
public IList<string> Alternates { get; set; }
|
||||
|
||||
public bool WasExecuted { get; set; }
|
||||
public IHtmlString ChildContent { get; set; }
|
||||
|
Reference in New Issue
Block a user