diff --git a/src/Orchard.Tests/DisplayManagement/Descriptors/DefaultShapeTableManagerTests.cs b/src/Orchard.Tests/DisplayManagement/Descriptors/DefaultShapeTableManagerTests.cs index 16b3ed452..fcafd7278 100644 --- a/src/Orchard.Tests/DisplayManagement/Descriptors/DefaultShapeTableManagerTests.cs +++ b/src/Orchard.Tests/DisplayManagement/Descriptors/DefaultShapeTableManagerTests.cs @@ -6,6 +6,7 @@ using NUnit.Framework; using Orchard.Caching; using Orchard.ContentManagement; using Orchard.DisplayManagement.Descriptors; +using Orchard.DisplayManagement.Descriptors.ShapePlacementStrategy; using Orchard.DisplayManagement.Implementation; using Orchard.Environment.Extensions; using Orchard.Environment.Extensions.Models; @@ -215,7 +216,47 @@ namespace Orchard.Tests.DisplayManagement.Descriptors { Assert.That(result5, Is.EqualTo("")); Assert.That(result6, Is.EqualTo("Header:5")); } - + + [Test] + public void PathConstraintShouldMatch() { + + // all path have a trailing / as per the current implementation + // todo: (sebros) find a way to 'use' the current implementation in DefaultContentDisplay.BindPlacement instead of emulating it + + var rules = new[] { + Tuple.Create("~/my-blog", "~/my-blog/", true), + Tuple.Create("~/my-blog/", "~/my-blog/", true), + + // star match + Tuple.Create("~/my-blog*", "~/my-blog/", true), + Tuple.Create("~/my-blog*", "~/my-blog/my-post/", true), + Tuple.Create("~/my-blog/*", "~/my-blog/", true), + Tuple.Create("~/my-blog/*", "~/my-blog123/", false), + Tuple.Create("~/my-blog*", "~/my-blog123/", true) + }; + + foreach (var rule in rules) { + var path = rule.Item1; + var context = rule.Item2; + var match = rule.Item3; + + _container.Resolve().Discover = + builder => builder.Describe("Hello").From(TestFeature()) + .Placement(ShapePlacementParsingStrategy.BuildPredicate(c => true, new KeyValuePair("Path", path)), "Match"); + + var manager = _container.Resolve(); + var hello = manager.GetShapeTable(null).Descriptors["Hello"]; + var result = hello.Placement(new ShapePlacementContext {Path = context}); + + if (match) { + Assert.That(result, Is.EqualTo("Match"), String.Format("{0}|{1}", path, context)); + } + else { + Assert.That(result, Is.Null, String.Format("{0}|{1}", path, context)); + } + } + } + [Test] public void OnlyShapesFromTheGivenThemeAreProvided() { _container.Resolve(); diff --git a/src/Orchard.Web/Modules/Orchard.DesignerTools/Services/ObjectDumper.cs b/src/Orchard.Web/Modules/Orchard.DesignerTools/Services/ObjectDumper.cs index 3250f8740..b39553cd4 100644 --- a/src/Orchard.Web/Modules/Orchard.DesignerTools/Services/ObjectDumper.cs +++ b/src/Orchard.Web/Modules/Orchard.DesignerTools/Services/ObjectDumper.cs @@ -68,20 +68,15 @@ namespace Orchard.DesignerTools.Services { } private void DumpObject(object o, string name) { - if (_parents.Count >= _levels) { - _node.Add( - new XElement("div", new XAttribute("class", "name"), name), - new XElement("div", new XAttribute("class", "object last"), o) - ); - - return; - } - _node.Add( new XElement("div", new XAttribute("class", "name"), name), new XElement("div", new XAttribute("class", "type"), FormatType(o.GetType())) ); + if (_parents.Count >= _levels) { + return; + } + if (o is IDictionary) { DumpDictionary((IDictionary)o); } diff --git a/src/Orchard/ContentManagement/DefaultContentDisplay.cs b/src/Orchard/ContentManagement/DefaultContentDisplay.cs index 6fb975cc0..96921a47e 100644 --- a/src/Orchard/ContentManagement/DefaultContentDisplay.cs +++ b/src/Orchard/ContentManagement/DefaultContentDisplay.cs @@ -97,8 +97,7 @@ namespace Orchard.ContentManagement { private void BindPlacement(BuildShapeContext context, string displayType) { context.FindPlacement = (partShapeType, differentiator, defaultLocation) => { - //var workContext = _workContextAccessor.GetContext(); - //var theme = workContext.CurrentTheme; + var theme = _themeService.Value.GetRequestTheme(_requestContext); var shapeTable = _shapeTableManager.GetShapeTable(theme.Id); var request = _requestContext.HttpContext.Request; @@ -109,7 +108,7 @@ namespace Orchard.ContentManagement { ContentType = context.ContentItem.ContentType, DisplayType = displayType, Differentiator = differentiator, - Path = request.Path.Substring((request.ApplicationPath ?? "").Length) // get the current app-relative path, i.e. /my-blog + Path = VirtualPathUtility.AppendTrailingSlash(VirtualPathUtility.ToAppRelative(request.Path)) // get the current app-relative path, i.e. ~/my-blog/foo }; var location = descriptor.Placement(placementContext); return location ?? defaultLocation; diff --git a/src/Orchard/DisplayManagement/Descriptors/ShapePlacementStrategy/ShapePlacementParsingStrategy.cs b/src/Orchard/DisplayManagement/Descriptors/ShapePlacementStrategy/ShapePlacementParsingStrategy.cs index 3275b32ae..b8e10e720 100644 --- a/src/Orchard/DisplayManagement/Descriptors/ShapePlacementStrategy/ShapePlacementParsingStrategy.cs +++ b/src/Orchard/DisplayManagement/Descriptors/ShapePlacementStrategy/ShapePlacementParsingStrategy.cs @@ -2,6 +2,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using System.Web; using Orchard.Environment.Descriptor.Models; using Orchard.Environment.Extensions; using Orchard.Environment.Extensions.Models; @@ -83,7 +84,7 @@ namespace Orchard.DisplayManagement.Descriptors.ShapePlacementStrategy { } } - private Func BuildPredicate(Func predicate, KeyValuePair term) { + public static Func BuildPredicate(Func predicate, KeyValuePair term) { var expression = term.Value; switch (term.Key) { case "ContentType": @@ -99,11 +100,17 @@ namespace Orchard.DisplayManagement.Descriptors.ShapePlacementStrategy { } return ctx => (ctx.DisplayType == expression) && predicate(ctx); case "Path": - if (expression.EndsWith("*")) { - var prefix = expression.Substring(0, expression.Length - 1); - return ctx => (ctx.Path ?? "").StartsWith(prefix, StringComparison.OrdinalIgnoreCase) && predicate(ctx); + var normalizedPath = VirtualPathUtility.IsAbsolute(expression) + ? VirtualPathUtility.ToAppRelative(expression) + : VirtualPathUtility.Combine("~/", expression); + + if (normalizedPath.EndsWith("*")) { + var prefix = normalizedPath.Substring(0, normalizedPath.Length - 1); + return ctx => VirtualPathUtility.ToAppRelative(ctx.Path ?? "").StartsWith(prefix, StringComparison.OrdinalIgnoreCase) && predicate(ctx); } - return ctx => (ctx.Path.Equals(expression, StringComparison.OrdinalIgnoreCase)) && predicate(ctx); + + normalizedPath = VirtualPathUtility.AppendTrailingSlash(normalizedPath); + return ctx => (ctx.Path.Equals(normalizedPath, StringComparison.OrdinalIgnoreCase)) && predicate(ctx); } return predicate; }