mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-07-16 04:42:53 +08:00
Making the ShapeDescriptor.Bindings multiply occuring information
The same descriptor has all variants registered in the bindings collection The descriptor is registered in the table under each of those names --HG-- branch : theming
This commit is contained in:
parent
6bfde2891c
commit
bab30e826d
@ -2,11 +2,183 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using Autofac;
|
||||
using NUnit.Framework;
|
||||
using Orchard.DisplayManagement.Descriptors;
|
||||
using Orchard.DisplayManagement.Implementation;
|
||||
using Orchard.DisplayManagement.Shapes;
|
||||
using Orchard.Themes;
|
||||
|
||||
namespace Orchard.Tests.DisplayManagement {
|
||||
[TestFixture]
|
||||
public class DefaultDisplayManagerTests {
|
||||
|
||||
[TestFixture]
|
||||
public class DefaultDisplayManagerTests : ContainerTestBase {
|
||||
ShapeTable _defaultShapeTable;
|
||||
WorkContext _workContext;
|
||||
|
||||
protected override void Register(Autofac.ContainerBuilder builder) {
|
||||
_defaultShapeTable = new ShapeTable { Descriptors = new Dictionary<string, ShapeDescriptor>() };
|
||||
_workContext = new TestWorkContext {
|
||||
CurrentTheme = new Theme { ThemeName = "Hello" }
|
||||
};
|
||||
|
||||
|
||||
builder.RegisterType<DefaultDisplayManager>().As<IDisplayManager>();
|
||||
builder.RegisterType<TestShapeTableManager>().As<IShapeTableManager>();
|
||||
builder.RegisterType<TestWorkContextAccessor>().As<IWorkContextAccessor>();
|
||||
builder.Register(ctx => _defaultShapeTable);
|
||||
builder.Register(ctx => _workContext);
|
||||
}
|
||||
|
||||
public class Theme : ITheme {
|
||||
public string ThemeName { get; set; }
|
||||
public string DisplayName { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Version { get; set; }
|
||||
public string Author { get; set; }
|
||||
public string HomePage { get; set; }
|
||||
public string Tags { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class TestShapeTableManager : IShapeTableManager {
|
||||
private readonly ShapeTable _defaultShapeTable;
|
||||
|
||||
public TestShapeTableManager(ShapeTable defaultShapeTable) {
|
||||
_defaultShapeTable = defaultShapeTable;
|
||||
}
|
||||
|
||||
public ShapeTable GetShapeTable(string themeName) {
|
||||
return _defaultShapeTable;
|
||||
}
|
||||
}
|
||||
|
||||
public class TestWorkContextAccessor : IWorkContextAccessor {
|
||||
private readonly WorkContext _workContext;
|
||||
public TestWorkContextAccessor(WorkContext workContext) {
|
||||
_workContext = workContext;
|
||||
}
|
||||
|
||||
public WorkContext GetContext(HttpContextBase httpContext) {
|
||||
return _workContext;
|
||||
}
|
||||
|
||||
public IWorkContextScope CreateWorkContextScope(HttpContextBase httpContext) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public WorkContext GetContext() {
|
||||
return _workContext;
|
||||
}
|
||||
|
||||
public IWorkContextScope CreateWorkContextScope() {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class TestWorkContext : WorkContext {
|
||||
readonly IDictionary<string, object> _state = new Dictionary<string, object>();
|
||||
|
||||
public override T Resolve<T>() {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override T GetState<T>(string name) {
|
||||
object value;
|
||||
return _state.TryGetValue(name, out value) ? (T)value : default(T);
|
||||
}
|
||||
|
||||
public override void SetState<T>(string name, T value) {
|
||||
_state[name] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void AddShapeDescriptor(ShapeDescriptor shapeDescriptor) {
|
||||
foreach (var binding in shapeDescriptor.Bindings) {
|
||||
_defaultShapeTable.Descriptors[binding.Key] = shapeDescriptor;
|
||||
}
|
||||
}
|
||||
|
||||
static DisplayContext CreateDisplayContext(Shape shape) {
|
||||
return new DisplayContext {
|
||||
Value = shape,
|
||||
ViewContext = new ViewContext()
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RenderSimpleShape() {
|
||||
var displayManager = _container.Resolve<IDisplayManager>();
|
||||
|
||||
var shape = new Shape {
|
||||
Metadata = new ShapeMetadata {
|
||||
Type = "Foo"
|
||||
}
|
||||
};
|
||||
|
||||
var descriptor = new ShapeDescriptor {
|
||||
ShapeType = "Foo",
|
||||
};
|
||||
descriptor.Bindings["Foo"] = new ShapeBinding {
|
||||
BindingName = "Foo",
|
||||
Binding = ctx => new HtmlString("Hi there!"),
|
||||
};
|
||||
AddShapeDescriptor(descriptor);
|
||||
|
||||
var result = displayManager.Execute(CreateDisplayContext(shape));
|
||||
Assert.That(result.ToString(), Is.EqualTo("Hi there!"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RenderFallbackShape() {
|
||||
var displayManager = _container.Resolve<IDisplayManager>();
|
||||
|
||||
var shape = new Shape {
|
||||
Metadata = new ShapeMetadata {
|
||||
Type = "Foo__2"
|
||||
}
|
||||
};
|
||||
|
||||
var descriptor = new ShapeDescriptor {
|
||||
ShapeType = "Foo",
|
||||
};
|
||||
descriptor.Bindings["Foo"] = new ShapeBinding {
|
||||
BindingName = "Foo",
|
||||
Binding = ctx => new HtmlString("Hi there!"),
|
||||
};
|
||||
AddShapeDescriptor(descriptor);
|
||||
|
||||
var result = displayManager.Execute(CreateDisplayContext(shape));
|
||||
Assert.That(result.ToString(), Is.EqualTo("Hi there!"));
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void RenderAlternateShape() {
|
||||
var displayManager = _container.Resolve<IDisplayManager>();
|
||||
|
||||
var shape = new Shape {
|
||||
Metadata = new ShapeMetadata {
|
||||
Type = "Foo__2"
|
||||
}
|
||||
};
|
||||
|
||||
var descriptor = new ShapeDescriptor {
|
||||
ShapeType = "Foo",
|
||||
};
|
||||
descriptor.Bindings["Foo"] = new ShapeBinding {
|
||||
BindingName = "Foo",
|
||||
Binding = ctx => new HtmlString("Hi there!"),
|
||||
};
|
||||
descriptor.Bindings["Foo__2"] = new ShapeBinding {
|
||||
BindingName = "Foo__2",
|
||||
Binding = ctx => new HtmlString("Hello again!"),
|
||||
};
|
||||
AddShapeDescriptor(descriptor);
|
||||
|
||||
var result = displayManager.Execute(CreateDisplayContext(shape));
|
||||
Assert.That(result.ToString(), Is.EqualTo("Hello again!"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,18 +32,21 @@ namespace Orchard.DisplayManagement.Descriptors {
|
||||
|
||||
Func<DisplayContext, IHtmlString> target = null;
|
||||
|
||||
descriptor.BindingSource = bindingSource;
|
||||
var binding = new ShapeBinding {
|
||||
BindingName = _shapeType,
|
||||
BindingSource = bindingSource,
|
||||
Binding = displayContext => {
|
||||
|
||||
// announce the binding, which may be reconfigured before it's used
|
||||
descriptor.Binding = displayContext => {
|
||||
// when used, first realize the actual target once
|
||||
if (target == null)
|
||||
target = binder(descriptor);
|
||||
|
||||
// when used, first realize the actual target once
|
||||
if (target == null)
|
||||
target = binder(descriptor);
|
||||
|
||||
// and execute the re
|
||||
return target(displayContext);
|
||||
// and execute the re
|
||||
return target(displayContext);
|
||||
}
|
||||
};
|
||||
descriptor.Bindings[_shapeType] = binding;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@ -61,9 +64,8 @@ namespace Orchard.DisplayManagement.Descriptors {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public ShapeAlteration Build() {
|
||||
return new ShapeAlteration(_shapeType, _feature, _configurations.ToArray());
|
||||
}
|
||||
public ShapeAlteration Build() {
|
||||
return new ShapeAlteration(_shapeType, _feature, _configurations.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
@ -10,21 +10,38 @@ namespace Orchard.DisplayManagement.Descriptors {
|
||||
Creating = Enumerable.Empty<Action<ShapeCreatingContext>>();
|
||||
Created = Enumerable.Empty<Action<ShapeCreatedContext>>();
|
||||
Wrappers = new List<string>();
|
||||
Bindings = new Dictionary<string, ShapeBinding>();
|
||||
}
|
||||
|
||||
public string ShapeType { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The BindingSource is informational text about the source of the Binding delegate. Not used except for
|
||||
/// troubleshooting.
|
||||
/// </summary>
|
||||
public string BindingSource { get; set; }
|
||||
public string BindingSource {
|
||||
get {
|
||||
return Bindings[ShapeType].BindingSource;
|
||||
}
|
||||
}
|
||||
|
||||
public Func<DisplayContext, IHtmlString> Binding { get; set; }
|
||||
public Func<DisplayContext, IHtmlString> Binding {
|
||||
get {
|
||||
return Bindings[ShapeType].Binding;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Action<ShapeCreatingContext>> Creating {get;set;}
|
||||
public IEnumerable<Action<ShapeCreatedContext>> Created {get;set;}
|
||||
public IDictionary<string, ShapeBinding> Bindings { get; set; }
|
||||
|
||||
public IEnumerable<Action<ShapeCreatingContext>> Creating { get; set; }
|
||||
public IEnumerable<Action<ShapeCreatedContext>> Created { get; set; }
|
||||
|
||||
public IList<string> Wrappers { get; set; }
|
||||
}
|
||||
|
||||
public class ShapeBinding {
|
||||
public string BindingName { get; set; }
|
||||
public string BindingSource { get; set; }
|
||||
public Func<DisplayContext, IHtmlString> Binding { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -49,9 +49,11 @@ namespace Orchard.DisplayManagement.Implementation {
|
||||
var shapeTable = _shapeTableManager.GetShapeTable(workContext.CurrentTheme.ThemeName);
|
||||
//preproc loop / event (alter shape, swapping type)
|
||||
|
||||
|
||||
ShapeDescriptor shapeDescriptor;
|
||||
if (shapeTable.Descriptors.TryGetValue(shapeMetadata.Type, out shapeDescriptor)) {
|
||||
shape.Metadata.ChildContent = Process(shapeDescriptor, shape, context);
|
||||
ShapeBinding shapeBinding;
|
||||
if (TryGetDescriptor(shapeMetadata.Type, shapeTable, out shapeDescriptor, out shapeBinding)) {
|
||||
shape.Metadata.ChildContent = Process(shapeDescriptor, shapeBinding, shape, context);
|
||||
}
|
||||
else {
|
||||
throw new OrchardException(T("Shape type {0} not found", shapeMetadata.Type));
|
||||
@ -59,15 +61,35 @@ namespace Orchard.DisplayManagement.Implementation {
|
||||
|
||||
foreach (var frameType in shape.Metadata.Wrappers) {
|
||||
ShapeDescriptor frameDescriptor;
|
||||
if (shapeTable.Descriptors.TryGetValue(frameType, out frameDescriptor)) {
|
||||
shape.Metadata.ChildContent = Process(frameDescriptor, shape, context);
|
||||
ShapeBinding frameBinding;
|
||||
if (TryGetDescriptor(frameType, shapeTable, out frameDescriptor, out frameBinding)) {
|
||||
shape.Metadata.ChildContent = Process(frameDescriptor, frameBinding, shape, context);
|
||||
}
|
||||
}
|
||||
|
||||
return shape.Metadata.ChildContent;
|
||||
}
|
||||
|
||||
private IHtmlString CoerceHtmlString(object value) {
|
||||
static bool TryGetDescriptor(string shapeType, ShapeTable shapeTable, out ShapeDescriptor shapeDescriptor, out ShapeBinding shapeBinding) {
|
||||
|
||||
var shapeTypeScan = shapeType;
|
||||
for (; ; ) {
|
||||
if (shapeTable.Descriptors.TryGetValue(shapeTypeScan, out shapeDescriptor) &&
|
||||
shapeDescriptor.Bindings.TryGetValue(shapeTypeScan, out shapeBinding)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var delimiterIndex = shapeTypeScan.LastIndexOf("__");
|
||||
if (delimiterIndex < 0) {
|
||||
shapeBinding = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
shapeTypeScan = shapeTypeScan.Substring(0, delimiterIndex);
|
||||
}
|
||||
}
|
||||
|
||||
static IHtmlString CoerceHtmlString(object value) {
|
||||
if (value == null)
|
||||
return null;
|
||||
|
||||
@ -78,12 +100,13 @@ namespace Orchard.DisplayManagement.Implementation {
|
||||
return new HtmlString(HttpUtility.HtmlEncode(value));
|
||||
}
|
||||
|
||||
private IHtmlString Process(ShapeDescriptor shapeDescriptor, IShape shape, DisplayContext context) {
|
||||
if (shapeDescriptor == null || shapeDescriptor.Binding == null) {
|
||||
static IHtmlString Process(ShapeDescriptor shapeDescriptor, ShapeBinding shapeBinding, IShape shape, DisplayContext context) {
|
||||
|
||||
if (shapeDescriptor == null || shapeBinding == null || shapeBinding.Binding == null) {
|
||||
//todo: create result from all child shapes
|
||||
return shape.Metadata.ChildContent ?? new HtmlString("");
|
||||
}
|
||||
return CoerceHtmlString(shapeDescriptor.Binding(context));
|
||||
return CoerceHtmlString(shapeBinding.Binding(context));
|
||||
}
|
||||
|
||||
class ForgivingConvertBinder : ConvertBinder {
|
||||
|
Loading…
Reference in New Issue
Block a user