From 0ce0dcb69b63e251ff2ee0251dd4bdee50d0a7b1 Mon Sep 17 00:00:00 2001 From: Louis DeJardin Date: Tue, 12 Oct 2010 01:02:18 -0700 Subject: [PATCH] Preparing to put a content part placement subsystem in effect ContentShapeResult.Apply calls through the context.FindPlacement to acquire placement location DefaultContentDisplay component wires the FindPlacement onto the ShapeDescriptor.Placement ShapeDescriptor.Placement func contains the chained per-theme rule stack for part shape placement Next up - simple Placement.txt parser to convert rules into Placement chain --HG-- branch : composition --- .../DefaultShapeTableManagerTests.cs | 62 +++++++++ .../Core/Common/Drivers/BodyPartDriver.cs | 22 ++-- .../Core/Contents/Views/Items/Content.cshtml | 2 +- .../Core/Routable/Drivers/RoutePartDriver.cs | 8 +- .../DefaultContentDisplay.cs | 123 ++++++++++++++++++ .../DefaultContentManager.cs | 56 +------- .../Drivers/ContentPartDriver.cs | 18 ++- .../Drivers/ContentShapeResult.cs | 52 +++++--- .../Handlers/BuildShapeContext.cs | 4 + .../ContentManagement/IContentManager.cs | 6 + .../Descriptors/ShapeAlterationBuilder.cs | 24 +++- .../Descriptors/ShapeDescriptor.cs | 4 + src/Orchard/Orchard.Framework.csproj | 1 + 13 files changed, 293 insertions(+), 89 deletions(-) create mode 100644 src/Orchard/ContentManagement/DefaultContentDisplay.cs diff --git a/src/Orchard.Tests/DisplayManagement/Descriptors/DefaultShapeTableManagerTests.cs b/src/Orchard.Tests/DisplayManagement/Descriptors/DefaultShapeTableManagerTests.cs index 00871a191..990da3959 100644 --- a/src/Orchard.Tests/DisplayManagement/Descriptors/DefaultShapeTableManagerTests.cs +++ b/src/Orchard.Tests/DisplayManagement/Descriptors/DefaultShapeTableManagerTests.cs @@ -79,5 +79,67 @@ namespace Orchard.Tests.DisplayManagement.Descriptors { Assert.That(foo.Displaying.Single(), Is.SameAs(cb3)); Assert.That(foo.Displayed.Single(), Is.SameAs(cb4)); } + + [Test] + public void DefaultPlacementIsReturnedByDefault() { + var manager = _container.Resolve(); + + var hello = manager.GetShapeTable(null).Descriptors["Hello"]; + hello.DefaultPlacement = "Header:5"; + var result = hello.Placement(null); + Assert.That(result, Is.EqualTo("Header:5")); + } + + [Test] + public void DescribedPlacementIsReturnedIfNotNull() { + + _container.Resolve().Discover = + builder => builder.Describe("Hello") + .Placement(ctx => ctx.DisplayType == "Detail" ? "Main" : null) + .Placement(ctx => ctx.DisplayType == "Summary" ? "" : null); + + var manager = _container.Resolve(); + var hello = manager.GetShapeTable(null).Descriptors["Hello"]; + var result1 = hello.Placement(new ShapePlacementContext { DisplayType = "Detail" }); + var result2 = hello.Placement(new ShapePlacementContext { DisplayType = "Summary" }); + var result3 = hello.Placement(new ShapePlacementContext { DisplayType = "Tile" }); + hello.DefaultPlacement = "Header:5"; + var result4 = hello.Placement(new ShapePlacementContext { DisplayType = "Detail" }); + var result5 = hello.Placement(new ShapePlacementContext { DisplayType = "Summary" }); + var result6 = hello.Placement(new ShapePlacementContext { DisplayType = "Tile" }); + + Assert.That(result1, Is.EqualTo("Main")); + Assert.That(result2, Is.EqualTo("")); + Assert.That(result3, Is.Null); + Assert.That(result4, Is.EqualTo("Main")); + Assert.That(result5, Is.EqualTo("")); + Assert.That(result6, Is.EqualTo("Header:5")); + } + + [Test] + public void TwoArgumentVariationDoesSameThing() { + + _container.Resolve().Discover = + builder => builder.Describe("Hello") + .Placement(ctx => ctx.DisplayType == "Detail", "Main") + .Placement(ctx => ctx.DisplayType == "Summary", ""); + + var manager = _container.Resolve(); + var hello = manager.GetShapeTable(null).Descriptors["Hello"]; + var result1 = hello.Placement(new ShapePlacementContext { DisplayType = "Detail" }); + var result2 = hello.Placement(new ShapePlacementContext { DisplayType = "Summary" }); + var result3 = hello.Placement(new ShapePlacementContext { DisplayType = "Tile" }); + hello.DefaultPlacement = "Header:5"; + var result4 = hello.Placement(new ShapePlacementContext { DisplayType = "Detail" }); + var result5 = hello.Placement(new ShapePlacementContext { DisplayType = "Summary" }); + var result6 = hello.Placement(new ShapePlacementContext { DisplayType = "Tile" }); + + Assert.That(result1, Is.EqualTo("Main")); + Assert.That(result2, Is.EqualTo("")); + Assert.That(result3, Is.Null); + Assert.That(result4, Is.EqualTo("Main")); + Assert.That(result5, Is.EqualTo("")); + Assert.That(result6, Is.EqualTo("Header:5")); + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Core/Common/Drivers/BodyPartDriver.cs b/src/Orchard.Web/Core/Common/Drivers/BodyPartDriver.cs index 694d6b59b..a9020d471 100644 --- a/src/Orchard.Web/Core/Common/Drivers/BodyPartDriver.cs +++ b/src/Orchard.Web/Core/Common/Drivers/BodyPartDriver.cs @@ -34,19 +34,17 @@ namespace Orchard.Core.Common.Drivers { } protected override DriverResult Display(BodyPart part, string displayType, dynamic shapeHelper) { - var bodyText = _htmlFilters.Aggregate(part.Text, (text, filter) => filter.ProcessContent(text)); - var body = shapeHelper.Parts_Common_Body(ContentPart: part, Html: new HtmlString(bodyText)); - if (!string.IsNullOrWhiteSpace(displayType)) - body.Metadata.Type = string.Format("{0}.{1}", body.Metadata.Type, displayType); - var location = part.GetLocation(displayType); - //return Combined( - // Services.Authorizer.Authorize(Permissions.ChangeOwner) ? ContentPartTemplate(model, "Parts/Common.Body.ManageWrapperPre").LongestMatch(displayType, "SummaryAdmin").Location(location) : null, - // Services.Authorizer.Authorize(Permissions.ChangeOwner) ? ContentPartTemplate(model, "Parts/Common.Body.Manage").LongestMatch(displayType, "SummaryAdmin").Location(location) : null, - // ContentPartTemplate(model, TemplateName, Prefix).LongestMatch(displayType, "Summary", "SummaryAdmin").Location(location), - // Services.Authorizer.Authorize(Permissions.ChangeOwner) ? ContentPartTemplate(model, "Parts/Common.Body.ManageWrapperPost").LongestMatch(displayType, "SummaryAdmin").Location(location) : null); - - return ContentShape(body).Location(location); + return Combined( + ContentShape("Parts_Common_Body", displayType == "Detail" ? "Content" : null, () => { + var bodyText = _htmlFilters.Aggregate(part.Text, (text, filter) => filter.ProcessContent(text)); + return shapeHelper.Parts_Common_Body(ContentPart: part, Html: new HtmlString(bodyText)); + }), + ContentShape("Parts_Common_Body_Summary", displayType == "Summary" ? "Content" : null, () => { + var bodyText = _htmlFilters.Aggregate(part.Text, (text, filter) => filter.ProcessContent(text)); + return shapeHelper.Parts_Common_Body_Summary(ContentPart: part, Html: new HtmlString(bodyText)); + }) + ); } protected override DriverResult Editor(BodyPart part, dynamic shapeHelper) { diff --git a/src/Orchard.Web/Core/Contents/Views/Items/Content.cshtml b/src/Orchard.Web/Core/Contents/Views/Items/Content.cshtml index 9147b7ecb..46e4e50b9 100644 --- a/src/Orchard.Web/Core/Contents/Views/Items/Content.cshtml +++ b/src/Orchard.Web/Core/Contents/Views/Items/Content.cshtml @@ -3,6 +3,6 @@ @Display(Model.Header)
-@Display(Model.Primary) +@Display(Model.Content)
\ No newline at end of file diff --git a/src/Orchard.Web/Core/Routable/Drivers/RoutePartDriver.cs b/src/Orchard.Web/Core/Routable/Drivers/RoutePartDriver.cs index fb6c81c00..5a0b308cc 100644 --- a/src/Orchard.Web/Core/Routable/Drivers/RoutePartDriver.cs +++ b/src/Orchard.Web/Core/Routable/Drivers/RoutePartDriver.cs @@ -45,11 +45,7 @@ namespace Orchard.Core.Routable.Drivers { } protected override DriverResult Display(RoutePart part, string displayType, dynamic shapeHelper) { - var routePart = shapeHelper.Parts_RoutableTitle(ContentPart: part, Title: part.Title); - if (!string.IsNullOrWhiteSpace(displayType)) - routePart.Metadata.Type = string.Format("{0}.{1}", routePart.Metadata.Type, displayType); - var location = part.GetLocation(displayType, "Header", "5"); - return ContentShape(routePart).Location(location); + return ContentShape("Parts_RoutableTitle", "Header:5", () => shapeHelper.Parts_RoutableTitle(ContentPart: part, Title: part.Title)); } protected override DriverResult Editor(RoutePart part, dynamic shapeHelper) { @@ -80,7 +76,7 @@ namespace Orchard.Core.Routable.Drivers { } protected override DriverResult Editor(RoutePart part, IUpdateModel updater, dynamic shapeHelper) { - + var model = new RoutableEditorViewModel(); updater.TryUpdateModel(model, Prefix, null, null); part.Title = model.Title; diff --git a/src/Orchard/ContentManagement/DefaultContentDisplay.cs b/src/Orchard/ContentManagement/DefaultContentDisplay.cs new file mode 100644 index 000000000..a90f29add --- /dev/null +++ b/src/Orchard/ContentManagement/DefaultContentDisplay.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web.Routing; +using Microsoft.CSharp.RuntimeBinder; +using Orchard.ContentManagement.Handlers; +using Orchard.DisplayManagement; +using Orchard.DisplayManagement.Descriptors; +using Orchard.Logging; +using Orchard.Mvc; +using Orchard.Themes; + +namespace Orchard.ContentManagement { + public class DefaultContentDisplay : IContentDisplay { + private readonly Lazy> _handlers; + private readonly IShapeHelperFactory _shapeHelperFactory; + private readonly IShapeTableManager _shapeTableManager; + private readonly IWorkContextAccessor _workContextAccessor; + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly Lazy _themeService; + private readonly RequestContext _requestContext; + + public DefaultContentDisplay( + Lazy> handlers, + IShapeHelperFactory shapeHelperFactory, + IShapeTableManager shapeTableManager, + IWorkContextAccessor workContextAccessor, + IHttpContextAccessor httpContextAccessor, + Lazy themeService, + RequestContext requestContext) { + _handlers = handlers; + _shapeHelperFactory = shapeHelperFactory; + _shapeTableManager = shapeTableManager; + _workContextAccessor = workContextAccessor; + _httpContextAccessor = httpContextAccessor; + _themeService = themeService; + _requestContext = requestContext; + Logger = NullLogger.Instance; + } + + public ILogger Logger { get; set; } + + static readonly CallSiteCollection _shapeHelperCalls = new CallSiteCollection(shapeTypeName => Binder.InvokeMember( + CSharpBinderFlags.None, + shapeTypeName, + Enumerable.Empty(), + null, + new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) })); + + + public dynamic BuildDisplay(IContent content, string displayType) { + var contentTypeDefinition = content.ContentItem.TypeDefinition; + string stereotype; + if (!contentTypeDefinition.Settings.TryGetValue("Stereotype", out stereotype)) + stereotype = "Content"; + + var shapeTypeName = "Items_" + stereotype; + var shapeDisplayType = string.IsNullOrWhiteSpace(displayType) ? "Detail" : displayType; + + var shapeHelper = _shapeHelperFactory.CreateHelper(); + var itemShape = _shapeHelperCalls.Invoke(shapeHelper, shapeTypeName); + + itemShape.ContentItem = content.ContentItem; + itemShape.Metadata.DisplayType = shapeDisplayType; + + var context = new BuildDisplayContext(itemShape, content, shapeDisplayType, _shapeHelperFactory); + BindPlacement(context, displayType); + + _handlers.Value.Invoke(handler => handler.BuildDisplay(context), Logger); + return context.Shape; + } + + public dynamic BuildEditor(IContent content) { + var shapeHelper = _shapeHelperFactory.CreateHelper(); + var itemShape = shapeHelper.Items_Content_Edit(); + + IContent iContent = content; + if (iContent != null) + itemShape.ContentItem = iContent.ContentItem; + + var context = new BuildEditorContext(itemShape, content, _shapeHelperFactory); + BindPlacement(context, null); + + _handlers.Value.Invoke(handler => handler.BuildEditor(context), Logger); + return context.Shape; + } + + public dynamic UpdateEditor(IContent content, IUpdateModel updater) { + var shapeHelper = _shapeHelperFactory.CreateHelper(); + var itemShape = shapeHelper.Items_Content_Edit(); + + IContent iContent = content; + if (iContent != null) + itemShape.ContentItem = iContent.ContentItem; + + var context = new UpdateEditorContext(itemShape, content, updater, _shapeHelperFactory); + BindPlacement(context, null); + + _handlers.Value.Invoke(handler => handler.UpdateEditor(context), Logger); + return context.Shape; + } + + private void BindPlacement(BuildShapeContext context, string displayType) { + context.FindPlacement = (partShapeType, defaultLocation) => { + //var workContext = _workContextAccessor.GetContext(); + //var theme = workContext.CurrentTheme; + var theme = _themeService.Value.GetRequestTheme(_requestContext); + var shapeTable = _shapeTableManager.GetShapeTable(theme.ThemeName); + ShapeDescriptor descriptor; + if (shapeTable.Descriptors.TryGetValue(partShapeType, out descriptor)) { + var placementContext = new ShapePlacementContext { + ContentType = context.ContentItem.ContentType, + DisplayType = displayType + }; + var location = descriptor.Placement(placementContext); + return location ?? defaultLocation; + } + return defaultLocation; + }; + } + } +} diff --git a/src/Orchard/ContentManagement/DefaultContentManager.cs b/src/Orchard/ContentManagement/DefaultContentManager.cs index 679753224..b6582c8be 100644 --- a/src/Orchard/ContentManagement/DefaultContentManager.cs +++ b/src/Orchard/ContentManagement/DefaultContentManager.cs @@ -4,14 +4,12 @@ using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using Autofac; -using Microsoft.CSharp.RuntimeBinder; using Orchard.ContentManagement.Handlers; using Orchard.ContentManagement.MetaData; using Orchard.ContentManagement.MetaData.Builders; using Orchard.ContentManagement.MetaData.Models; using Orchard.ContentManagement.Records; using Orchard.Data; -using Orchard.DisplayManagement; using Orchard.Indexing; using Orchard.Logging; @@ -23,7 +21,7 @@ namespace Orchard.ContentManagement { private readonly IRepository _contentItemVersionRepository; private readonly IContentDefinitionManager _contentDefinitionManager; private readonly Func _contentManagerSession; - private readonly IShapeHelperFactory _shapeHelperFactory; + private readonly IContentDisplay _contentDisplay; public DefaultContentManager( IComponentContext context, @@ -32,14 +30,14 @@ namespace Orchard.ContentManagement { IRepository contentItemVersionRepository, IContentDefinitionManager contentDefinitionManager, Func contentManagerSession, - IShapeHelperFactory shapeHelperFactory) { + IContentDisplay contentDisplay) { _context = context; _contentTypeRepository = contentTypeRepository; _contentItemRepository = contentItemRepository; _contentItemVersionRepository = contentItemVersionRepository; _contentDefinitionManager = contentDefinitionManager; _contentManagerSession = contentManagerSession; - _shapeHelperFactory = shapeHelperFactory; + _contentDisplay = contentDisplay; Logger = NullLogger.Instance; } @@ -370,59 +368,17 @@ namespace Orchard.ContentManagement { return context.Metadata; } - static readonly CallSiteCollection _shapeHelperCalls = new CallSiteCollection(shapeTypeName => Binder.InvokeMember( - CSharpBinderFlags.None, - shapeTypeName, - Enumerable.Empty(), - null, - new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) })); - public dynamic BuildDisplay(IContent content, string displayType = "") { - var contentTypeDefinition = content.ContentItem.TypeDefinition; - string stereotype; - if (!contentTypeDefinition.Settings.TryGetValue("Stereotype", out stereotype)) - stereotype = "Content"; - - var shapeTypeName = "Items_" + stereotype; - var shapeDisplayType = string.IsNullOrWhiteSpace(displayType) ? "Detail" : displayType; - - var shapeHelper = _shapeHelperFactory.CreateHelper(); - var itemShape = _shapeHelperCalls.Invoke(shapeHelper, shapeTypeName); - - itemShape.ContentItem = content.ContentItem; - itemShape.Metadata.DisplayType = shapeDisplayType; - - var context = new BuildDisplayContext(itemShape, content, shapeDisplayType, _shapeHelperFactory); - Handlers.Invoke(handler => handler.BuildDisplay(context), Logger); - return context.Shape; + return _contentDisplay.BuildDisplay(content, displayType); } - public dynamic BuildEditor(IContent content) { - var shapeHelper = _shapeHelperFactory.CreateHelper(); - var itemShape = shapeHelper.Items_Content_Edit(); - - IContent iContent = content; - if (iContent != null) - itemShape.ContentItem = iContent.ContentItem; - - var context = new BuildEditorContext(itemShape, content, _shapeHelperFactory); - Handlers.Invoke(handler => handler.BuildEditor(context), Logger); - return context.Shape; + return _contentDisplay.BuildEditor(content); } public dynamic UpdateEditor(IContent content, IUpdateModel updater) { - var shapeHelper = _shapeHelperFactory.CreateHelper(); - var itemShape = shapeHelper.Items_Content_Edit(); - - IContent iContent = content; - if (iContent != null) - itemShape.ContentItem = iContent.ContentItem; - - var context = new UpdateEditorContext(itemShape, content, updater, _shapeHelperFactory); - Handlers.Invoke(handler => handler.UpdateEditor(context), Logger); - return context.Shape; + return _contentDisplay.UpdateEditor(content, updater); } public IContentQuery Query() { diff --git a/src/Orchard/ContentManagement/Drivers/ContentPartDriver.cs b/src/Orchard/ContentManagement/Drivers/ContentPartDriver.cs index bf88335ea..cfe937ef0 100644 --- a/src/Orchard/ContentManagement/Drivers/ContentPartDriver.cs +++ b/src/Orchard/ContentManagement/Drivers/ContentPartDriver.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using Orchard.ContentManagement.Handlers; using Orchard.ContentManagement.MetaData; +using Orchard.DisplayManagement; namespace Orchard.ContentManagement.Drivers { public abstract class ContentPartDriver : IContentPartDriver where TContent : ContentPart, new() { @@ -27,8 +28,21 @@ namespace Orchard.ContentManagement.Drivers { protected virtual DriverResult Editor(TContent part, dynamic shapeHelper) { return null; } protected virtual DriverResult Editor(TContent part, IUpdateModel updater, dynamic shapeHelper) { return null; } - public ContentShapeResult ContentShape(dynamic shape) { - return new ContentShapeResult(shape, Prefix).Location(Zone); + [Obsolete("Provided while transitioning to factory variations")] + public ContentShapeResult ContentShape(IShape shape) { + return ContentShapeImplementation(shape.Metadata.Type, Zone, () => shape); + } + + public ContentShapeResult ContentShape(string shapeType, Func factory) { + return ContentShapeImplementation(shapeType, null, factory); + } + + public ContentShapeResult ContentShape(string shapeType, string defaultLocation, Func factory) { + return ContentShapeImplementation(shapeType, defaultLocation, factory); + } + + private ContentShapeResult ContentShapeImplementation(string shapeType, string defaultLocation, Func factory) { + return new ContentShapeResult(shapeType, Prefix, factory).Location(defaultLocation); } [Obsolete] diff --git a/src/Orchard/ContentManagement/Drivers/ContentShapeResult.cs b/src/Orchard/ContentManagement/Drivers/ContentShapeResult.cs index 0c4328abf..3c4e6af78 100644 --- a/src/Orchard/ContentManagement/Drivers/ContentShapeResult.cs +++ b/src/Orchard/ContentManagement/Drivers/ContentShapeResult.cs @@ -1,37 +1,57 @@ -using Orchard.ContentManagement.Handlers; +using System; +using Orchard.ContentManagement.Handlers; using Orchard.DisplayManagement; +using Orchard.DisplayManagement.Shapes; namespace Orchard.ContentManagement.Drivers { public class ContentShapeResult : DriverResult { - public dynamic Shape { get; set; } - public string Prefix { get; set; } - public string Zone { get; set; } - public string Position { get; set; } + private string _defaultLocation; + private readonly string _shapeType; + private readonly string _prefix; + private readonly Func _shapeBuilder; - public ContentShapeResult(dynamic shape, string prefix) { - Shape = shape; - Prefix = prefix; + public ContentShapeResult(string shapeType, string prefix, Func shapeBuilder) { + _shapeType = shapeType; + _prefix = prefix; + _shapeBuilder = shapeBuilder; } public override void Apply(BuildDisplayContext context) { - context.Shape.Zones[Zone].Add(Shape, Position); + ApplyImplementation(context, context.DisplayType); } public override void Apply(BuildEditorContext context) { - IShape iShape = Shape; - if (iShape != null ) - Shape.Metadata.Prefix = Prefix; - context.Shape.Zones[Zone].Add(Shape, Position); + ApplyImplementation(context, null); + } + + private void ApplyImplementation(BuildShapeContext context, string displayType) { + var location = context.FindPlacement(_shapeType, _defaultLocation); + if (string.IsNullOrEmpty(location) || location == "-") + return; + + dynamic parentShape = context.Shape; + IShape contentShape = _shapeBuilder(); + contentShape.Metadata.Prefix = _prefix; + contentShape.Metadata.DisplayType = displayType; + + var delimiterIndex = location.IndexOf(':'); + if (delimiterIndex < 0) { + parentShape.Zones[location].Add(contentShape); + } + else { + var zoneName = location.Substring(0, delimiterIndex); + var position = location.Substring(delimiterIndex + 1); + parentShape.Zones[zoneName].Add(contentShape, position); + } } public ContentShapeResult Location(string zone) { - Zone = zone; + _defaultLocation = zone; return this; } public ContentShapeResult Location(string zone, string position) { - Zone = zone; - Position = position; + _defaultLocation = zone + ":" + position; return this; } diff --git a/src/Orchard/ContentManagement/Handlers/BuildShapeContext.cs b/src/Orchard/ContentManagement/Handlers/BuildShapeContext.cs index e0a4b1cf8..216f27995 100644 --- a/src/Orchard/ContentManagement/Handlers/BuildShapeContext.cs +++ b/src/Orchard/ContentManagement/Handlers/BuildShapeContext.cs @@ -1,3 +1,4 @@ +using System; using Orchard.DisplayManagement; namespace Orchard.ContentManagement.Handlers { @@ -6,10 +7,13 @@ namespace Orchard.ContentManagement.Handlers { Shape = shape; ContentItem = content.ContentItem; New = shapeHelperFactory.CreateHelper(); + FindPlacement = (partType, defaultLocation) => defaultLocation; } public dynamic Shape { get; private set; } public ContentItem ContentItem { get; private set; } public dynamic New { get; private set; } + + public Func FindPlacement { get; set; } } } \ No newline at end of file diff --git a/src/Orchard/ContentManagement/IContentManager.cs b/src/Orchard/ContentManagement/IContentManager.cs index 571ed0325..127b07de3 100644 --- a/src/Orchard/ContentManagement/IContentManager.cs +++ b/src/Orchard/ContentManagement/IContentManager.cs @@ -31,6 +31,12 @@ namespace Orchard.ContentManagement { dynamic UpdateEditor(IContent content, IUpdateModel updater); } + public interface IContentDisplay : IDependency { + dynamic BuildDisplay(IContent content, string displayType = ""); + dynamic BuildEditor(IContent content); + dynamic UpdateEditor(IContent content, IUpdateModel updater); + } + public class VersionOptions { public static VersionOptions Latest { get { return new VersionOptions { IsLatest = true }; } } public static VersionOptions Published { get { return new VersionOptions { IsPublished = true }; } } diff --git a/src/Orchard/DisplayManagement/Descriptors/ShapeAlterationBuilder.cs b/src/Orchard/DisplayManagement/Descriptors/ShapeAlterationBuilder.cs index 312d469d0..93e796a46 100644 --- a/src/Orchard/DisplayManagement/Descriptors/ShapeAlterationBuilder.cs +++ b/src/Orchard/DisplayManagement/Descriptors/ShapeAlterationBuilder.cs @@ -73,7 +73,7 @@ namespace Orchard.DisplayManagement.Descriptors { descriptor.Created = existing.Concat(new[] { action }); }); } - + public ShapeAlterationBuilder OnDisplaying(Action action) { return Configure(descriptor => { var existing = descriptor.Displaying ?? Enumerable.Empty>(); @@ -88,8 +88,28 @@ namespace Orchard.DisplayManagement.Descriptors { }); } + public ShapeAlterationBuilder Placement(Func action) { + return Configure(descriptor => { + var next = descriptor.Placement; + descriptor.Placement = ctx => action(ctx) ?? next(ctx); + }); + } + + public ShapeAlterationBuilder Placement(Func predicate, string location) { + return Configure(descriptor => { + var next = descriptor.Placement; + descriptor.Placement = ctx => predicate(ctx) ? location : next(ctx); + }); + } + public ShapeAlteration Build() { return new ShapeAlteration(_shapeType, _feature, _configurations.ToArray()); } } -} \ No newline at end of file + + public class ShapePlacementContext { + public string ContentType { get; set; } + public string DisplayType { get; set; } + + } +} diff --git a/src/Orchard/DisplayManagement/Descriptors/ShapeDescriptor.cs b/src/Orchard/DisplayManagement/Descriptors/ShapeDescriptor.cs index 28ef54af0..1c7a64109 100644 --- a/src/Orchard/DisplayManagement/Descriptors/ShapeDescriptor.cs +++ b/src/Orchard/DisplayManagement/Descriptors/ShapeDescriptor.cs @@ -13,6 +13,7 @@ namespace Orchard.DisplayManagement.Descriptors { Displayed = Enumerable.Empty>(); Wrappers = new List(); Bindings = new Dictionary(); + Placement = ctx => DefaultPlacement; } public string ShapeType { get; set; } @@ -41,6 +42,9 @@ namespace Orchard.DisplayManagement.Descriptors { public IEnumerable> Displaying { get; set; } public IEnumerable> Displayed { get; set; } + public Func Placement { get; set; } + public string DefaultPlacement { get; set; } + public IList Wrappers { get; set; } } diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index d5f2f1843..b1be6b24e 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -159,6 +159,7 @@ +