Content manager assigning values to definition properties

DefaultContentManager now takes a dependency on IContentDefinitionManager
ContentItem.TypeDefinition assigned to ContentTypeDefinition instance when creating
ContentPart.TypePartDefinition assigned to ContentTypeDefinition.Part instance as added
Empty definition instances are created as code-only types and parts are created

--HG--
branch : dev
This commit is contained in:
Louis DeJardin
2010-06-08 12:05:29 -07:00
parent 1b39eb3bc0
commit 57e830f19e
19 changed files with 137 additions and 41 deletions

View File

@@ -6,6 +6,7 @@ using JetBrains.Annotations;
using Moq;
using NUnit.Framework;
using Orchard.ContentManagement.Aspects;
using Orchard.ContentManagement.MetaData;
using Orchard.Core.Common;
using Orchard.Core.Common.Handlers;
using Orchard.Core.Common.Models;
@@ -25,6 +26,7 @@ namespace Orchard.Core.Tests.Common.Providers {
private Mock<IAuthenticationService> _authn;
private Mock<IAuthorizationService> _authz;
private Mock<IMembershipService> _membership;
private Mock<IContentDefinitionManager> _contentDefinitionManager;
public override void Register(ContainerBuilder builder) {
builder.RegisterType<DefaultContentManager>().As<IContentManager>();
@@ -35,11 +37,12 @@ namespace Orchard.Core.Tests.Common.Providers {
_authn = new Mock<IAuthenticationService>();
_authz = new Mock<IAuthorizationService>();
_membership = new Mock<IMembershipService>();
_contentDefinitionManager = new Mock<IContentDefinitionManager>();
builder.RegisterInstance(_authn.Object);
builder.RegisterInstance(_authz.Object);
builder.RegisterInstance(_membership.Object);
builder.RegisterInstance(_contentDefinitionManager.Object);
}
protected override IEnumerable<Type> DatabaseTypes {

View File

@@ -2,10 +2,12 @@
using System.Collections.Generic;
using Autofac;
using JetBrains.Annotations;
using Moq;
using NUnit.Framework;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.Records;
using Orchard.Core.Common.Models;
using Orchard.Core.Common.Services;
@@ -27,6 +29,7 @@ namespace Orchard.Core.Tests.Common.Services {
public override void Register(ContainerBuilder builder) {
builder.RegisterType<DefaultContentManager>().As<IContentManager>();
builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>();
builder.RegisterInstance(new Mock<IContentDefinitionManager>().Object);
builder.RegisterType<ThingHandler>().As<IContentHandler>();
builder.RegisterType<StuffHandler>().As<IContentHandler>();

View File

@@ -9,6 +9,8 @@ using Moq;
using NUnit.Framework;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.MetaData.Builders;
using Orchard.ContentManagement.MetaData.Models;
using Orchard.Core.Common.Models;
using Orchard.Core.Feeds;
using Orchard.Core.Feeds.Controllers;
@@ -145,7 +147,7 @@ namespace Orchard.Core.Tests.Feeds.Controllers {
[Test]
public void CorePartValuesAreExtracted() {
var clock = new StubClock();
var hello = new ContentItemBuilder("hello")
var hello = new ContentItemBuilder(new ContentTypeDefinitionBuilder().Named("hello").Build())
.Weld<CommonAspect>()
.Weld<RoutableAspect>()
.Weld<BodyAspect>()

View File

@@ -4,6 +4,7 @@ using Autofac;
using Moq;
using NUnit.Framework;
using Orchard.ContentManagement;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.Records;
using Orchard.Core.Scheduling.Models;
using Orchard.Core.Scheduling.Services;
@@ -29,6 +30,7 @@ namespace Orchard.Core.Tests.Scheduling {
builder.RegisterInstance(new Mock<IOrchardServices>().Object);
builder.RegisterType<DefaultContentManager>().As<IContentManager>();
builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>();
builder.RegisterInstance(new Mock<IContentDefinitionManager>().Object);
builder.RegisterType<ScheduledTaskExecutor>().As<IBackgroundTask>().Named("ScheduledTaskExecutor", typeof(IBackgroundTask));
builder.RegisterInstance(_handler).As<IScheduledTaskHandler>();

View File

@@ -5,6 +5,7 @@ using Autofac;
using Moq;
using NUnit.Framework;
using Orchard.ContentManagement;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.Records;
using Orchard.Core.Scheduling.Models;
using Orchard.Core.Scheduling.Services;
@@ -33,6 +34,7 @@ namespace Orchard.Core.Tests.Scheduling {
builder.RegisterInstance(_mockServices.Object);
builder.RegisterType<DefaultContentManager>().As<IContentManager>();
builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>();
builder.RegisterInstance(new Mock<IContentDefinitionManager>().Object);
builder.RegisterType<ScheduledTaskManager>().As<IScheduledTaskManager>();
}

View File

@@ -1,7 +1,9 @@
using System.Linq;
using Autofac;
using Moq;
using NHibernate;
using NUnit.Framework;
using Orchard.ContentManagement.MetaData;
using Orchard.Data;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
@@ -44,6 +46,7 @@ namespace Orchard.Tests.ContentManagement {
builder.RegisterModule(new ContentModule());
builder.RegisterType<DefaultContentManager>().As<IContentManager>().SingleInstance();
builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>();
builder.RegisterInstance(new Mock<IContentDefinitionManager>().Object);
builder.RegisterType<AlphaHandler>().As<IContentHandler>();
builder.RegisterType<BetaHandler>().As<IContentHandler>();

View File

@@ -2,8 +2,11 @@
using System.Diagnostics;
using System.Linq;
using Autofac;
using Moq;
using NHibernate;
using NUnit.Framework;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Builders;
using Orchard.Data;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
@@ -18,6 +21,7 @@ namespace Orchard.Tests.ContentManagement {
private IContentManager _manager;
private ISessionFactory _sessionFactory;
private ISession _session;
private Mock<IContentDefinitionManager> _contentDefinitionManager;
[TestFixtureSetUp]
public void InitFixture() {
@@ -39,10 +43,12 @@ namespace Orchard.Tests.ContentManagement {
[SetUp]
public void Init() {
_contentDefinitionManager = new Mock<IContentDefinitionManager>();
var builder = new ContainerBuilder();
//builder.RegisterModule(new ImplicitCollectionSupportModule());
builder.RegisterType<DefaultContentManager>().As<IContentManager>();
builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>();
builder.RegisterInstance(_contentDefinitionManager.Object);
builder.RegisterType<AlphaHandler>().As<IContentHandler>();
builder.RegisterType<BetaHandler>().As<IContentHandler>();
@@ -459,6 +465,40 @@ namespace Orchard.Tests.ContentManagement {
Assert.That(gammas[3].Version, Is.EqualTo(4));
}
[Test]
public void EmptyTypeDefinitionShouldBeCreatedIfNotAlreadyDefined() {
var contentItem = _manager.New("no-such-type");
Assert.That(contentItem.ContentType, Is.EqualTo("no-such-type"));
Assert.That(contentItem.TypeDefinition, Is.Not.Null);
Assert.That(contentItem.TypeDefinition.Name, Is.EqualTo("no-such-type"));
Assert.That(contentItem.TypeDefinition.Settings.Count(), Is.EqualTo(0));
Assert.That(contentItem.TypeDefinition.Parts.Count(), Is.EqualTo(0));
}
[Test]
public void ExistingTypeAndPartDefinitionShouldBeUsed() {
var alphaType = new ContentTypeDefinitionBuilder()
.Named("alpha")
.WithSetting("x", "1")
.WithPart("foo")
.WithPart("Flavored", part => part.WithSetting("spin", "clockwise"))
.Build();
_contentDefinitionManager
.Setup(x => x.GetTypeDefinition("alpha"))
.Returns(alphaType);
var contentItem = _manager.New("alpha");
Assert.That(contentItem.ContentType, Is.EqualTo("alpha"));
Assert.That(contentItem.TypeDefinition, Is.Not.Null);
Assert.That(contentItem.TypeDefinition, Is.SameAs(alphaType));
var flavored = contentItem.As<Flavored>();
Assert.That(flavored, Is.Not.Null);
Assert.That(flavored.TypePartDefinition, Is.Not.Null);
Assert.That(flavored.TypePartDefinition.Settings["spin"], Is.EqualTo("clockwise"));
}
}
}

View File

@@ -1,6 +1,7 @@
using NUnit.Framework;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.MetaData.Builders;
namespace Orchard.Tests.ContentManagement.Handlers {
@@ -22,7 +23,7 @@ namespace Orchard.Tests.ContentManagement.Handlers {
public void PartShouldBeAddedBasedOnSimplePredicate() {
var modelDriver = new TestModelHandler();
var builder = new ContentItemBuilder("testing");
var builder = new ContentItemBuilder(new ContentTypeDefinitionBuilder().Named("testing").Build());
((IContentHandler)modelDriver).Activating(new ActivatingContentContext { Builder = builder, ContentType = "testing" });
var model = builder.Build();
Assert.That(model.Is<TestModelPart>(), Is.True);

View File

@@ -5,6 +5,7 @@ using System.Text;
using NUnit.Framework;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.MetaData.Builders;
using Orchard.Tests.ContentManagement.Models;
namespace Orchard.Tests.ContentManagement.Handlers {
@@ -12,21 +13,21 @@ namespace Orchard.Tests.ContentManagement.Handlers {
public class ModelBuilderTests {
[Test]
public void BuilderShouldReturnWorkingModelWithTypeAndId() {
var builder = new ContentItemBuilder("foo");
var builder = new ContentItemBuilder(new ContentTypeDefinitionBuilder().Named("foo").Build());
var model = builder.Build();
Assert.That(model.ContentType, Is.EqualTo("foo"));
}
[Test]
public void IdShouldDefaultToZero() {
var builder = new ContentItemBuilder("foo");
var builder = new ContentItemBuilder(new ContentTypeDefinitionBuilder().Named("foo").Build());
var model = builder.Build();
Assert.That(model.Id, Is.EqualTo(0));
}
[Test]
public void WeldShouldAddPartToModel() {
var builder = new ContentItemBuilder("foo");
var builder = new ContentItemBuilder(new ContentTypeDefinitionBuilder().Named("foo").Build());
builder.Weld<Alpha>();
var model = builder.Build();

View File

@@ -24,6 +24,7 @@ namespace Orchard.Core.Routable.Controllers {
if (string.IsNullOrEmpty(matchedPath)) {
throw new ApplicationException("404 - should not have passed path constraint");
}
var hits = _contentManager
.Query<IsRoutable, RoutableRecord>(VersionOptions.Published)
.Where(r => r.Path == matchedPath)

View File

@@ -1,12 +1,14 @@
using System.Collections.Generic;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.MetaData.Builders;
using Orchard.Security;
namespace Orchard.Roles.Models {
public static class UserSimulation {
public static IUser Create(string role) {
var simulation = new ContentItemBuilder("user")
var simulationType = new ContentTypeDefinitionBuilder().Named("user").Build();
var simulation = new ContentItemBuilder(simulationType)
.Weld<SimulatedUser>()
.Weld<SimulatedUserRoles>()
.Build();

View File

@@ -7,6 +7,7 @@ using Orchard.Commands;
using Orchard.Commands.Builtin;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.MetaData.Builders;
using Orchard.Data.Builders;
using Orchard.Environment.Extensions;
using Orchard.Localization;
@@ -90,7 +91,8 @@ namespace Orchard.Setup {
class SafeModeSiteService : ISiteService {
public ISite GetSiteSettings() {
var site = new ContentItemBuilder("site")
var siteType = new ContentTypeDefinitionBuilder().Named("site").Build();
var site = new ContentItemBuilder(siteType)
.Weld<SafeModeSite>()
.Build();

View File

@@ -4,9 +4,9 @@ using Orchard.ContentManagement.Utilities;
namespace Orchard.ContentManagement {
public abstract class ContentPart : IContent {
public virtual ContentItem ContentItem { get; set; }
public ContentTypeDefinition TypeDefinition { get; set; }
public ContentTypeDefinition TypeDefinition { get { return ContentItem.TypeDefinition; } }
public ContentTypeDefinition.Part TypePartDefinition { get; set; }
public ContentPartDefinition PartDefinition { get; set; }
public ContentPartDefinition PartDefinition { get { return TypePartDefinition.PartDefinition; } }
}
public class ContentPart<TRecord> : ContentPart {

View File

@@ -3,6 +3,9 @@ using System.Collections.Generic;
using System.Linq;
using Autofac;
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.Mvc.ViewModels;
@@ -13,6 +16,7 @@ namespace Orchard.ContentManagement {
private readonly IRepository<ContentTypeRecord> _contentTypeRepository;
private readonly IRepository<ContentItemRecord> _contentItemRepository;
private readonly IRepository<ContentItemVersionRecord> _contentItemVersionRepository;
private readonly IContentDefinitionManager _contentDefinitionManager;
private readonly Func<IContentManagerSession> _contentManagerSession;
public DefaultContentManager(
@@ -20,11 +24,13 @@ namespace Orchard.ContentManagement {
IRepository<ContentTypeRecord> contentTypeRepository,
IRepository<ContentItemRecord> contentItemRepository,
IRepository<ContentItemVersionRecord> contentItemVersionRepository,
IContentDefinitionManager contentDefinitionManager,
Func<IContentManagerSession> contentManagerSession) {
_context = context;
_contentTypeRepository = contentTypeRepository;
_contentItemRepository = contentItemRepository;
_contentItemVersionRepository = contentItemVersionRepository;
_contentDefinitionManager = contentDefinitionManager;
_contentManagerSession = contentManagerSession;
}
@@ -44,11 +50,16 @@ namespace Orchard.ContentManagement {
}
public virtual ContentItem New(string contentType) {
var contentTypeDefinition = _contentDefinitionManager.GetTypeDefinition(contentType);
if (contentTypeDefinition == null) {
contentTypeDefinition = new ContentTypeDefinitionBuilder().Named(contentType).Build();
}
// create a new kernel for the model instance
var context = new ActivatingContentContext {
ContentType = contentType,
Builder = new ContentItemBuilder(contentType)
ContentType = contentTypeDefinition.Name,
Definition = contentTypeDefinition,
Builder = new ContentItemBuilder(contentTypeDefinition)
};
// invoke handlers to weld aspects onto kernel

View File

@@ -52,11 +52,12 @@ namespace Orchard.ContentManagement.Drivers {
return new CombinedResult(results);
}
public IEnumerable<ContentPartInfo> GetPartInfo()
{
var contentPartInfo = new List<ContentPartInfo>() {
new ContentPartInfo()
{PartName = typeof(TContent).Name,Factory = () => new TContent()}
public IEnumerable<ContentPartInfo> GetPartInfo() {
var contentPartInfo = new[] {
new ContentPartInfo {
PartName = typeof (TContent).Name,
Factory = typePartDefinition => new TContent {TypePartDefinition = typePartDefinition}
}
};
return contentPartInfo;

View File

@@ -1,6 +1,9 @@
using Orchard.ContentManagement.MetaData.Models;
namespace Orchard.ContentManagement.Handlers {
public class ActivatingContentContext {
public string ContentType { get; set; }
public ContentTypeDefinition Definition { get; set; }
public ContentItemBuilder Builder { get; set; }
}
}

View File

@@ -1,9 +1,18 @@
namespace Orchard.ContentManagement.Handlers {
using System.Collections.Generic;
using System.Linq;
using Orchard.ContentManagement.MetaData.Models;
namespace Orchard.ContentManagement.Handlers {
public class ContentItemBuilder {
private readonly ContentTypeDefinition _definition;
private readonly ContentItem _item;
public ContentItemBuilder(string contentType) {
_item = new ContentItem { ContentType = contentType };
public ContentItemBuilder(ContentTypeDefinition definition) {
_definition = definition;
_item = new ContentItem {
ContentType = definition.Name,
TypeDefinition = definition
};
}
public ContentItem Build() {
@@ -11,7 +20,18 @@
}
public ContentItemBuilder Weld<TPart>() where TPart : ContentPart, new() {
var part = new TPart();
var partName = typeof(TPart).Name;
var typePartDefinition = _definition.Parts.FirstOrDefault(p => p.PartDefinition.Name == partName);
if (typePartDefinition == null) {
typePartDefinition = new ContentTypeDefinition.Part(
new ContentPartDefinition(partName),
new Dictionary<string, string>());
}
var part = new TPart {
TypePartDefinition = typePartDefinition
};
_item.Weld(part);
return this;
}
@@ -20,6 +40,5 @@
_item.Weld(contentPart);
return this;
}
}
}

View File

@@ -14,14 +14,15 @@ namespace Orchard.ContentManagement.MetaData {
}
public override void Activating(ActivatingContentContext context) {
var contentTypeRecord = _contentDefinitionManager.GetTypeDefinition(context.ContentType);
if (contentTypeRecord == null)
var contentTypeDefinition = _contentDefinitionManager.GetTypeDefinition(context.ContentType);
if (contentTypeDefinition == null)
return;
foreach (var partInfo in _contentPartDrivers.SelectMany(cpp => cpp.GetPartInfo())) {
var partName = partInfo.PartName;
if (contentTypeRecord.Parts.Any(p=>p.PartDefinition.Name == partName)) {
context.Builder.Weld(partInfo.Factory());
var typePartDefinition = contentTypeDefinition.Parts.FirstOrDefault(p => p.PartDefinition.Name == partName);
if (typePartDefinition != null) {
context.Builder.Weld(partInfo.Factory(typePartDefinition));
}
}
}

View File

@@ -1,10 +1,9 @@
using System;
using Orchard.ContentManagement.MetaData.Models;
namespace Orchard.ContentManagement.MetaData
{
public class ContentPartInfo
{
namespace Orchard.ContentManagement.MetaData {
public class ContentPartInfo {
public string PartName { get; set; }
public Func<ContentPart> Factory { get; set; }
public Func<ContentTypeDefinition.Part, ContentPart> Factory { get; set; }
}
}