mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-07-17 03:40:06 +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.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Web;
|
||||||
|
using System.Web.Mvc;
|
||||||
|
using Autofac;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using Orchard.DisplayManagement.Descriptors;
|
||||||
|
using Orchard.DisplayManagement.Implementation;
|
||||||
|
using Orchard.DisplayManagement.Shapes;
|
||||||
|
using Orchard.Themes;
|
||||||
|
|
||||||
namespace Orchard.Tests.DisplayManagement {
|
namespace Orchard.Tests.DisplayManagement {
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class DefaultDisplayManagerTests {
|
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,10 +32,10 @@ namespace Orchard.DisplayManagement.Descriptors {
|
|||||||
|
|
||||||
Func<DisplayContext, IHtmlString> target = null;
|
Func<DisplayContext, IHtmlString> target = null;
|
||||||
|
|
||||||
descriptor.BindingSource = bindingSource;
|
var binding = new ShapeBinding {
|
||||||
|
BindingName = _shapeType,
|
||||||
// announce the binding, which may be reconfigured before it's used
|
BindingSource = bindingSource,
|
||||||
descriptor.Binding = displayContext => {
|
Binding = displayContext => {
|
||||||
|
|
||||||
// when used, first realize the actual target once
|
// when used, first realize the actual target once
|
||||||
if (target == null)
|
if (target == null)
|
||||||
@ -43,7 +43,10 @@ namespace Orchard.DisplayManagement.Descriptors {
|
|||||||
|
|
||||||
// and execute the re
|
// and execute the re
|
||||||
return target(displayContext);
|
return target(displayContext);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
descriptor.Bindings[_shapeType] = binding;
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +64,6 @@ namespace Orchard.DisplayManagement.Descriptors {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ShapeAlteration Build() {
|
public ShapeAlteration Build() {
|
||||||
return new ShapeAlteration(_shapeType, _feature, _configurations.ToArray());
|
return new ShapeAlteration(_shapeType, _feature, _configurations.ToArray());
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ namespace Orchard.DisplayManagement.Descriptors {
|
|||||||
Creating = Enumerable.Empty<Action<ShapeCreatingContext>>();
|
Creating = Enumerable.Empty<Action<ShapeCreatingContext>>();
|
||||||
Created = Enumerable.Empty<Action<ShapeCreatedContext>>();
|
Created = Enumerable.Empty<Action<ShapeCreatedContext>>();
|
||||||
Wrappers = new List<string>();
|
Wrappers = new List<string>();
|
||||||
|
Bindings = new Dictionary<string, ShapeBinding>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ShapeType { get; set; }
|
public string ShapeType { get; set; }
|
||||||
@ -18,13 +19,29 @@ namespace Orchard.DisplayManagement.Descriptors {
|
|||||||
/// The BindingSource is informational text about the source of the Binding delegate. Not used except for
|
/// The BindingSource is informational text about the source of the Binding delegate. Not used except for
|
||||||
/// troubleshooting.
|
/// troubleshooting.
|
||||||
/// </summary>
|
/// </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 IDictionary<string, ShapeBinding> Bindings { get; set; }
|
||||||
|
|
||||||
public IEnumerable<Action<ShapeCreatingContext>> Creating { get; set; }
|
public IEnumerable<Action<ShapeCreatingContext>> Creating { get; set; }
|
||||||
public IEnumerable<Action<ShapeCreatedContext>> Created { get; set; }
|
public IEnumerable<Action<ShapeCreatedContext>> Created { get; set; }
|
||||||
|
|
||||||
public IList<string> Wrappers { 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);
|
var shapeTable = _shapeTableManager.GetShapeTable(workContext.CurrentTheme.ThemeName);
|
||||||
//preproc loop / event (alter shape, swapping type)
|
//preproc loop / event (alter shape, swapping type)
|
||||||
|
|
||||||
|
|
||||||
ShapeDescriptor shapeDescriptor;
|
ShapeDescriptor shapeDescriptor;
|
||||||
if (shapeTable.Descriptors.TryGetValue(shapeMetadata.Type, out shapeDescriptor)) {
|
ShapeBinding shapeBinding;
|
||||||
shape.Metadata.ChildContent = Process(shapeDescriptor, shape, context);
|
if (TryGetDescriptor(shapeMetadata.Type, shapeTable, out shapeDescriptor, out shapeBinding)) {
|
||||||
|
shape.Metadata.ChildContent = Process(shapeDescriptor, shapeBinding, shape, context);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new OrchardException(T("Shape type {0} not found", shapeMetadata.Type));
|
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) {
|
foreach (var frameType in shape.Metadata.Wrappers) {
|
||||||
ShapeDescriptor frameDescriptor;
|
ShapeDescriptor frameDescriptor;
|
||||||
if (shapeTable.Descriptors.TryGetValue(frameType, out frameDescriptor)) {
|
ShapeBinding frameBinding;
|
||||||
shape.Metadata.ChildContent = Process(frameDescriptor, shape, context);
|
if (TryGetDescriptor(frameType, shapeTable, out frameDescriptor, out frameBinding)) {
|
||||||
|
shape.Metadata.ChildContent = Process(frameDescriptor, frameBinding, shape, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return shape.Metadata.ChildContent;
|
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)
|
if (value == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -78,12 +100,13 @@ namespace Orchard.DisplayManagement.Implementation {
|
|||||||
return new HtmlString(HttpUtility.HtmlEncode(value));
|
return new HtmlString(HttpUtility.HtmlEncode(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
private IHtmlString Process(ShapeDescriptor shapeDescriptor, IShape shape, DisplayContext context) {
|
static IHtmlString Process(ShapeDescriptor shapeDescriptor, ShapeBinding shapeBinding, IShape shape, DisplayContext context) {
|
||||||
if (shapeDescriptor == null || shapeDescriptor.Binding == null) {
|
|
||||||
|
if (shapeDescriptor == null || shapeBinding == null || shapeBinding.Binding == null) {
|
||||||
//todo: create result from all child shapes
|
//todo: create result from all child shapes
|
||||||
return shape.Metadata.ChildContent ?? new HtmlString("");
|
return shape.Metadata.ChildContent ?? new HtmlString("");
|
||||||
}
|
}
|
||||||
return CoerceHtmlString(shapeDescriptor.Binding(context));
|
return CoerceHtmlString(shapeBinding.Binding(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
class ForgivingConvertBinder : ConvertBinder {
|
class ForgivingConvertBinder : ConvertBinder {
|
||||||
|
Loading…
Reference in New Issue
Block a user