mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Adding a PartDriver concept to try and drive down complexity
--HG-- extra : convert_revision : svn%3A5ff7c347-ad56-4c35-b696-ccb81de16e03/trunk%4043668
This commit is contained in:
101
src/Orchard.Tests/Models/PartDriverHandlerTests.cs
Normal file
101
src/Orchard.Tests/Models/PartDriverHandlerTests.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Autofac;
|
||||
using Autofac.Builder;
|
||||
using Autofac.Modules;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Models;
|
||||
using Orchard.Models.Driver;
|
||||
using Orchard.Models.ViewModels;
|
||||
|
||||
namespace Orchard.Tests.Models {
|
||||
[TestFixture]
|
||||
public class PartDriverHandlerTests {
|
||||
private IContainer _container;
|
||||
|
||||
[SetUp]
|
||||
public void Init() {
|
||||
var builder = new ContainerBuilder();
|
||||
builder.RegisterModule(new ImplicitCollectionSupportModule());
|
||||
builder.Register<PartDriverHandler>().As<IContentHandler>();
|
||||
_container = builder.Build();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DriverHandlerShouldNotThrowException() {
|
||||
var contentHandler = _container.Resolve<IContentHandler>();
|
||||
contentHandler.BuildDisplayModel(null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AllDriversShouldBeCalled() {
|
||||
var driver1 = new Mock<IPartDriver>();
|
||||
var driver2 = new Mock<IPartDriver>();
|
||||
_container.Build(x => {
|
||||
x.Register(driver1.Object);
|
||||
x.Register(driver2.Object);
|
||||
});
|
||||
var contentHandler = _container.Resolve<IContentHandler>();
|
||||
|
||||
var ctx = new BuildDisplayModelContext(new ItemDisplayModel(new ContentItem()), null, null);
|
||||
|
||||
driver1.Verify(x => x.BuildDisplayModel(ctx), Times.Never());
|
||||
contentHandler.BuildDisplayModel(ctx);
|
||||
driver1.Verify(x => x.BuildDisplayModel(ctx));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDriverCanAddDisplay() {
|
||||
var driver = new StubDriver();
|
||||
_container.Build(x => x.Register(driver).As<IPartDriver>());
|
||||
|
||||
var contentHandler = _container.Resolve<IContentHandler>();
|
||||
|
||||
var item = new ContentItem();
|
||||
item.Weld(new StubPart());
|
||||
|
||||
var ctx = new BuildDisplayModelContext(new ItemDisplayModel(item), null, null);
|
||||
Assert.That(ctx.DisplayModel.Displays.Count(), Is.EqualTo(0));
|
||||
contentHandler.BuildDisplayModel(ctx);
|
||||
Assert.That(ctx.DisplayModel.Displays.Count(), Is.EqualTo(1));
|
||||
Assert.That(ctx.DisplayModel.Displays.Single().Prefix, Is.EqualTo("Stub"));
|
||||
|
||||
}
|
||||
|
||||
private class StubDriver : PartDriver<StubPart> {
|
||||
protected override string Prefix {
|
||||
get { return "Stub"; }
|
||||
}
|
||||
|
||||
protected override DriverResult Display(StubPart part, string groupName, string displayType) {
|
||||
var viewModel = new StubViewModel { Foo = string.Join(",", part.Foo) };
|
||||
return PartialView(viewModel);
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(StubPart part, string groupName) {
|
||||
var viewModel = new StubViewModel { Foo = string.Join(",", part.Foo) };
|
||||
return PartialView(viewModel);
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(StubPart part, string groupName, IUpdateModel updater) {
|
||||
var viewModel = new StubViewModel { Foo = string.Join(",", part.Foo) };
|
||||
updater.TryUpdateModel(viewModel, Prefix, null, null);
|
||||
part.Foo = viewModel.Foo.Split(new[] {','}).Select(x => x.Trim()).ToArray();
|
||||
return PartialView(viewModel);
|
||||
}
|
||||
}
|
||||
|
||||
private class StubPart : ContentPart {
|
||||
public string[] Foo { get; set; }
|
||||
}
|
||||
private class StubViewModel {
|
||||
[Required]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -66,6 +66,9 @@
|
||||
<HintPath>..\..\lib\nunit\nunit.framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
@@ -117,6 +120,7 @@
|
||||
<Compile Include="Models\DefaultModelManagerTests.cs" />
|
||||
<Compile Include="Models\Drivers\ModelBuilderTests.cs" />
|
||||
<Compile Include="Models\Drivers\ModelDriverTests.cs" />
|
||||
<Compile Include="Models\PartDriverHandlerTests.cs" />
|
||||
<Compile Include="Models\Stubs\Alpha.cs" />
|
||||
<Compile Include="Models\Stubs\AlphaHandler.cs" />
|
||||
<Compile Include="Models\Stubs\Beta.cs" />
|
||||
|
137
src/Orchard/Models/PartDriver.cs
Normal file
137
src/Orchard/Models/PartDriver.cs
Normal file
@@ -0,0 +1,137 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.Logging;
|
||||
using Orchard.Models.Driver;
|
||||
using Orchard.Models.ViewModels;
|
||||
|
||||
namespace Orchard.Models {
|
||||
public interface IPartDriver : IEvents {
|
||||
DriverResult BuildDisplayModel(BuildDisplayModelContext context);
|
||||
DriverResult BuildEditorModel(BuildEditorModelContext context);
|
||||
DriverResult UpdateEditorModel(UpdateEditorModelContext context);
|
||||
}
|
||||
|
||||
|
||||
public abstract class PartDriver<TPart> : IPartDriver where TPart : class, IContent {
|
||||
DriverResult IPartDriver.BuildDisplayModel(BuildDisplayModelContext context) {
|
||||
var part = context.ContentItem.As<TPart>();
|
||||
return part == null ? null : BuildDisplayModel(part, context.GroupName, context.DisplayType);
|
||||
}
|
||||
|
||||
DriverResult IPartDriver.BuildEditorModel(BuildEditorModelContext context) {
|
||||
var part = context.ContentItem.As<TPart>();
|
||||
return part == null ? null : BuildEditorModel(part, context.GroupName);
|
||||
}
|
||||
|
||||
DriverResult IPartDriver.UpdateEditorModel(UpdateEditorModelContext context) {
|
||||
var part = context.ContentItem.As<TPart>();
|
||||
return part == null ? null : UpdateEditorModel(part, context.GroupName, context.Updater);
|
||||
}
|
||||
|
||||
protected virtual DriverResult BuildDisplayModel(TPart part, string groupName, string displayType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected virtual DriverResult BuildEditorModel(TPart part, string groupName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected virtual DriverResult UpdateEditorModel(TPart part, string groupName, IUpdateModel updater) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected virtual string Prefix { get { return ""; } }
|
||||
|
||||
public TemplateResult PartialView(object model) {
|
||||
return new TemplateResult(model, null, Prefix);
|
||||
}
|
||||
public TemplateResult PartialView(object model, string template) {
|
||||
return new TemplateResult(model, template, Prefix);
|
||||
}
|
||||
public TemplateResult PartialView(object model, string template, string prefix) {
|
||||
return new TemplateResult(model, template, prefix);
|
||||
}
|
||||
}
|
||||
|
||||
public class DriverResult {
|
||||
public virtual void Apply(BuildDisplayModelContext context) { }
|
||||
public virtual void Apply(BuildEditorModelContext context) { }
|
||||
}
|
||||
|
||||
public class TemplateResult : DriverResult {
|
||||
public object Model { get; set; }
|
||||
public string TemplateName { get; set; }
|
||||
public string Prefix { get; set; }
|
||||
|
||||
public TemplateResult(object model, string templateName, string prefix) {
|
||||
Model = model;
|
||||
TemplateName = templateName;
|
||||
Prefix = prefix;
|
||||
}
|
||||
|
||||
public override void Apply(BuildDisplayModelContext context) {
|
||||
context.AddDisplay(new TemplateViewModel(Model, Prefix) { TemplateName = TemplateName });
|
||||
}
|
||||
|
||||
public override void Apply(BuildEditorModelContext context) {
|
||||
context.AddEditor(new TemplateViewModel(Model, Prefix) { TemplateName = TemplateName });
|
||||
}
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
public class PartDriverHandler : IContentHandler {
|
||||
private readonly IEnumerable<IPartDriver> _drivers;
|
||||
|
||||
public PartDriverHandler(IEnumerable<IPartDriver> drivers) {
|
||||
_drivers = drivers;
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
System.Collections.Generic.IEnumerable<ContentType> IContentHandler.GetContentTypes() {
|
||||
return Enumerable.Empty<ContentType>();
|
||||
}
|
||||
|
||||
void IContentHandler.Activating(ActivatingContentContext context) { }
|
||||
|
||||
void IContentHandler.Activated(ActivatedContentContext context) { }
|
||||
|
||||
void IContentHandler.Creating(CreateContentContext context) { }
|
||||
|
||||
void IContentHandler.Created(CreateContentContext context) { }
|
||||
|
||||
void IContentHandler.Loading(LoadContentContext context) { }
|
||||
|
||||
void IContentHandler.Loaded(LoadContentContext context) { }
|
||||
|
||||
void IContentHandler.GetItemMetadata(GetItemMetadataContext context) { }
|
||||
|
||||
void IContentHandler.BuildDisplayModel(BuildDisplayModelContext context) {
|
||||
_drivers.Invoke(driver => {
|
||||
var result = driver.BuildDisplayModel(context);
|
||||
if (result != null)
|
||||
result.Apply(context);
|
||||
}, Logger);
|
||||
}
|
||||
|
||||
void IContentHandler.BuildEditorModel(BuildEditorModelContext context) {
|
||||
_drivers.Invoke(driver => {
|
||||
var result = driver.BuildEditorModel(context);
|
||||
if (result != null)
|
||||
result.Apply(context);
|
||||
}, Logger);
|
||||
}
|
||||
|
||||
void IContentHandler.UpdateEditorModel(UpdateEditorModelContext context) {
|
||||
_drivers.Invoke(driver => {
|
||||
var result = driver.UpdateEditorModel(context);
|
||||
if (result != null)
|
||||
result.Apply(context);
|
||||
}, Logger);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -19,6 +19,7 @@ namespace Orchard.Models.ViewModels {
|
||||
|
||||
public ItemDisplayModel(ContentItem item) {
|
||||
Item = item;
|
||||
Displays = Enumerable.Empty<TemplateViewModel>();
|
||||
}
|
||||
|
||||
public ContentItem Item {
|
||||
|
@@ -178,6 +178,7 @@
|
||||
<Compile Include="Models\ContentPart.cs" />
|
||||
<Compile Include="Models\IContent.cs" />
|
||||
<Compile Include="Models\IContentQuery.cs" />
|
||||
<Compile Include="Models\PartDriver.cs" />
|
||||
<Compile Include="Models\Records\ContentItemRecordAlteration.cs" />
|
||||
<Compile Include="Models\Records\ContentPartRecord.cs" />
|
||||
<Compile Include="Models\Records\ContentPartRecordAlteration.cs" />
|
||||
|
Reference in New Issue
Block a user