mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-14 02:44:52 +08:00
More theming work
Continued work towards making zone classes obsolete Shape table construction per theme Adding display helper to webforms view classes --HG-- branch : theming
This commit is contained in:
@@ -1 +1 @@
|
||||
ccaf72b5e2d5fea43a6f15b3a912b631e3c0302d Clay
|
||||
3bc513c8049ad19173130a0e0e6a5486ee8247d2 Clay
|
||||
|
@@ -75,7 +75,6 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\lib\Castle Windsor 2.0\bin\Castle.DynamicProxy2.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ClaySharp, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL" />
|
||||
<Reference Include="FluentNHibernate, Version=1.0.0.593, Culture=neutral, PublicKeyToken=8aa435e3cb308880, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\lib\fluentnhibernate\FluentNHibernate.dll</HintPath>
|
||||
@@ -233,6 +232,7 @@
|
||||
<Compile Include="Stubs\StubVirtualPathMonitor.cs" />
|
||||
<Compile Include="Stubs\StubCacheManager.cs" />
|
||||
<Compile Include="Stubs\StubWebSiteFolder.cs" />
|
||||
<Compile Include="UI\ShapeTests.cs" />
|
||||
<Compile Include="Utility\ContainerExtensions.cs" />
|
||||
<Compile Include="Environment\TestDependencies\TestDependency.cs" />
|
||||
<Compile Include="Environment\Blueprint\DefaultShellDescriptorCacheTests.cs" />
|
||||
@@ -272,6 +272,10 @@
|
||||
<Compile Include="Utility\ReflectTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Clay\src\ClaySharp\ClaySharp.csproj">
|
||||
<Project>{76BCD43B-7BA5-4B63-B1E1-861641CA2686}</Project>
|
||||
<Name>ClaySharp</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Orchard\Orchard.Framework.csproj">
|
||||
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>
|
||||
<Name>Orchard.Framework</Name>
|
||||
|
136
src/Orchard.Tests/UI/ShapeTests.cs
Normal file
136
src/Orchard.Tests/UI/ShapeTests.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Autofac;
|
||||
using ClaySharp;
|
||||
using NUnit.Framework;
|
||||
using Orchard.DisplayManagement;
|
||||
using Orchard.DisplayManagement.Descriptors;
|
||||
using Orchard.DisplayManagement.Implementation;
|
||||
using Orchard.Environment;
|
||||
using Orchard.Mvc;
|
||||
using Orchard.UI.Zones;
|
||||
|
||||
namespace Orchard.Tests.UI {
|
||||
[TestFixture]
|
||||
public class ShapeTests : ContainerTestBase {
|
||||
private WorkContext _workContext;
|
||||
|
||||
protected override void Register(ContainerBuilder builder) {
|
||||
builder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>();
|
||||
builder.RegisterType<DefaultWorkContextAccessor>().As<IWorkContextAccessor>();
|
||||
builder.RegisterType<DefaultShapeFactory>().As<IShapeFactory>();
|
||||
builder.RegisterType<DefaultShapeTableManager>().As<IShapeTableManager>();
|
||||
builder.RegisterType<PageWorkContext>().As<IWorkContextStateProvider>();
|
||||
builder.RegisterType<CoreShapes>().As<IShapeDescriptorBindingStrategy>();
|
||||
builder.RegisterType<NumberIsAlwaysFortyTwo>().As<IShapeFactoryEvents>();
|
||||
}
|
||||
|
||||
protected override void Resolve(IContainer container) {
|
||||
_workContext = container.Resolve<IWorkContextAccessor>().CreateWorkContextScope().WorkContext;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WorkContextPageIsLayoutShape() {
|
||||
var page = _workContext.Page;
|
||||
IShapeMetadata pageMetadata = page.Metadata;
|
||||
Assert.That(pageMetadata.Type, Is.EqualTo("Layout"));
|
||||
Assert.That(page.Metadata.Type, Is.EqualTo("Layout"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PagePropertiesAreNil() {
|
||||
var page = _workContext.Page;
|
||||
var pageFoo = page.Foo;
|
||||
Assert.That(pageFoo == null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PageZonesPropertyIsNotNil() {
|
||||
var page = _workContext.Page;
|
||||
var pageZones = page.Zones;
|
||||
Assert.That(pageZones != null);
|
||||
Assert.That(pageZones.Foo == null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddingToZonePropertyMakesItExist() {
|
||||
var page = _workContext.Page;
|
||||
Assert.That(page.Zones.Foo == null);
|
||||
|
||||
var pageZonesFoo = page.Zones.Foo;
|
||||
pageZonesFoo.Add("hello");
|
||||
|
||||
Assert.That(page.Zones.Foo != null);
|
||||
Assert.That(page.Foo != null);
|
||||
Assert.That(page.Foo.Metadata.Type, Is.EqualTo("Zone"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddingToZoneIndexedMakesItExist() {
|
||||
var page = _workContext.Page;
|
||||
Assert.That(page.Zones["Foo"] == null);
|
||||
|
||||
var pageZonesFoo = page.Zones["Foo"];
|
||||
pageZonesFoo.Add("hello");
|
||||
|
||||
Assert.That(page.Zones["Foo"] != null);
|
||||
Assert.That(page["Foo"] != null);
|
||||
Assert.That(page["Foo"].Metadata.Type, Is.EqualTo("Zone"));
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void CallingAddOnNilPropertyMakesItBecomeZone() {
|
||||
var page = _workContext.Page;
|
||||
Assert.That(page.Foo == null);
|
||||
|
||||
page.Foo.Add("hello");
|
||||
|
||||
Assert.That(page.Foo != null);
|
||||
Assert.That(page.Foo.Metadata.Type, Is.EqualTo("Zone"));
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void ZoneContentsAreEnumerable() {
|
||||
var page = _workContext.Page;
|
||||
Assert.That(page.Foo == null);
|
||||
|
||||
page.Foo.Add("hello");
|
||||
page.Foo.Add("world");
|
||||
|
||||
var list = new List<object>();
|
||||
foreach (var item in page.Foo) {
|
||||
list.Add(item);
|
||||
}
|
||||
|
||||
Assert.That(list.Count(), Is.EqualTo(2));
|
||||
Assert.That(list.First(), Is.EqualTo("hello"));
|
||||
Assert.That(list.Last(), Is.EqualTo("world"));
|
||||
}
|
||||
|
||||
|
||||
class NumberIsAlwaysFortyTwo : ShapeFactoryEvents {
|
||||
public override void Creating(ShapeCreatingContext context) {
|
||||
context.Behaviors.Add(new Behavior());
|
||||
}
|
||||
|
||||
class Behavior : ClayBehavior {
|
||||
public override object GetMember(Func<object> proceed, object self, string name) {
|
||||
return name == "Number" ? 42 : proceed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NumberIsFortyTwo() {
|
||||
var page = _workContext.Page;
|
||||
Assert.That(page.Number, Is.EqualTo(42));
|
||||
Assert.That(page.Foo.Number == null);
|
||||
page.Foo.Add("yarg");
|
||||
Assert.That(page.Foo.Number, Is.EqualTo(42));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
using System.Web.Mvc;
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.Mvc.Filters;
|
||||
using Orchard.UI;
|
||||
|
||||
namespace Orchard.Core.Feeds.Services {
|
||||
[UsedImplicitly]
|
||||
@@ -14,7 +15,8 @@ namespace Orchard.Core.Feeds.Services {
|
||||
}
|
||||
|
||||
public void OnResultExecuting(ResultExecutingContext filterContext) {
|
||||
_workContextAccessor.GetContext(filterContext).Page.Zones["Head"].Add(html => html.ViewContext.Writer.Write(_feedManager.GetRegisteredLinks(html)), ":after");
|
||||
IPage page =_workContextAccessor.GetContext(filterContext).Page;
|
||||
page.Zones["Head"].Add((HtmlHelper html) => html.ViewContext.Writer.Write(_feedManager.GetRegisteredLinks(html)), ":after");
|
||||
}
|
||||
|
||||
public void OnResultExecuted(ResultExecutedContext filterContext) {}
|
||||
|
@@ -13,6 +13,7 @@ using Orchard.Data.Providers;
|
||||
using Orchard.Data.Migration;
|
||||
using Orchard.DisplayManagement;
|
||||
using Orchard.DisplayManagement.Descriptors;
|
||||
using Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy;
|
||||
using Orchard.DisplayManagement.Implementation;
|
||||
using Orchard.DisplayManagement.Shapes;
|
||||
using Orchard.Environment;
|
||||
@@ -31,6 +32,7 @@ using Orchard.Themes;
|
||||
using Orchard.UI.Notify;
|
||||
using Orchard.UI.PageClass;
|
||||
using Orchard.UI.PageTitle;
|
||||
using Orchard.UI.Zones;
|
||||
|
||||
namespace Orchard.Setup {
|
||||
public class SetupMode : Module {
|
||||
@@ -41,8 +43,8 @@ namespace Orchard.Setup {
|
||||
builder.RegisterModule(new CommandModule());
|
||||
builder.RegisterType<RoutePublisher>().As<IRoutePublisher>().InstancePerLifetimeScope();
|
||||
builder.RegisterType<ModelBinderPublisher>().As<IModelBinderPublisher>().InstancePerLifetimeScope();
|
||||
builder.RegisterType<WebFormViewEngineProvider>().As<IViewEngineProvider>().InstancePerLifetimeScope();
|
||||
builder.RegisterType<RazorViewEngineProvider>().As<IViewEngineProvider>().InstancePerLifetimeScope();
|
||||
builder.RegisterType<WebFormViewEngineProvider>().As<IViewEngineProvider>().As<IShapeTemplateViewEngine>().InstancePerLifetimeScope();
|
||||
builder.RegisterType<RazorViewEngineProvider>().As<IViewEngineProvider>().As<IShapeTemplateViewEngine>().InstancePerLifetimeScope();
|
||||
builder.RegisterType<ThemedViewResultFilter>().As<IFilterProvider>().InstancePerLifetimeScope();
|
||||
builder.RegisterType<ThemeFilter>().As<IFilterProvider>().InstancePerLifetimeScope();
|
||||
builder.RegisterType<PageTitleBuilder>().As<IPageTitleBuilder>().InstancePerLifetimeScope();
|
||||
@@ -52,7 +54,7 @@ namespace Orchard.Setup {
|
||||
builder.RegisterType<DataServicesProviderFactory>().As<IDataServicesProviderFactory>().InstancePerLifetimeScope();
|
||||
builder.RegisterType<DefaultCommandManager>().As<ICommandManager>().InstancePerLifetimeScope();
|
||||
builder.RegisterType<HelpCommand>().As<ICommandHandler>().InstancePerLifetimeScope();
|
||||
builder.RegisterType<DefaultWorkContextAccessor>().As<IWorkContextAccessor>();
|
||||
builder.RegisterType<DefaultWorkContextAccessor>().As<IWorkContextAccessor>().InstancePerMatchingLifetimeScope("shell");
|
||||
|
||||
// setup mode specific implementations of needed service interfaces
|
||||
builder.RegisterType<SafeModeThemeService>().As<IThemeService>().InstancePerLifetimeScope();
|
||||
@@ -72,7 +74,11 @@ namespace Orchard.Setup {
|
||||
builder.RegisterType<ThemeAwareViewEngine>().As<IThemeAwareViewEngine>();
|
||||
builder.RegisterType<LayoutAwareViewEngine>().As<ILayoutAwareViewEngine>();
|
||||
builder.RegisterType<ConfiguredEnginesCache>().As<IConfiguredEnginesCache>();
|
||||
builder.RegisterType<PageWorkContextStateProvider>().As<IWorkContextStateProvider>().As<IShapeEvents>();
|
||||
builder.RegisterType<PageWorkContext>().As<IWorkContextStateProvider>();
|
||||
|
||||
builder.RegisterType<CoreShapes>().As<IShapeDescriptorBindingStrategy>();
|
||||
builder.RegisterType<ShapeTemplateBindingStrategy>().As<IShapeDescriptorBindingStrategy>();
|
||||
builder.RegisterType<BasicShapeTemplateHarvester>().As<IShapeTemplateHarvester>();
|
||||
}
|
||||
|
||||
|
||||
|
@@ -105,6 +105,7 @@
|
||||
<Content Include="Themes\Contoso\Views\Orchard.Search\Search\Index.ascx" />
|
||||
<Content Include="Themes\Corporate\Views\DisplayTemplates\Parts\Blogs.BlogPost.Metadata.ascx" />
|
||||
<Content Include="Themes\Green\Views\Orchard.Search\Search\Index.ascx" />
|
||||
<Content Include="Themes\SafeMode\Views\Zone.ascx" />
|
||||
<Content Include="Themes\TheAdmin\Scripts\admin.js" />
|
||||
<Content Include="Themes\TheAdmin\Styles\ie.css" />
|
||||
<Content Include="Themes\TheAdmin\Styles\images\menuClosed.gif" />
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<BaseViewModel>" %>
|
||||
<%@ Import Namespace="Orchard.Mvc.ViewModels" %>
|
||||
<% //todo: (heskew) this should really be using the IResourceManager if it's to be a theme especially for the jquery dep (w/out needing to copy into this theme...)
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl" %>
|
||||
|
||||
<%-- //todo: (heskew) this should really be using the IResourceManager if it's to be a theme especially for the jquery dep (w/out needing to copy into this theme...)
|
||||
var jquery = ResolveUrl("~/Modules/Orchard.Themes/Scripts/jquery-1.4.2.js");
|
||||
Model.Zones.AddAction("head:scripts", html =>
|
||||
html.ViewContext.Writer.Write(@"<script type=""text/javascript"" src=""" + jquery + @"""></script>"));
|
||||
@@ -15,10 +15,12 @@
|
||||
html.ViewContext.Writer.Write(@"<link rel=""stylesheet"" type=""text/css"" href=""" + siteCss + @"""/>"));
|
||||
var ie6Css = ResolveUrl("../Styles/ie6.css");
|
||||
Model.Zones.AddAction("head:styles", html =>
|
||||
html.ViewContext.Writer.Write(@"<!--[if lte IE 6]><link rel=""stylesheet"" type=""text/css"" media=""screen, projection"" href=""" + ie6Css + @"""/><![endif]-->")); %>
|
||||
html.ViewContext.Writer.Write(@"<!--[if lte IE 6]><link rel=""stylesheet"" type=""text/css"" media=""screen, projection"" href=""" + ie6Css + @"""/><![endif]-->"));
|
||||
--%>
|
||||
<div id="header">
|
||||
<div id="branding"><h1>Welcome to Orchard</h1></div>
|
||||
</div>
|
||||
<div id="main">
|
||||
<%Html.ZoneBody("content"); %>
|
||||
</div>
|
||||
|
||||
<%: Display(Model.Content) %>
|
||||
</div>
|
||||
|
4
src/Orchard.Web/Themes/SafeMode/Views/Zone.ascx
Normal file
4
src/Orchard.Web/Themes/SafeMode/Views/Zone.ascx
Normal file
@@ -0,0 +1,4 @@
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl" %>
|
||||
<div class="zone zone-<%:Model.ZoneName %>">
|
||||
<%foreach (var item in Model.Items) {%><%:Display(item)%><%}%>
|
||||
</div>
|
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Orchard.DisplayManagement.Descriptors {
|
||||
@@ -9,30 +10,41 @@ namespace Orchard.DisplayManagement.Descriptors {
|
||||
_bindingStrategies = bindingStrategies;
|
||||
}
|
||||
|
||||
private ShapeTable _shapeTable;
|
||||
ConcurrentDictionary<string, ShapeTable> _tables = new ConcurrentDictionary<string, ShapeTable>();
|
||||
|
||||
public ShapeTable GetShapeTable(string themeName) {
|
||||
if (_shapeTable == null) {
|
||||
return _tables.GetOrAdd(themeName ?? "", x => {
|
||||
var builder = new ShapeTableBuilder();
|
||||
foreach (var bindingStrategy in _bindingStrategies) {
|
||||
bindingStrategy.Discover(builder);
|
||||
}
|
||||
// placeholder - alterations will need to be selective and in a particular order
|
||||
|
||||
// GroupBy has been determined to preserve the order of items in original series
|
||||
_shapeTable = new ShapeTable {
|
||||
Descriptors = builder.Build()
|
||||
.GroupBy(alteration => alteration.ShapeType)
|
||||
.Select(group => group.Aggregate(
|
||||
new ShapeDescriptor { ShapeType = group.Key },
|
||||
(d, a) => {
|
||||
a.Alter(d);
|
||||
return d;
|
||||
}))
|
||||
.ToDictionary(sd => sd.ShapeType)
|
||||
|
||||
var alterations = builder.Build()
|
||||
.Where(alteration => IsModuleOrRequestedTheme(alteration, themeName));
|
||||
|
||||
var descriptors = alterations.GroupBy(alteration => alteration.ShapeType)
|
||||
.Select(group => group.Aggregate(
|
||||
new ShapeDescriptor { ShapeType = group.Key },
|
||||
(descriptor, alteration) => {
|
||||
alteration.Alter(descriptor);
|
||||
return descriptor;
|
||||
}));
|
||||
|
||||
return new ShapeTable {
|
||||
Descriptors = descriptors.ToDictionary(sd => sd.ShapeType)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
static bool IsModuleOrRequestedTheme(ShapeDescriptorAlteration alteration, string themeName) {
|
||||
if (alteration == null ||
|
||||
alteration.Feature == null ||
|
||||
alteration.Feature.Extension == null) {
|
||||
return false;
|
||||
}
|
||||
return _shapeTable;
|
||||
|
||||
return alteration.Feature.Extension.ExtensionType == "Module" ||
|
||||
(alteration.Feature.Extension.ExtensionType == "Theme" && alteration.Feature.Name == themeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Orchard.DisplayManagement.Implementation;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.DisplayManagement.Descriptors {
|
||||
|
||||
@@ -18,104 +13,4 @@ namespace Orchard.DisplayManagement.Descriptors {
|
||||
public interface IShapeDescriptorBindingStrategy : IDependency {
|
||||
void Discover(ShapeTableBuilder builder);
|
||||
}
|
||||
|
||||
public class ShapeTable {
|
||||
public IDictionary<string, ShapeDescriptor> Descriptors { get; set; }
|
||||
}
|
||||
|
||||
public class ShapeDescriptor {
|
||||
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 Func<DisplayContext, IHtmlString> Binding { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class ShapeTableBuilder {
|
||||
readonly IList<ShapeDescriptorAlterationBuilderImpl> _descriptorBuilders = new List<ShapeDescriptorAlterationBuilderImpl>();
|
||||
|
||||
public ShapeDescriptorAlterationBuilder Describe {
|
||||
get {
|
||||
var db = new ShapeDescriptorAlterationBuilderImpl();
|
||||
_descriptorBuilders.Add(db);
|
||||
return db;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<ShapeDescriptorAlteration> Build() {
|
||||
return _descriptorBuilders.Select(b => b.Build());
|
||||
}
|
||||
|
||||
class ShapeDescriptorAlterationBuilderImpl : ShapeDescriptorAlterationBuilder {
|
||||
public ShapeDescriptorAlteration Build() {
|
||||
return new ShapeDescriptorAlteration(_shapeType, _feature, _configurations.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ShapeDescriptorAlteration {
|
||||
private readonly IList<Action<ShapeDescriptor>> _configurations;
|
||||
|
||||
public ShapeDescriptorAlteration(string shapeType, FeatureDescriptor feature, IList<Action<ShapeDescriptor>> configurations) {
|
||||
_configurations = configurations;
|
||||
ShapeType = shapeType;
|
||||
Feature = feature;
|
||||
}
|
||||
|
||||
public string ShapeType { get; private set; }
|
||||
public FeatureDescriptor Feature { get; private set; }
|
||||
public void Alter(ShapeDescriptor descriptor) {
|
||||
foreach (var configuration in _configurations) {
|
||||
configuration(descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ShapeDescriptorAlterationBuilder {
|
||||
protected FeatureDescriptor _feature;
|
||||
protected string _shapeType;
|
||||
protected readonly IList<Action<ShapeDescriptor>> _configurations = new List<Action<ShapeDescriptor>>();
|
||||
|
||||
public ShapeDescriptorAlterationBuilder Named(string shapeType) {
|
||||
_shapeType = shapeType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ShapeDescriptorAlterationBuilder From(FeatureDescriptor feature) {
|
||||
_feature = feature;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ShapeDescriptorAlterationBuilder Configure(Action<ShapeDescriptor> action) {
|
||||
_configurations.Add(action);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ShapeDescriptorAlterationBuilder BoundAs(string bindingSource, Func<ShapeDescriptor, Func<DisplayContext, IHtmlString>> binder) {
|
||||
// schedule the configuration
|
||||
return Configure(descriptor => {
|
||||
|
||||
Func<DisplayContext, IHtmlString> target = null;
|
||||
|
||||
descriptor.BindingSource = bindingSource;
|
||||
|
||||
// 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);
|
||||
|
||||
// and execute the re
|
||||
return target(displayContext);
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
22
src/Orchard/DisplayManagement/Descriptors/ShapeDescriptor.cs
Normal file
22
src/Orchard/DisplayManagement/Descriptors/ShapeDescriptor.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Web;
|
||||
using Orchard.DisplayManagement.Implementation;
|
||||
|
||||
namespace Orchard.DisplayManagement.Descriptors {
|
||||
public class ShapeDescriptor {
|
||||
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 Func<DisplayContext, IHtmlString> Binding { get; set; }
|
||||
|
||||
public IEnumerable<Action<ShapeCreatingContext>> Creating {get;set;}
|
||||
|
||||
public IEnumerable<Action<ShapeCreatedContext>> Created {get;set;}
|
||||
}
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
|
||||
namespace Orchard.DisplayManagement.Descriptors {
|
||||
public class ShapeDescriptorAlteration {
|
||||
private readonly IList<Action<ShapeDescriptor>> _configurations;
|
||||
|
||||
public ShapeDescriptorAlteration(string shapeType, FeatureDescriptor feature, IList<Action<ShapeDescriptor>> configurations) {
|
||||
_configurations = configurations;
|
||||
ShapeType = shapeType;
|
||||
Feature = feature;
|
||||
}
|
||||
|
||||
public string ShapeType { get; private set; }
|
||||
public FeatureDescriptor Feature { get; private set; }
|
||||
public void Alter(ShapeDescriptor descriptor) {
|
||||
foreach (var configuration in _configurations) {
|
||||
configuration(descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Orchard.DisplayManagement.Implementation;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
|
||||
namespace Orchard.DisplayManagement.Descriptors {
|
||||
public class ShapeDescriptorAlterationBuilder {
|
||||
protected FeatureDescriptor _feature;
|
||||
protected string _shapeType;
|
||||
protected readonly IList<Action<ShapeDescriptor>> _configurations = new List<Action<ShapeDescriptor>>();
|
||||
|
||||
public ShapeDescriptorAlterationBuilder Named(string shapeType) {
|
||||
_shapeType = shapeType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ShapeDescriptorAlterationBuilder From(FeatureDescriptor feature) {
|
||||
_feature = feature;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ShapeDescriptorAlterationBuilder Configure(Action<ShapeDescriptor> action) {
|
||||
_configurations.Add(action);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ShapeDescriptorAlterationBuilder BoundAs(string bindingSource, Func<ShapeDescriptor, Func<DisplayContext, IHtmlString>> binder) {
|
||||
// schedule the configuration
|
||||
return Configure(descriptor => {
|
||||
|
||||
Func<DisplayContext, IHtmlString> target = null;
|
||||
|
||||
descriptor.BindingSource = bindingSource;
|
||||
|
||||
// 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);
|
||||
|
||||
// and execute the re
|
||||
return target(displayContext);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public ShapeDescriptorAlterationBuilder OnCreating(Action<ShapeCreatingContext> action) {
|
||||
return Configure(descriptor => {
|
||||
var existing = descriptor.Creating ?? Enumerable.Empty<Action<ShapeCreatingContext>>();
|
||||
descriptor.Creating = existing.Concat(new[] { action });
|
||||
});
|
||||
}
|
||||
|
||||
public ShapeDescriptorAlterationBuilder OnCreated(Action<ShapeCreatedContext> action) {
|
||||
return Configure(descriptor => {
|
||||
var existing = descriptor.Created ?? Enumerable.Empty<Action<ShapeCreatedContext>>();
|
||||
descriptor.Created = existing.Concat(new[] { action });
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
7
src/Orchard/DisplayManagement/Descriptors/ShapeTable.cs
Normal file
7
src/Orchard/DisplayManagement/Descriptors/ShapeTable.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.DisplayManagement.Descriptors {
|
||||
public class ShapeTable {
|
||||
public IDictionary<string, ShapeDescriptor> Descriptors { get; set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Orchard.DisplayManagement.Descriptors {
|
||||
public class ShapeTableBuilder {
|
||||
readonly IList<ShapeDescriptorAlterationBuilderImpl> _descriptorBuilders = new List<ShapeDescriptorAlterationBuilderImpl>();
|
||||
|
||||
public ShapeDescriptorAlterationBuilder Describe {
|
||||
get {
|
||||
var db = new ShapeDescriptorAlterationBuilderImpl();
|
||||
_descriptorBuilders.Add(db);
|
||||
return db;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<ShapeDescriptorAlteration> Build() {
|
||||
return _descriptorBuilders.Select(b => b.Build());
|
||||
}
|
||||
|
||||
class ShapeDescriptorAlterationBuilderImpl : ShapeDescriptorAlterationBuilder {
|
||||
public ShapeDescriptorAlteration Build() {
|
||||
return new ShapeDescriptorAlteration(_shapeType, _feature, _configurations.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -11,6 +11,7 @@ using Orchard.Localization;
|
||||
namespace Orchard.DisplayManagement.Implementation {
|
||||
public class DefaultDisplayManager : IDisplayManager {
|
||||
private readonly IShapeTableManager _shapeTableManager;
|
||||
private readonly IWorkContextAccessor _workContextAccessor;
|
||||
|
||||
// this need to be Shape instead of IShape - cast to interface throws error on clr types like HtmlString
|
||||
private static readonly CallSite<Func<CallSite, object, Shape>> _convertAsShapeCallsite = CallSite<Func<CallSite, object, Shape>>.Create(
|
||||
@@ -20,8 +21,11 @@ namespace Orchard.DisplayManagement.Implementation {
|
||||
typeof(Shape),
|
||||
null/*typeof(DefaultDisplayManager)*/)));
|
||||
|
||||
public DefaultDisplayManager(IShapeTableManager shapeTableManager) {
|
||||
public DefaultDisplayManager(
|
||||
IShapeTableManager shapeTableManager,
|
||||
IWorkContextAccessor workContextAccessor) {
|
||||
_shapeTableManager = shapeTableManager;
|
||||
_workContextAccessor = workContextAccessor;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
@@ -32,7 +36,7 @@ namespace Orchard.DisplayManagement.Implementation {
|
||||
|
||||
var shape = _convertAsShapeCallsite.Target(_convertAsShapeCallsite, context.Value);
|
||||
|
||||
// non-shape arguements are returned as a no-op
|
||||
// non-shape arguments are returned as a no-op
|
||||
if (shape == null)
|
||||
return CoerceHtmlString(context.Value);
|
||||
|
||||
@@ -41,7 +45,8 @@ namespace Orchard.DisplayManagement.Implementation {
|
||||
if (shapeMetadata == null || string.IsNullOrEmpty(shapeMetadata.Type))
|
||||
return CoerceHtmlString(context.Value);
|
||||
|
||||
var shapeTable = _shapeTableManager.GetShapeTable(null);
|
||||
var workContext = _workContextAccessor.GetContext(context.ViewContext);
|
||||
var shapeTable = _shapeTableManager.GetShapeTable(workContext.CurrentTheme.ThemeName);
|
||||
//preproc loop / event (alter shape, swapping type)
|
||||
|
||||
ShapeDescriptor shapeDescriptor;
|
||||
@@ -63,7 +68,7 @@ namespace Orchard.DisplayManagement.Implementation {
|
||||
return new HtmlString(HttpUtility.HtmlEncode(value));
|
||||
}
|
||||
|
||||
private IHtmlString Process(ShapeDescriptor shapeDescriptor, IShape shape, DisplayContext context) {
|
||||
private IHtmlString Process(ShapeDescriptor shapeDescriptor, IShape shape, DisplayContext context) {
|
||||
return CoerceHtmlString(shapeDescriptor.Binding(context));
|
||||
}
|
||||
|
||||
|
@@ -2,14 +2,20 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ClaySharp;
|
||||
using Orchard.DisplayManagement.Descriptors;
|
||||
using Orchard.DisplayManagement.Shapes;
|
||||
|
||||
namespace Orchard.DisplayManagement.Implementation {
|
||||
public interface IShapeEvents : IDependency {
|
||||
public interface IShapeFactoryEvents : IDependency {
|
||||
void Creating(ShapeCreatingContext context);
|
||||
void Created(ShapeCreatedContext context);
|
||||
}
|
||||
|
||||
public abstract class ShapeFactoryEvents : IShapeFactoryEvents{
|
||||
public virtual void Creating(ShapeCreatingContext context) {}
|
||||
public virtual void Created(ShapeCreatedContext context) {}
|
||||
}
|
||||
|
||||
public class ShapeCreatingContext {
|
||||
public IShapeFactory ShapeFactory { get; set; }
|
||||
public string ShapeType { get; set; }
|
||||
@@ -27,13 +33,19 @@ namespace Orchard.DisplayManagement.Implementation {
|
||||
|
||||
|
||||
public class DefaultShapeFactory : IShapeFactory {
|
||||
private readonly IEnumerable<Lazy<IShapeEvents>> _events;
|
||||
private readonly IEnumerable<Lazy<IShapeFactoryEvents>> _events;
|
||||
private readonly IShapeTableManager _shapeTableManager;
|
||||
|
||||
public DefaultShapeFactory(IEnumerable<Lazy<IShapeEvents>> events) {
|
||||
public DefaultShapeFactory(IEnumerable<Lazy<IShapeFactoryEvents>> events, IShapeTableManager shapeTableManager) {
|
||||
_events = events;
|
||||
_shapeTableManager = shapeTableManager;
|
||||
}
|
||||
|
||||
public IShape Create(string shapeType, INamedEnumerable<object> parameters) {
|
||||
var defaultShapeTable = _shapeTableManager.GetShapeTable(null);
|
||||
ShapeDescriptor shapeDescriptor;
|
||||
defaultShapeTable.Descriptors.TryGetValue(shapeType, out shapeDescriptor);
|
||||
|
||||
var creatingContext = new ShapeCreatingContext {
|
||||
ShapeFactory = this,
|
||||
ShapeType = shapeType,
|
||||
@@ -50,7 +62,6 @@ namespace Orchard.DisplayManagement.Implementation {
|
||||
// consume the first argument
|
||||
positional = positional.Skip(1);
|
||||
}
|
||||
IClayBehavior[] behaviors;
|
||||
|
||||
if (creatingContext.BaseType == typeof(Array)) {
|
||||
// array is a hint - not an intended base class
|
||||
@@ -70,10 +81,17 @@ namespace Orchard.DisplayManagement.Implementation {
|
||||
};
|
||||
}
|
||||
|
||||
// "creating" events may add behaviors and alter base type
|
||||
foreach (var ev in _events) {
|
||||
ev.Value.Creating(creatingContext);
|
||||
}
|
||||
if (shapeDescriptor != null && shapeDescriptor.Creating != null) {
|
||||
foreach (var ev in shapeDescriptor.Creating) {
|
||||
ev(creatingContext);
|
||||
}
|
||||
}
|
||||
|
||||
// create the new instance
|
||||
var createdContext = new ShapeCreatedContext {
|
||||
ShapeFactory = this,
|
||||
ShapeType = creatingContext.ShapeType,
|
||||
@@ -81,6 +99,22 @@ namespace Orchard.DisplayManagement.Implementation {
|
||||
};
|
||||
createdContext.Shape.Metadata = new ShapeMetadata { Type = shapeType };
|
||||
|
||||
// "created" events provides default values and new object initialization
|
||||
foreach (var ev in _events) {
|
||||
ev.Value.Created(createdContext);
|
||||
}
|
||||
if (shapeDescriptor != null && shapeDescriptor.Created != null) {
|
||||
foreach (var ev in shapeDescriptor.Created) {
|
||||
ev(createdContext);
|
||||
}
|
||||
}
|
||||
foreach (var ev in creatingContext.OnCreated) {
|
||||
ev(createdContext);
|
||||
}
|
||||
|
||||
|
||||
// other properties passed with call overlay any defaults, so are after the created events
|
||||
|
||||
// only one non-Type, non-named argument is allowed
|
||||
var initializer = positional.SingleOrDefault();
|
||||
if (initializer != null) {
|
||||
@@ -93,13 +127,6 @@ namespace Orchard.DisplayManagement.Implementation {
|
||||
createdContext.Shape[kv.Key] = kv.Value;
|
||||
}
|
||||
|
||||
foreach (var ev in creatingContext.OnCreated) {
|
||||
ev(createdContext);
|
||||
}
|
||||
foreach (var ev in _events) {
|
||||
ev.Value.Created(createdContext);
|
||||
}
|
||||
|
||||
return createdContext.Shape;
|
||||
}
|
||||
}
|
||||
|
@@ -1,36 +0,0 @@
|
||||
using System.Linq;
|
||||
using ClaySharp.Implementation;
|
||||
using Orchard.DisplayManagement.Zones;
|
||||
using Orchard.UI;
|
||||
|
||||
namespace Orchard.DisplayManagement.Implementation {
|
||||
public class PageWorkContextStateProvider : IWorkContextStateProvider, IShapeEvents {
|
||||
private readonly IShapeFactory _shapeFactory;
|
||||
|
||||
public PageWorkContextStateProvider(IShapeFactory shapeFactory) {
|
||||
_shapeFactory = shapeFactory;
|
||||
}
|
||||
|
||||
public T Get<T>(string name) {
|
||||
if (name == "Page") {
|
||||
var page = (dynamic)_shapeFactory.Create("Layout", Arguments.From(Enumerable.Empty<object>(), Enumerable.Empty<string>()));
|
||||
return page;
|
||||
}
|
||||
return default(T);
|
||||
}
|
||||
|
||||
public void Creating(ShapeCreatingContext context) {
|
||||
if (context.ShapeType == "Layout") {
|
||||
context.Behaviors.Add(new ZoneHoldingBehavior(context.ShapeFactory));
|
||||
}
|
||||
else if (context.ShapeType == "Zone") {
|
||||
context.BaseType = typeof(Zone);
|
||||
}
|
||||
}
|
||||
|
||||
public void Created(ShapeCreatedContext context) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -100,7 +100,12 @@ namespace Orchard.Environment {
|
||||
}
|
||||
|
||||
public override T GetState<T>(string name) {
|
||||
return (T)_state.GetOrAdd(name, x => _workContextStateProviders.Select(wcsp => wcsp.Get<T>(x)).Where(t => !Equals(t, default(T))).FirstOrDefault());
|
||||
return (T)_state.GetOrAdd(name, x => GetStateInternal<T>(x));
|
||||
}
|
||||
|
||||
private T GetStateInternal<T>(string name) {
|
||||
return _workContextStateProviders.Select(wcsp => wcsp.Get<T>(name))
|
||||
.FirstOrDefault(value => !Equals(value, default(T)));
|
||||
}
|
||||
|
||||
public override void SetState<T>(string name, T value) {
|
||||
|
16
src/Orchard/Mvc/ViewEngines/Razor/RazorViewEngine.cs
Normal file
16
src/Orchard/Mvc/ViewEngines/Razor/RazorViewEngine.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web.Mvc;
|
||||
|
||||
namespace Orchard.Mvc.ViewEngines.Razor {
|
||||
public class RazorViewEngine : CshtmlViewEngine {
|
||||
protected override bool FileExists(ControllerContext controllerContext, string virtualPath) {
|
||||
if (!virtualPath.EndsWith(".cshtml", StringComparison.InvariantCultureIgnoreCase))
|
||||
return false;
|
||||
|
||||
return base.FileExists(controllerContext, virtualPath);
|
||||
}
|
||||
}
|
||||
}
|
@@ -79,7 +79,7 @@ namespace Orchard.Mvc.ViewEngines.Razor {
|
||||
|
||||
//Logger.Debug("UniversalFormats (module): \r\n\t-{0}", string.Join("\r\n\t-", universalFormats));
|
||||
|
||||
var viewEngine = new CshtmlViewEngine {
|
||||
var viewEngine = new RazorViewEngine {
|
||||
MasterLocationFormats = DisabledFormats,
|
||||
ViewLocationFormats = universalFormats,
|
||||
PartialViewLocationFormats = universalFormats,
|
||||
@@ -92,7 +92,7 @@ namespace Orchard.Mvc.ViewEngines.Razor {
|
||||
}
|
||||
|
||||
public IViewEngine CreateBareViewEngine() {
|
||||
return new CshtmlViewEngine {
|
||||
return new RazorViewEngine {
|
||||
MasterLocationFormats = DisabledFormats,
|
||||
ViewLocationFormats = DisabledFormats,
|
||||
PartialViewLocationFormats = DisabledFormats,
|
||||
|
@@ -1,16 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web.Mvc;
|
||||
using Autofac;
|
||||
using ClaySharp;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Data.Migration;
|
||||
using Autofac;
|
||||
using Orchard.DisplayManagement;
|
||||
using Orchard.Environment;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Mvc.Html;
|
||||
using Orchard.Security;
|
||||
using Orchard.Security.Permissions;
|
||||
|
||||
|
@@ -37,7 +37,7 @@ namespace Orchard.Mvc.ViewEngines.ThemeAwareness {
|
||||
var buffer = new StringWriter();
|
||||
findBody.View.Render(viewContext, buffer);
|
||||
|
||||
_workContext.Page.Zones["Content"].Add(new HtmlString(buffer.ToString()), "5");
|
||||
_workContext.Page.Zones.Content.Add(new HtmlString(buffer.ToString()), "5");
|
||||
|
||||
var display = _displayHelperFactory.CreateHelper(viewContext, viewDataContainer);
|
||||
IHtmlString result = display(_workContext.Page);
|
||||
|
@@ -1,13 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy;
|
||||
using Orchard.FileSystems.VirtualPath;
|
||||
using Orchard.Logging;
|
||||
|
||||
namespace Orchard.Mvc.ViewEngines.WebForms {
|
||||
public class WebFormViewEngineProvider : IViewEngineProvider {
|
||||
public WebFormViewEngineProvider() {
|
||||
public class WebFormViewEngineProvider : IViewEngineProvider, IShapeTemplateViewEngine {
|
||||
private readonly IVirtualPathProvider _virtualPathProvider;
|
||||
|
||||
public WebFormViewEngineProvider(IVirtualPathProvider virtualPathProvider) {
|
||||
_virtualPathProvider = virtualPathProvider;
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
static string[] DisabledFormats = new[] { "~/Disabled" };
|
||||
|
||||
public ILogger Logger { get; set; }
|
||||
@@ -98,5 +106,15 @@ namespace Orchard.Mvc.ViewEngines.WebForms {
|
||||
AreaPartialViewLocationFormats = DisabledFormats,
|
||||
};
|
||||
}
|
||||
|
||||
public IEnumerable<string> DetectTemplateFileNames(string virtualPath) {
|
||||
var fileNames = _virtualPathProvider.ListFiles(virtualPath).Select(Path.GetFileName);
|
||||
foreach (var fileName in fileNames) {
|
||||
if (fileName.EndsWith(".aspx", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.EndsWith(".ascx", StringComparison.OrdinalIgnoreCase)) {
|
||||
yield return fileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,7 @@
|
||||
using System.Web.Mvc;
|
||||
using Autofac;
|
||||
using Orchard.DisplayManagement;
|
||||
using Orchard.DisplayManagement.Implementation;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Mvc.Html;
|
||||
using Orchard.Security;
|
||||
@@ -6,15 +9,23 @@ using Orchard.Security.Permissions;
|
||||
|
||||
namespace Orchard.Mvc {
|
||||
public class ViewPage<TModel> : System.Web.Mvc.ViewPage<TModel> {
|
||||
public ViewPage() {
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
private object _display;
|
||||
private Localizer _localizer = NullLocalizer.Instance;
|
||||
|
||||
public Localizer T { get; set; }
|
||||
public Localizer T { get { return _localizer; } }
|
||||
public dynamic Display { get { return _display; } }
|
||||
public IDisplayHelperFactory DisplayHelperFactory { get; set; }
|
||||
|
||||
public override void RenderView(ViewContext viewContext) {
|
||||
T = LocalizationUtilities.Resolve(viewContext, AppRelativeVirtualPath);
|
||||
base.RenderView(viewContext);
|
||||
public IAuthorizer Authorizer { get; set; }
|
||||
|
||||
public override void InitHelpers() {
|
||||
base.InitHelpers();
|
||||
|
||||
var workContext = ViewContext.GetWorkContext();
|
||||
workContext.Resolve<IComponentContext>().InjectUnsetProperties(this);
|
||||
|
||||
_localizer = LocalizationUtilities.Resolve(ViewContext, AppRelativeVirtualPath);
|
||||
_display = DisplayHelperFactory.CreateHelper(ViewContext, this);
|
||||
}
|
||||
|
||||
public MvcHtmlString H(string value) {
|
||||
@@ -22,7 +33,7 @@ namespace Orchard.Mvc {
|
||||
}
|
||||
|
||||
public bool AuthorizedFor(Permission permission) {
|
||||
return Html.Resolve<IAuthorizer>().Authorize(permission);
|
||||
return Authorizer.Authorize(permission);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,19 +1,28 @@
|
||||
using System.Web.Mvc;
|
||||
using Autofac;
|
||||
using Orchard.DisplayManagement;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Mvc.Html;
|
||||
using Orchard.Security;
|
||||
using Orchard.Security.Permissions;
|
||||
|
||||
namespace Orchard.Mvc {
|
||||
public class ViewUserControl<TModel> : System.Web.Mvc.ViewUserControl<TModel> {
|
||||
public ViewUserControl() {
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
private object _display;
|
||||
private Localizer _localizer = NullLocalizer.Instance;
|
||||
|
||||
public Localizer T { get; set; }
|
||||
public Localizer T { get { return _localizer; } }
|
||||
public dynamic Display { get { return _display; } }
|
||||
public IDisplayHelperFactory DisplayHelperFactory { get; set; }
|
||||
|
||||
public IAuthorizer Authorizer { get; set; }
|
||||
|
||||
public override void RenderView(ViewContext viewContext) {
|
||||
T = LocalizationUtilities.Resolve(viewContext, AppRelativeVirtualPath);
|
||||
var workContext = viewContext.GetWorkContext();
|
||||
workContext.Resolve<IComponentContext>().InjectUnsetProperties(this);
|
||||
|
||||
_localizer = LocalizationUtilities.Resolve(viewContext, AppRelativeVirtualPath);
|
||||
_display = DisplayHelperFactory.CreateHelper(viewContext, this);
|
||||
|
||||
base.RenderView(viewContext);
|
||||
}
|
||||
|
||||
@@ -22,7 +31,10 @@ namespace Orchard.Mvc {
|
||||
}
|
||||
|
||||
public bool AuthorizedFor(Permission permission) {
|
||||
return Html.Resolve<IAuthorizer>().Authorize(permission);
|
||||
return Authorizer.Authorize(permission);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ViewUserControl : ViewUserControl<dynamic> {
|
||||
}
|
||||
}
|
||||
|
@@ -139,8 +139,14 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="DisplayManagement\Implementation\PageWorkContextStateProvider.cs" />
|
||||
<Compile Include="DisplayManagement\Zones\ZoneHoldingBehavior.cs" />
|
||||
<Compile Include="DisplayManagement\Descriptors\ShapeDescriptor.cs" />
|
||||
<Compile Include="DisplayManagement\Descriptors\ShapeDescriptorAlteration.cs" />
|
||||
<Compile Include="DisplayManagement\Descriptors\ShapeDescriptorAlterationBuilder.cs" />
|
||||
<Compile Include="DisplayManagement\Descriptors\ShapeTable.cs" />
|
||||
<Compile Include="DisplayManagement\Descriptors\ShapeTableBuilder.cs" />
|
||||
<Compile Include="Mvc\ViewEngines\Razor\RazorViewEngine.cs" />
|
||||
<Compile Include="UI\Zones\PageWorkContext.cs" />
|
||||
<Compile Include="UI\Zones\ZoneHoldingBehavior.cs" />
|
||||
<Compile Include="Mvc\ViewEngines\ThemeAwareness\ConfiguredEnginesCache.cs" />
|
||||
<Compile Include="Mvc\ViewEngines\ThemeAwareness\LayoutAwareViewEngine.cs" />
|
||||
<Compile Include="Mvc\ViewEngines\ThemeAwareness\ThemeAwareViewEngine.cs" />
|
||||
@@ -731,18 +737,18 @@
|
||||
<Compile Include="UI\Resources\LinkEntry.cs" />
|
||||
<Compile Include="UI\Resources\ResourceFilter.cs" />
|
||||
<Compile Include="UI\Resources\ResourceManager.cs" />
|
||||
<Compile Include="UI\Zones\DelegateZoneItem.cs" />
|
||||
<Compile Include="UI\Zones\ContentItemDisplayZoneItem.cs" />
|
||||
<Compile Include="UI\Zones\IZoneManager.cs" />
|
||||
<Compile Include="UI\Zones\ContentPartDisplayZoneItem.cs" />
|
||||
<Compile Include="UI\Zones\ContentPartEditorZoneItem.cs" />
|
||||
<Compile Include="UI\Zones\IZoneManagerEvents.cs" />
|
||||
<Compile Include="UI\Zones\RenderActionZoneItem.cs" />
|
||||
<Compile Include="UI\Zones\RenderPartialZoneItem.cs" />
|
||||
<Compile Include="UI\Zones\RenderStaticZoneItem.cs" />
|
||||
<Compile Include="UI\Zones\ZoneCollection.cs" />
|
||||
<Compile Include="UI\Zones\ZoneEntry.cs" />
|
||||
<Compile Include="UI\Zones\ZoneItem.cs" />
|
||||
<Compile Include="UI\Zones\Obsolete\DelegateZoneItem.cs" />
|
||||
<Compile Include="UI\Zones\Obsolete\ContentItemDisplayZoneItem.cs" />
|
||||
<Compile Include="UI\Zones\Obsolete\IZoneManager.cs" />
|
||||
<Compile Include="UI\Zones\Obsolete\ContentPartDisplayZoneItem.cs" />
|
||||
<Compile Include="UI\Zones\Obsolete\ContentPartEditorZoneItem.cs" />
|
||||
<Compile Include="UI\Zones\Obsolete\IZoneManagerEvents.cs" />
|
||||
<Compile Include="UI\Zones\Obsolete\RenderActionZoneItem.cs" />
|
||||
<Compile Include="UI\Zones\Obsolete\RenderPartialZoneItem.cs" />
|
||||
<Compile Include="UI\Zones\Obsolete\RenderStaticZoneItem.cs" />
|
||||
<Compile Include="UI\Zones\Obsolete\ZoneCollection.cs" />
|
||||
<Compile Include="UI\Zones\Obsolete\ZoneEntry.cs" />
|
||||
<Compile Include="UI\Zones\Obsolete\ZoneItem.cs" />
|
||||
<Compile Include="Mvc\ViewPage.cs">
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
</Compile>
|
||||
@@ -784,7 +790,7 @@
|
||||
<Compile Include="FileSystems\Media\IStorageFile.cs" />
|
||||
<Compile Include="FileSystems\Media\IStorageFolder.cs" />
|
||||
<Compile Include="FileSystems\Media\IStorageProvider.cs" />
|
||||
<Compile Include="UI\Zones\ZoneManager.cs" />
|
||||
<Compile Include="UI\Zones\Obsolete\ZoneManager.cs" />
|
||||
<Compile Include="Utility\Extensions\ReadOnlyCollectionExtensions.cs" />
|
||||
<Compile Include="Utility\Extensions\RouteValueDictionaryExtensions.cs" />
|
||||
<Compile Include="Utility\Extensions\StringExtensions.cs" />
|
||||
|
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Mvc;
|
||||
using Orchard.DisplayManagement.Shapes;
|
||||
|
||||
namespace Orchard.UI {
|
||||
public interface IPage {
|
||||
@@ -31,7 +33,7 @@ namespace Orchard.UI {
|
||||
IZone Add(Action<HtmlHelper> action, string position);
|
||||
}
|
||||
|
||||
public class Zone : IZone {
|
||||
public class Zone : Shape, IZone {
|
||||
private readonly IList<object> _items = new List<object>();
|
||||
|
||||
public virtual string ZoneName { get; set; }
|
||||
@@ -55,5 +57,11 @@ namespace Orchard.UI {
|
||||
//throw new NotImplementedException();
|
||||
return this;
|
||||
}
|
||||
|
||||
public virtual IList<object> Items {
|
||||
get {
|
||||
return _items;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
39
src/Orchard/UI/Zones/PageWorkContext.cs
Normal file
39
src/Orchard/UI/Zones/PageWorkContext.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System.Linq;
|
||||
using ClaySharp.Implementation;
|
||||
using Orchard.DisplayManagement;
|
||||
using Orchard.DisplayManagement.Descriptors;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
|
||||
namespace Orchard.UI.Zones {
|
||||
public class PageWorkContext : IWorkContextStateProvider {
|
||||
private readonly IShapeFactory _shapeFactory;
|
||||
|
||||
public PageWorkContext(IShapeFactory shapeFactory) {
|
||||
_shapeFactory = shapeFactory;
|
||||
}
|
||||
|
||||
public T Get<T>(string name) {
|
||||
if (name == "Page") {
|
||||
return (dynamic)_shapeFactory.Create("Layout", Arguments.Empty());
|
||||
}
|
||||
return default(T);
|
||||
}
|
||||
}
|
||||
|
||||
public class CoreShapes : IShapeDescriptorBindingStrategy {
|
||||
public void Discover(ShapeTableBuilder builder) {
|
||||
var feature = new FeatureDescriptor {
|
||||
Name = "Orchard.Framework",
|
||||
Extension = new ExtensionDescriptor {
|
||||
Name = "Orchard.Framework",
|
||||
ExtensionType = "Module",
|
||||
}
|
||||
};
|
||||
builder.Describe.Named("Layout").From(feature)
|
||||
.OnCreating(context => context.Behaviors.Add(new ZoneHoldingBehavior(context.ShapeFactory)));
|
||||
|
||||
builder.Describe.Named("Zone").From(feature)
|
||||
.OnCreating(context => context.BaseType = typeof(Zone));
|
||||
}
|
||||
}
|
||||
}
|
@@ -3,9 +3,22 @@ using System.Linq;
|
||||
using ClaySharp;
|
||||
using ClaySharp.Behaviors;
|
||||
using ClaySharp.Implementation;
|
||||
using Orchard.UI;
|
||||
using Orchard.DisplayManagement;
|
||||
|
||||
namespace Orchard.DisplayManagement.Zones {
|
||||
namespace Orchard.UI.Zones {
|
||||
/// <summary>
|
||||
/// Provides the behavior of shapes that have a Zones property.
|
||||
/// Examples include Layout and Item
|
||||
///
|
||||
/// * Returns a fake parent object for zones
|
||||
/// Foo.Zones
|
||||
///
|
||||
/// *
|
||||
/// Foo.Zones.Alpha :
|
||||
/// Foo.Zones["Alpha"]
|
||||
/// Foo.Alpha :same
|
||||
///
|
||||
/// </summary>
|
||||
public class ZoneHoldingBehavior : ClayBehavior {
|
||||
private readonly IShapeFactory _shapeFactory;
|
||||
|
||||
@@ -15,18 +28,21 @@ namespace Orchard.DisplayManagement.Zones {
|
||||
|
||||
public override object GetMember(Func<object> proceed, object self, string name) {
|
||||
if (name == "Zones") {
|
||||
// provide a robot for zone manipulation on parent object
|
||||
return ClayActivator.CreateInstance(new IClayBehavior[] {
|
||||
new InterfaceProxyBehavior(),
|
||||
new ZonesBehavior(_shapeFactory, self)
|
||||
});
|
||||
}
|
||||
//Page.Zones.Sidebar.Add(x,"below")
|
||||
//Page.Sidebar.Add(x,"below")
|
||||
|
||||
|
||||
var result = proceed();
|
||||
if (((dynamic)result) == null) {
|
||||
|
||||
// substitute nil results with a robot that turns adds a zone on
|
||||
// the parent when .Add is invoked
|
||||
return ClayActivator.CreateInstance(new IClayBehavior[] {
|
||||
new NilResultBehavior(),
|
||||
new InterfaceProxyBehavior(),
|
||||
new NilBehavior(),
|
||||
new ZoneOnDemandBehavior(_shapeFactory, self, name)
|
||||
});
|
||||
}
|
||||
@@ -47,6 +63,7 @@ namespace Orchard.DisplayManagement.Zones {
|
||||
if (parentMember == null) {
|
||||
return ClayActivator.CreateInstance(new IClayBehavior[] {
|
||||
new InterfaceProxyBehavior(),
|
||||
new NilBehavior(),
|
||||
new ZoneOnDemandBehavior(_shapeFactory, _parent, name)
|
||||
});
|
||||
}
|
||||
@@ -63,12 +80,12 @@ namespace Orchard.DisplayManagement.Zones {
|
||||
public class ZoneOnDemandBehavior : ClayBehavior {
|
||||
private readonly IShapeFactory _shapeFactory;
|
||||
private readonly object _parent;
|
||||
private readonly string _name;
|
||||
private readonly string _potentialZoneName;
|
||||
|
||||
public ZoneOnDemandBehavior(IShapeFactory shapeFactory, object parent, string name) {
|
||||
public ZoneOnDemandBehavior(IShapeFactory shapeFactory, object parent, string potentialZoneName) {
|
||||
_shapeFactory = shapeFactory;
|
||||
_parent = parent;
|
||||
_name = name;
|
||||
_potentialZoneName = potentialZoneName;
|
||||
}
|
||||
|
||||
public override object InvokeMember(Func<object> proceed, object self, string name, INamedEnumerable<object> args) {
|
||||
@@ -77,8 +94,8 @@ namespace Orchard.DisplayManagement.Zones {
|
||||
dynamic parent = _parent;
|
||||
|
||||
dynamic zone = _shapeFactory.Create("Zone", Arguments.Empty());
|
||||
zone.ZoneName = name;
|
||||
parent[name] = zone;
|
||||
zone.ZoneName = _potentialZoneName;
|
||||
parent[_potentialZoneName] = zone;
|
||||
|
||||
if (argsCount == 1)
|
||||
return zone.Add(args.Single());
|
@@ -18,8 +18,8 @@ namespace Orchard {
|
||||
set { SetState("HttpContext", value); }
|
||||
}
|
||||
|
||||
public IPage Page {
|
||||
get { return GetState<IPage>("Page"); }
|
||||
public dynamic Page {
|
||||
get { return GetState<object>("Page"); }
|
||||
set { SetState("Page", value); }
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user