mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-01-23 21:32:14 +08:00
Adding data versioning capabilities which content parts may opt-into. Still needs query support though.
--HG-- extra : convert_revision : svn%3A5ff7c347-ad56-4c35-b696-ccb81de16e03/trunk%4044752
This commit is contained in:
@@ -37,7 +37,7 @@ namespace Orchard.Core.Tests.Common.Providers {
|
||||
|
||||
protected override IEnumerable<Type> DatabaseTypes {
|
||||
get {
|
||||
return new[] {typeof (ContentTypeRecord), typeof (ContentItemRecord), typeof (CommonRecord)};
|
||||
return new[] { typeof(ContentTypeRecord), typeof(ContentItemRecord), typeof(ContentItemVersionRecord), typeof(CommonRecord) };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Orchard.Tests.Packages.Users.Controllers {
|
||||
|
||||
protected override IEnumerable<Type> DatabaseTypes {
|
||||
get {
|
||||
return new[] { typeof(UserRecord), typeof(ContentItemRecord), typeof(ContentTypeRecord) };
|
||||
return new[] { typeof(UserRecord), typeof(ContentItemRecord), typeof(ContentItemVersionRecord), typeof(ContentTypeRecord) };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ namespace Orchard.Tests.Packages.Users.Services {
|
||||
_sessionFactory = DataUtility.CreateSessionFactory(
|
||||
databaseFileName,
|
||||
typeof(UserRecord),
|
||||
typeof(ContentItemVersionRecord),
|
||||
typeof(ContentItemRecord),
|
||||
typeof(ContentTypeRecord));
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace Orchard.Tests.Models {
|
||||
databaseFileName,
|
||||
typeof(GammaRecord),
|
||||
typeof(DeltaRecord),
|
||||
typeof(ContentItemVersionRecord),
|
||||
typeof(ContentItemRecord),
|
||||
typeof(ContentTypeRecord));
|
||||
}
|
||||
@@ -56,10 +57,11 @@ namespace Orchard.Tests.Models {
|
||||
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
|
||||
|
||||
_session = _sessionFactory.OpenSession();
|
||||
builder.Register(new DefaultModelManagerTests.TestSessionLocator(_session)).As<ISessionLocator>();
|
||||
builder.Register(new DefaultContentManagerTests.TestSessionLocator(_session)).As<ISessionLocator>();
|
||||
|
||||
_session.Delete("from GammaRecord");
|
||||
_session.Delete("from DeltaRecord");
|
||||
_session.Delete("from ContentItemVersionRecord");
|
||||
_session.Delete("from ContentItemRecord");
|
||||
_session.Delete("from ContentTypeRecord");
|
||||
_session.Flush();
|
||||
@@ -187,19 +189,21 @@ namespace Orchard.Tests.Models {
|
||||
_manager.Create<Gamma>("gamma", init => { init.Record.Frap = "three"; });
|
||||
_manager.Create<Gamma>("gamma", init => { init.Record.Frap = "four"; });
|
||||
_session.Flush();
|
||||
_session.Clear();
|
||||
|
||||
var ascending = _manager.Query("gamma")
|
||||
.OrderBy<GammaRecord, string>(x => x.Frap)
|
||||
.List<Gamma>();
|
||||
.List<Gamma>().ToList();
|
||||
|
||||
Assert.That(ascending.Count(), Is.EqualTo(5));
|
||||
Assert.That(ascending.First().Record.Frap, Is.EqualTo("four"));
|
||||
Assert.That(ascending.Last().Record.Frap, Is.EqualTo("two"));
|
||||
|
||||
_session.Clear();
|
||||
|
||||
var descending = _manager.Query<Gamma, GammaRecord>()
|
||||
.OrderByDescending(x => x.Frap)
|
||||
.List();
|
||||
.List().ToList();
|
||||
|
||||
Assert.That(descending.Count(), Is.EqualTo(5));
|
||||
Assert.That(descending.First().Record.Frap, Is.EqualTo("two"));
|
||||
|
||||
414
src/Orchard.Tests/Models/DefaultContentManagerTests.cs
Normal file
414
src/Orchard.Tests/Models/DefaultContentManagerTests.cs
Normal file
@@ -0,0 +1,414 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Autofac;
|
||||
using Autofac.Builder;
|
||||
using Autofac.Modules;
|
||||
using NHibernate;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Data;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.ContentManagement.Records;
|
||||
using Orchard.Tests.Models.Records;
|
||||
using Orchard.Tests.Models.Stubs;
|
||||
|
||||
namespace Orchard.Tests.Models {
|
||||
[TestFixture]
|
||||
public class DefaultContentManagerTests {
|
||||
private IContainer _container;
|
||||
private IContentManager _manager;
|
||||
private ISessionFactory _sessionFactory;
|
||||
private ISession _session;
|
||||
|
||||
[TestFixtureSetUp]
|
||||
public void InitFixture() {
|
||||
var databaseFileName = System.IO.Path.GetTempFileName();
|
||||
_sessionFactory = DataUtility.CreateSessionFactory(
|
||||
databaseFileName,
|
||||
typeof(ContentTypeRecord),
|
||||
typeof(ContentItemRecord),
|
||||
typeof(ContentItemVersionRecord),
|
||||
typeof(GammaRecord),
|
||||
typeof(DeltaRecord),
|
||||
typeof(EpsilonRecord));
|
||||
}
|
||||
|
||||
[TestFixtureTearDown]
|
||||
public void TermFixture() {
|
||||
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void Init() {
|
||||
var builder = new ContainerBuilder();
|
||||
builder.RegisterModule(new ImplicitCollectionSupportModule());
|
||||
builder.Register<DefaultContentManager>().As<IContentManager>();
|
||||
builder.Register<AlphaHandler>().As<IContentHandler>();
|
||||
builder.Register<BetaHandler>().As<IContentHandler>();
|
||||
builder.Register<GammaHandler>().As<IContentHandler>();
|
||||
builder.Register<DeltaHandler>().As<IContentHandler>();
|
||||
builder.Register<EpsilonHandler>().As<IContentHandler>();
|
||||
builder.Register<FlavoredHandler>().As<IContentHandler>();
|
||||
builder.Register<StyledHandler>().As<IContentHandler>();
|
||||
|
||||
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
|
||||
|
||||
_session = _sessionFactory.OpenSession();
|
||||
builder.Register(new TestSessionLocator(_session)).As<ISessionLocator>();
|
||||
|
||||
_container = builder.Build();
|
||||
_manager = _container.Resolve<IContentManager>();
|
||||
}
|
||||
|
||||
public class TestSessionLocator : ISessionLocator {
|
||||
private readonly ISession _session;
|
||||
|
||||
public TestSessionLocator(ISession session) {
|
||||
_session = session;
|
||||
}
|
||||
|
||||
public ISession For(Type entityType) {
|
||||
return _session;
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AlphaDriverShouldWeldItsPart() {
|
||||
var foo = _manager.New("alpha");
|
||||
|
||||
Assert.That(foo.Is<Alpha>(), Is.True);
|
||||
Assert.That(foo.As<Alpha>(), Is.Not.Null);
|
||||
Assert.That(foo.Is<Beta>(), Is.False);
|
||||
Assert.That(foo.As<Beta>(), Is.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void StronglyTypedNewShouldTypeCast() {
|
||||
var foo = _manager.New<Alpha>("alpha");
|
||||
Assert.That(foo, Is.Not.Null);
|
||||
Assert.That(foo.GetType(), Is.EqualTo(typeof(Alpha)));
|
||||
}
|
||||
|
||||
[Test, ExpectedException(typeof(InvalidCastException))]
|
||||
public void StronglyTypedNewShouldThrowCastExceptionIfNull() {
|
||||
_manager.New<Beta>("alpha");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AlphaIsFlavoredAndStyledAndBetaIsFlavoredOnly() {
|
||||
var alpha = _manager.New<Alpha>("alpha");
|
||||
var beta = _manager.New<Beta>("beta");
|
||||
|
||||
Assert.That(alpha.Is<Flavored>(), Is.True);
|
||||
Assert.That(alpha.Is<Styled>(), Is.True);
|
||||
Assert.That(beta.Is<Flavored>(), Is.True);
|
||||
Assert.That(beta.Is<Styled>(), Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetByIdShouldDetermineTypeAndLoadParts() {
|
||||
var modelRecord = CreateModelRecord("alpha");
|
||||
|
||||
var contentItem = _manager.Get(modelRecord.Id);
|
||||
Assert.That(contentItem.ContentType, Is.EqualTo("alpha"));
|
||||
Assert.That(contentItem.Id, Is.EqualTo(modelRecord.Id));
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void ModelPartWithRecordShouldCallRepositoryToPopulate() {
|
||||
|
||||
CreateModelRecord("gamma");
|
||||
CreateModelRecord("gamma");
|
||||
var modelRecord = CreateModelRecord("gamma");
|
||||
|
||||
var model = _manager.Get(modelRecord.Id);
|
||||
|
||||
// create a gamma record
|
||||
var gamma = new GammaRecord {
|
||||
ContentItemRecord = _container.Resolve<IRepository<ContentItemRecord>>().Get(model.Id),
|
||||
Frap = "foo"
|
||||
};
|
||||
|
||||
_container.Resolve<IRepository<GammaRecord>>().Create(gamma);
|
||||
_session.Flush();
|
||||
_session.Clear();
|
||||
|
||||
// re-fetch from database
|
||||
model = _manager.Get(modelRecord.Id);
|
||||
|
||||
Assert.That(model.ContentType, Is.EqualTo("gamma"));
|
||||
Assert.That(model.Id, Is.EqualTo(modelRecord.Id));
|
||||
Assert.That(model.Is<Gamma>(), Is.True);
|
||||
Assert.That(model.As<Gamma>().Record, Is.Not.Null);
|
||||
Assert.That(model.As<Gamma>().Record.ContentItemRecord.Id, Is.EqualTo(model.Id));
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateShouldMakeModelAndContentTypeRecords() {
|
||||
var beta = _manager.New("beta");
|
||||
_manager.Create(beta);
|
||||
|
||||
var modelRecord = _container.Resolve<IRepository<ContentItemRecord>>().Get(beta.Id);
|
||||
Assert.That(modelRecord, Is.Not.Null);
|
||||
Assert.That(modelRecord.ContentType.Name, Is.EqualTo("beta"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetContentTypesShouldReturnAllTypes() {
|
||||
var types = _manager.GetContentTypes();
|
||||
Assert.That(types.Count(), Is.EqualTo(4));
|
||||
Assert.That(types, Has.Some.With.Property("Name").EqualTo("alpha"));
|
||||
Assert.That(types, Has.Some.With.Property("Name").EqualTo("beta"));
|
||||
Assert.That(types, Has.Some.With.Property("Name").EqualTo("gamma"));
|
||||
Assert.That(types, Has.Some.With.Property("Name").EqualTo("delta"));
|
||||
}
|
||||
|
||||
private ContentItemRecord CreateModelRecord(string contentType) {
|
||||
var contentTypeRepository = _container.Resolve<IRepository<ContentTypeRecord>>();
|
||||
var contentItemRepository = _container.Resolve<IRepository<ContentItemRecord>>();
|
||||
var contentItemVersionRepository = _container.Resolve<IRepository<ContentItemVersionRecord>>();
|
||||
|
||||
var modelRecord = new ContentItemRecord { ContentType = contentTypeRepository.Get(x => x.Name == contentType) };
|
||||
if (modelRecord.ContentType == null) {
|
||||
modelRecord.ContentType = new ContentTypeRecord { Name = contentType };
|
||||
contentTypeRepository.Create(modelRecord.ContentType);
|
||||
}
|
||||
contentItemRepository.Create(modelRecord);
|
||||
|
||||
contentItemVersionRepository.Create(new ContentItemVersionRecord { ContentItemRecord = modelRecord, Latest = true, Published = true, Number = 1 });
|
||||
|
||||
_session.Flush();
|
||||
_session.Clear();
|
||||
return modelRecord;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InitialVersionShouldBeOne() {
|
||||
var gamma1 = _manager.Create<Gamma>("gamma");
|
||||
Assert.That(gamma1.ContentItem.Record, Is.Not.Null);
|
||||
Assert.That(gamma1.ContentItem.VersionRecord, Is.Not.Null);
|
||||
Assert.That(gamma1.ContentItem.Version, Is.EqualTo(1));
|
||||
Assert.That(gamma1.ContentItem.VersionRecord.Number, Is.EqualTo(1));
|
||||
|
||||
_session.Flush();
|
||||
_session.Clear();
|
||||
Trace.WriteLine("session flushed");
|
||||
|
||||
var gamma2 = _manager.Get<Gamma>(gamma1.ContentItem.Id);
|
||||
Assert.That(gamma2.ContentItem.Record, Is.Not.Null);
|
||||
Assert.That(gamma2.ContentItem.VersionRecord, Is.Not.Null);
|
||||
Assert.That(gamma2.ContentItem.Version, Is.EqualTo(1));
|
||||
Assert.That(gamma2.ContentItem.VersionRecord.Number, Is.EqualTo(1));
|
||||
|
||||
// asserts results are re-acquired from db
|
||||
Assert.That(gamma1, Is.Not.SameAs(gamma2));
|
||||
Assert.That(gamma1.Record, Is.Not.SameAs(gamma2.Record));
|
||||
Assert.That(gamma1.ContentItem, Is.Not.SameAs(gamma2.ContentItem));
|
||||
Assert.That(gamma1.ContentItem.Record, Is.Not.SameAs(gamma2.ContentItem.Record));
|
||||
Assert.That(gamma1.ContentItem.VersionRecord, Is.Not.SameAs(gamma2.ContentItem.VersionRecord));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InitialVersionCanBeSpecifiedAndIsPublished() {
|
||||
var gamma1 = _manager.Create<Gamma>("gamma", VersionOptions.Number(4));
|
||||
|
||||
Assert.That(gamma1.ContentItem.Version, Is.EqualTo(4));
|
||||
Assert.That(gamma1.ContentItem.VersionRecord.Published, Is.True);
|
||||
|
||||
_session.Flush();
|
||||
_session.Clear();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PublishedShouldBeLatestButNotDraft() {
|
||||
var gamma1 = _manager.Create("gamma", VersionOptions.Published);
|
||||
|
||||
var gammaPublished = _manager.Get(gamma1.Id, VersionOptions.Published);
|
||||
var gammaLatest = _manager.Get(gamma1.Id, VersionOptions.Latest);
|
||||
var gammaDraft = _manager.Get(gamma1.Id, VersionOptions.Draft);
|
||||
|
||||
Assert.That(gammaPublished.VersionRecord.Id, Is.EqualTo(gamma1.VersionRecord.Id));
|
||||
Assert.That(gammaLatest.VersionRecord.Id, Is.EqualTo(gamma1.VersionRecord.Id));
|
||||
Assert.That(gammaDraft, Is.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DraftShouldBeLatestButNotPublished() {
|
||||
var gamma1 = _manager.Create("gamma", VersionOptions.Draft);
|
||||
|
||||
var gammaPublished = _manager.Get(gamma1.Id, VersionOptions.Published);
|
||||
var gammaLatest = _manager.Get(gamma1.Id, VersionOptions.Latest);
|
||||
var gammaDraft = _manager.Get(gamma1.Id, VersionOptions.Draft);
|
||||
|
||||
Assert.That(gammaDraft.VersionRecord.Id, Is.EqualTo(gamma1.VersionRecord.Id));
|
||||
Assert.That(gammaLatest.VersionRecord.Id, Is.EqualTo(gamma1.VersionRecord.Id));
|
||||
Assert.That(gammaPublished, Is.Null);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void CreateDraftShouldNotCreateExtraDraftCopies() {
|
||||
var gamma1 = _manager.Create("gamma", VersionOptions.Draft);
|
||||
_session.Flush();
|
||||
_session.Clear();
|
||||
|
||||
var gammaDraft1 = _manager.Get(gamma1.Id, VersionOptions.Draft);
|
||||
Assert.That(gammaDraft1.VersionRecord.Id, Is.EqualTo(gamma1.VersionRecord.Id));
|
||||
Assert.That(gammaDraft1.Record.Versions, Has.Count.EqualTo(1));
|
||||
_session.Flush();
|
||||
_session.Clear();
|
||||
|
||||
var gammaDraft2 = _manager.Get(gamma1.Id, VersionOptions.DraftRequired);
|
||||
Assert.That(gammaDraft2.VersionRecord.Id, Is.EqualTo(gamma1.VersionRecord.Id));
|
||||
Assert.That(gammaDraft2.Record.Versions, Has.Count.EqualTo(1));
|
||||
_session.Flush();
|
||||
_session.Clear();
|
||||
|
||||
var gammaDraft3 = _manager.Get(gamma1.Id, VersionOptions.Draft);
|
||||
Assert.That(gammaDraft3.VersionRecord.Id, Is.EqualTo(gamma1.VersionRecord.Id));
|
||||
Assert.That(gammaDraft3.Record.Versions, Has.Count.EqualTo(1));
|
||||
_session.Flush();
|
||||
_session.Clear();
|
||||
|
||||
var gammaDraft4 = _manager.Get(gamma1.Id, VersionOptions.DraftRequired);
|
||||
Assert.That(gammaDraft4.VersionRecord.Id, Is.EqualTo(gamma1.VersionRecord.Id));
|
||||
Assert.That(gammaDraft4.Record.Versions, Has.Count.EqualTo(1));
|
||||
_session.Flush();
|
||||
_session.Clear();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DraftRequiredShouldBuildNewVersionIfLatestIsAlreadyPublished() {
|
||||
Trace.WriteLine("gamma1");
|
||||
var gamma1 = _manager.Create("gamma", VersionOptions.Published);
|
||||
Trace.WriteLine("flush");
|
||||
_session.Flush();
|
||||
_session.Clear();
|
||||
|
||||
Trace.WriteLine("gammaDraft1");
|
||||
var gammaDraft1 = _manager.Get(gamma1.Id, VersionOptions.Draft);
|
||||
Assert.That(gammaDraft1, Is.Null);
|
||||
Trace.WriteLine("flush");
|
||||
_session.Flush();
|
||||
_session.Clear();
|
||||
|
||||
Trace.WriteLine("gammaDraft2");
|
||||
var gammaDraft2 = _manager.Get(gamma1.Id, VersionOptions.DraftRequired);
|
||||
Assert.That(gammaDraft2.VersionRecord.Id, Is.Not.EqualTo(gamma1.VersionRecord.Id));
|
||||
Assert.That(gamma1.Version, Is.EqualTo(1));
|
||||
Assert.That(gammaDraft2.Version, Is.EqualTo(2));
|
||||
Trace.WriteLine("flush");
|
||||
_session.Flush();
|
||||
_session.Clear();
|
||||
|
||||
foreach (var x in _container.Resolve<IRepository<ContentItemVersionRecord>>().Fetch(x => true)) {
|
||||
Trace.WriteLine(string.Format("{0}/{1} #{2} published:{3} latest:{4}",
|
||||
x.ContentItemRecord.Id,
|
||||
x.Id,
|
||||
x.Number,
|
||||
x.Published,
|
||||
x.Latest));
|
||||
}
|
||||
|
||||
Trace.WriteLine("gammaDraft3");
|
||||
var gammaDraft3 = _manager.Get(gamma1.Id, VersionOptions.Draft);
|
||||
Assert.That(gammaDraft3.VersionRecord.Id, Is.EqualTo(gammaDraft2.VersionRecord.Id));
|
||||
Assert.That(gammaDraft3.Record, Is.Not.SameAs(gammaDraft2.Record));
|
||||
Assert.That(gammaDraft3.Record.Versions, Is.Not.SameAs(gammaDraft2.Record.Versions));
|
||||
|
||||
Assert.That(gammaDraft3.Record.Versions, Has.Count.EqualTo(2));
|
||||
Trace.WriteLine("flush");
|
||||
_session.Flush();
|
||||
_session.Clear();
|
||||
|
||||
Trace.WriteLine("gammaDraft4");
|
||||
var gammaDraft4 = _manager.Get(gamma1.Id, VersionOptions.DraftRequired);
|
||||
Assert.That(gammaDraft4.VersionRecord.Id, Is.EqualTo(gammaDraft2.VersionRecord.Id));
|
||||
Assert.That(gammaDraft4.Record.Versions, Has.Count.EqualTo(2));
|
||||
Trace.WriteLine("flush");
|
||||
_session.Flush();
|
||||
_session.Clear();
|
||||
|
||||
Trace.WriteLine("gamma2");
|
||||
var gamma2 = _manager.Get(gamma1.Id);
|
||||
Assert.That(gamma2.Record.Versions, Has.Count.EqualTo(2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NonVersionedPartsAreBoundToSameRecord() {
|
||||
Trace.WriteLine("gamma1");
|
||||
var gamma1 = _manager.Create<Gamma>("gamma", VersionOptions.Published, init => init.Record.Frap = "version one");
|
||||
Trace.WriteLine("gamma2");
|
||||
var gamma2 = _manager.Get<Gamma>(gamma1.ContentItem.Id, VersionOptions.DraftRequired);
|
||||
Assert.That(gamma1.Record.Frap, Is.EqualTo("version one"));
|
||||
Assert.That(gamma2.Record.Frap, Is.EqualTo("version one"));
|
||||
gamma2.Record.Frap = "version two";
|
||||
Assert.That(gamma1.Record.Frap, Is.EqualTo("version two"));
|
||||
Assert.That(gamma2.Record.Frap, Is.EqualTo("version two"));
|
||||
|
||||
Trace.WriteLine("flush");
|
||||
_session.Flush();
|
||||
_session.Clear();
|
||||
|
||||
Trace.WriteLine("gamma1B");
|
||||
var gamma1B = _manager.Get<Gamma>(gamma1.ContentItem.Id, VersionOptions.Published);
|
||||
Trace.WriteLine("gamma2B");
|
||||
var gamma2B = _manager.Get<Gamma>(gamma1.ContentItem.Id, VersionOptions.Draft);
|
||||
Assert.That(gamma1B.Record, Is.SameAs(gamma2B.Record));
|
||||
Assert.That(gamma1B.Record.Frap, Is.EqualTo("version two"));
|
||||
Assert.That(gamma2B.Record.Frap, Is.EqualTo("version two"));
|
||||
Assert.That(gamma1B.ContentItem.VersionRecord.Id, Is.Not.EqualTo(gamma2B.ContentItem.VersionRecord.Id));
|
||||
|
||||
Assert.That(gamma1.ContentItem.Record, Is.Not.SameAs(gamma1B.ContentItem.Record));
|
||||
Assert.That(gamma2.ContentItem.Record, Is.Not.SameAs(gamma2B.ContentItem.Record));
|
||||
Assert.That(gamma1.ContentItem.Record, Is.SameAs(gamma2.ContentItem.Record));
|
||||
Assert.That(gamma1B.ContentItem.Record, Is.SameAs(gamma2B.ContentItem.Record));
|
||||
Assert.That(gamma1.ContentItem.VersionRecord, Is.Not.SameAs(gamma2.ContentItem.VersionRecord));
|
||||
Assert.That(gamma1B.ContentItem.VersionRecord, Is.Not.SameAs(gamma2B.ContentItem.VersionRecord));
|
||||
|
||||
Trace.WriteLine("flush");
|
||||
_session.Flush();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VersionedPartsShouldBeDifferentRecordsWithClonedData() {
|
||||
var gamma1 = _manager.Create<Gamma>("gamma", VersionOptions.Published, init => init.Record.Frap = "version one");
|
||||
var epsilon1 = gamma1.As<Epsilon>();
|
||||
epsilon1.Record.Quad = "epsilon one";
|
||||
|
||||
var gamma2 = _manager.Get<Gamma>(gamma1.ContentItem.Id, VersionOptions.DraftRequired);
|
||||
var epsilon2 = gamma2.As<Epsilon>();
|
||||
|
||||
Assert.That(epsilon1.Record.Quad, Is.EqualTo("epsilon one"));
|
||||
Assert.That(epsilon2.Record.Quad, Is.EqualTo("epsilon one"));
|
||||
epsilon2.Record.Quad = "epsilon two";
|
||||
Assert.That(epsilon1.Record.Quad, Is.EqualTo("epsilon one"));
|
||||
Assert.That(epsilon2.Record.Quad, Is.EqualTo("epsilon two"));
|
||||
|
||||
|
||||
_session.Flush();
|
||||
_session.Clear();
|
||||
|
||||
var gamma1B = _manager.Get<Gamma>(gamma1.ContentItem.Id, VersionOptions.Published);
|
||||
var epsilon1B = gamma1B.As<Epsilon>();
|
||||
var gamma2B = _manager.Get<Gamma>(gamma1.ContentItem.Id, VersionOptions.Draft);
|
||||
var epsilon2B = gamma2B.As<Epsilon>();
|
||||
Assert.That(gamma1B.Record, Is.SameAs(gamma2B.Record));
|
||||
Assert.That(epsilon1B.Record, Is.Not.SameAs(epsilon2B.Record));
|
||||
Assert.That(epsilon1B.Record.Quad, Is.EqualTo("epsilon one"));
|
||||
Assert.That(epsilon2B.Record.Quad, Is.EqualTo("epsilon two"));
|
||||
Assert.That(epsilon1B.ContentItem.VersionRecord.Id, Is.Not.EqualTo(epsilon2B.ContentItem.VersionRecord.Id));
|
||||
|
||||
Assert.That(epsilon1.ContentItem.Record, Is.Not.SameAs(epsilon1B.ContentItem.Record));
|
||||
Assert.That(epsilon2.ContentItem.Record, Is.Not.SameAs(epsilon2B.ContentItem.Record));
|
||||
Assert.That(epsilon1.ContentItem.Record, Is.SameAs(epsilon2.ContentItem.Record));
|
||||
Assert.That(epsilon1B.ContentItem.Record, Is.SameAs(epsilon2B.ContentItem.Record));
|
||||
Assert.That(epsilon1.ContentItem.VersionRecord, Is.Not.SameAs(epsilon2.ContentItem.VersionRecord));
|
||||
Assert.That(epsilon1B.ContentItem.VersionRecord, Is.Not.SameAs(epsilon2B.ContentItem.VersionRecord));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Autofac;
|
||||
using Autofac.Builder;
|
||||
using Autofac.Modules;
|
||||
using NHibernate;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Data;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.ContentManagement.Records;
|
||||
using Orchard.Tests.Models.Records;
|
||||
using Orchard.Tests.Models.Stubs;
|
||||
|
||||
namespace Orchard.Tests.Models {
|
||||
[TestFixture]
|
||||
public class DefaultModelManagerTests {
|
||||
private IContainer _container;
|
||||
private IContentManager _manager;
|
||||
private ISessionFactory _sessionFactory;
|
||||
private ISession _session;
|
||||
|
||||
[TestFixtureSetUp]
|
||||
public void InitFixture() {
|
||||
var databaseFileName = System.IO.Path.GetTempFileName();
|
||||
_sessionFactory = DataUtility.CreateSessionFactory(
|
||||
databaseFileName,
|
||||
typeof(GammaRecord),
|
||||
typeof(ContentItemRecord),
|
||||
typeof(ContentTypeRecord));
|
||||
}
|
||||
|
||||
[TestFixtureTearDown]
|
||||
public void TermFixture() {
|
||||
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void Init() {
|
||||
var builder = new ContainerBuilder();
|
||||
builder.RegisterModule(new ImplicitCollectionSupportModule());
|
||||
builder.Register<DefaultContentManager>().As<IContentManager>();
|
||||
builder.Register<AlphaHandler>().As<IContentHandler>();
|
||||
builder.Register<BetaHandler>().As<IContentHandler>();
|
||||
builder.Register<GammaHandler>().As<IContentHandler>();
|
||||
builder.Register<FlavoredHandler>().As<IContentHandler>();
|
||||
builder.Register<StyledHandler>().As<IContentHandler>();
|
||||
|
||||
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
|
||||
|
||||
_session = _sessionFactory.OpenSession();
|
||||
builder.Register(new TestSessionLocator(_session)).As<ISessionLocator>();
|
||||
|
||||
_container = builder.Build();
|
||||
_manager = _container.Resolve<IContentManager>();
|
||||
}
|
||||
|
||||
public class TestSessionLocator : ISessionLocator {
|
||||
private readonly ISession _session;
|
||||
|
||||
public TestSessionLocator(ISession session) {
|
||||
_session = session;
|
||||
}
|
||||
|
||||
public ISession For(Type entityType) {
|
||||
return _session;
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AlphaDriverShouldWeldItsPart() {
|
||||
var foo = _manager.New("alpha");
|
||||
|
||||
Assert.That(foo.Is<Alpha>(), Is.True);
|
||||
Assert.That(foo.As<Alpha>(), Is.Not.Null);
|
||||
Assert.That(foo.Is<Beta>(), Is.False);
|
||||
Assert.That(foo.As<Beta>(), Is.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void StronglyTypedNewShouldTypeCast() {
|
||||
var foo = _manager.New<Alpha>("alpha");
|
||||
Assert.That(foo, Is.Not.Null);
|
||||
Assert.That(foo.GetType(), Is.EqualTo(typeof(Alpha)));
|
||||
}
|
||||
|
||||
[Test, ExpectedException(typeof(InvalidCastException))]
|
||||
public void StronglyTypedNewShouldThrowCastExceptionIfNull() {
|
||||
_manager.New<Beta>("alpha");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AlphaIsFlavoredAndStyledAndBetaIsFlavoredOnly() {
|
||||
var alpha = _manager.New<Alpha>("alpha");
|
||||
var beta = _manager.New<Beta>("beta");
|
||||
|
||||
Assert.That(alpha.Is<Flavored>(), Is.True);
|
||||
Assert.That(alpha.Is<Styled>(), Is.True);
|
||||
Assert.That(beta.Is<Flavored>(), Is.True);
|
||||
Assert.That(beta.Is<Styled>(), Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetByIdShouldDetermineTypeAndLoadParts() {
|
||||
var modelRecord = CreateModelRecord("alpha");
|
||||
|
||||
var contentItem = _manager.Get(modelRecord.Id);
|
||||
Assert.That(contentItem.ContentType, Is.EqualTo("alpha"));
|
||||
Assert.That(contentItem.Id, Is.EqualTo(modelRecord.Id));
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void ModelPartWithRecordShouldCallRepositoryToPopulate() {
|
||||
|
||||
CreateModelRecord("gamma");
|
||||
CreateModelRecord("gamma");
|
||||
var modelRecord = CreateModelRecord("gamma");
|
||||
|
||||
var model = _manager.Get(modelRecord.Id);
|
||||
|
||||
// create a gamma record
|
||||
var gamma = new GammaRecord {
|
||||
ContentItemRecord = _container.Resolve<IRepository<ContentItemRecord>>().Get(model.Id),
|
||||
Frap = "foo"
|
||||
};
|
||||
|
||||
_container.Resolve<IRepository<GammaRecord>>().Create(gamma);
|
||||
_session.Flush();
|
||||
_session.Clear();
|
||||
|
||||
// re-fetch from database
|
||||
model = _manager.Get(modelRecord.Id);
|
||||
|
||||
Assert.That(model.ContentType, Is.EqualTo("gamma"));
|
||||
Assert.That(model.Id, Is.EqualTo(modelRecord.Id));
|
||||
Assert.That(model.Is<Gamma>(), Is.True);
|
||||
Assert.That(model.As<Gamma>().Record, Is.Not.Null);
|
||||
Assert.That(model.As<Gamma>().Record.ContentItemRecord.Id, Is.EqualTo(model.Id));
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateShouldMakeModelAndContentTypeRecords() {
|
||||
var beta = _manager.New("beta");
|
||||
_manager.Create(beta);
|
||||
|
||||
var modelRecord = _container.Resolve<IRepository<ContentItemRecord>>().Get(beta.Id);
|
||||
Assert.That(modelRecord, Is.Not.Null);
|
||||
Assert.That(modelRecord.ContentType.Name, Is.EqualTo("beta"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetContentTypesShouldReturnAllTypes() {
|
||||
var types = _manager.GetContentTypes();
|
||||
Assert.That(types.Count(), Is.EqualTo(3));
|
||||
Assert.That(types, Has.Some.With.Property("Name").EqualTo("alpha"));
|
||||
Assert.That(types, Has.Some.With.Property("Name").EqualTo("beta"));
|
||||
Assert.That(types, Has.Some.With.Property("Name").EqualTo("gamma"));
|
||||
}
|
||||
|
||||
private ContentItemRecord CreateModelRecord(string contentType) {
|
||||
var contentItemRepository = _container.Resolve<IRepository<ContentItemRecord>>();
|
||||
var contentTypeRepository = _container.Resolve<IRepository<ContentTypeRecord>>();
|
||||
|
||||
var modelRecord = new ContentItemRecord { ContentType = new ContentTypeRecord { Name = contentType } };
|
||||
contentTypeRepository.Create(modelRecord.ContentType);
|
||||
contentItemRepository.Create(modelRecord);
|
||||
|
||||
_session.Flush();
|
||||
_session.Clear();
|
||||
return modelRecord;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
7
src/Orchard.Tests/Models/Records/EpsilonRecord.cs
Normal file
7
src/Orchard.Tests/Models/Records/EpsilonRecord.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
using Orchard.ContentManagement.Records;
|
||||
|
||||
namespace Orchard.Tests.Models.Stubs {
|
||||
public class EpsilonRecord : ContentPartVersionRecord {
|
||||
public virtual string Quad { get; set; }
|
||||
}
|
||||
}
|
||||
23
src/Orchard.Tests/Models/Stubs/Epsilon.cs
Normal file
23
src/Orchard.Tests/Models/Stubs/Epsilon.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Data;
|
||||
using Orchard.Tests.Models.Records;
|
||||
|
||||
namespace Orchard.Tests.Models.Stubs {
|
||||
|
||||
|
||||
public class Epsilon : ContentPart<EpsilonRecord> {
|
||||
}
|
||||
|
||||
public class EpsilonHandler : ContentHandler {
|
||||
|
||||
public EpsilonHandler(IRepository<EpsilonRecord> repository) {
|
||||
Filters.Add(new ActivatingFilter<Epsilon>(x => x == "gamma"));
|
||||
Filters.Add(new StorageVersionFilter<EpsilonRecord>(repository));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,4 @@
|
||||
using System.Linq;
|
||||
using FluentNHibernate.Automapping;
|
||||
using FluentNHibernate.Automapping.Alterations;
|
||||
using Orchard.Data;
|
||||
using Orchard.Data;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Tests.Models.Records;
|
||||
@@ -12,7 +9,7 @@ namespace Orchard.Tests.Models.Stubs {
|
||||
|
||||
|
||||
public class GammaHandler : ContentHandler {
|
||||
public override System.Collections.Generic.IEnumerable<Orchard.ContentManagement.ContentType> GetContentTypes() {
|
||||
public override System.Collections.Generic.IEnumerable<ContentType> GetContentTypes() {
|
||||
return new[] { new ContentType { Name = "gamma" } };
|
||||
}
|
||||
|
||||
@@ -23,30 +20,4 @@ namespace Orchard.Tests.Models.Stubs {
|
||||
}
|
||||
|
||||
|
||||
//public class ContentItemRecordAlteration : IAutoMappingAlteration {
|
||||
// public void Alter(AutoPersistenceModel model) {
|
||||
// model.OverrideAll(mapping => {
|
||||
// var genericArguments = mapping.GetType().GetGenericArguments();
|
||||
// if (!genericArguments.Single().IsSubclassOf(typeof (ContentPartRecord))) {
|
||||
// return;
|
||||
// }
|
||||
// });
|
||||
|
||||
// model.Override<ContentItemRecord>(mapping => mapping.HasOne(record => (GammaRecord)record["GammaRecord"]).Access.NoOp().Fetch.Select());
|
||||
|
||||
|
||||
// }
|
||||
|
||||
// interface IAlteration {
|
||||
// void Override(object mapping);
|
||||
// }
|
||||
|
||||
// class Alteration<T> : IAlteration where T : ContentPartRecord {
|
||||
// public void Override(object mappingObj) {
|
||||
// var mapping = (AutoMapping<T>)mappingObj;
|
||||
// mapping.Id(x => x.Id).GeneratedBy.Foreign("ContentItem");
|
||||
// mapping.HasOne(x => x.ContentItem).Constrained();
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
<Compile Include="Localization\NullLocalizerTests.cs" />
|
||||
<Compile Include="Logging\LoggingModuleTests.cs" />
|
||||
<Compile Include="Models\ContentQueryTests.cs" />
|
||||
<Compile Include="Models\DefaultModelManagerTests.cs" />
|
||||
<Compile Include="Models\DefaultContentManagerTests.cs" />
|
||||
<Compile Include="Models\Drivers\ModelBuilderTests.cs" />
|
||||
<Compile Include="Models\Drivers\ModelDriverTests.cs" />
|
||||
<Compile Include="Models\PartDriverHandlerTests.cs" />
|
||||
@@ -127,6 +127,8 @@
|
||||
<Compile Include="Models\Stubs\BetaHandler.cs" />
|
||||
<Compile Include="Models\Stubs\Delta.cs" />
|
||||
<Compile Include="Models\Records\DeltaRecord.cs" />
|
||||
<Compile Include="Models\Stubs\Epsilon.cs" />
|
||||
<Compile Include="Models\Records\EpsilonRecord.cs" />
|
||||
<Compile Include="Models\Stubs\Flavored.cs" />
|
||||
<Compile Include="Models\Stubs\FlavoredHandler.cs" />
|
||||
<Compile Include="Models\Stubs\Gamma.cs" />
|
||||
|
||||
@@ -5,7 +5,6 @@ using Orchard.Localization;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Settings;
|
||||
using Orchard.UI.Notify;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
|
||||
namespace Orchard.Core.Settings.Controllers {
|
||||
[ValidateInput(false)]
|
||||
@@ -24,18 +23,19 @@ namespace Orchard.Core.Settings.Controllers {
|
||||
public Localizer T { get; set; }
|
||||
|
||||
public ActionResult Index(string tabName) {
|
||||
var model = new Orchard.Core.Settings.ViewModels.SettingsIndexViewModel {
|
||||
Site = _siteService.GetSiteSettings().As<SiteSettings>() };
|
||||
var model = new Orchard.Core.Settings.ViewModels.SettingsIndexViewModel {
|
||||
Site = _siteService.GetSiteSettings().As<SiteSettings>()
|
||||
};
|
||||
model.EditorModel = _modelManager.BuildEditorModel(model.Site);
|
||||
return View(model);
|
||||
}
|
||||
|
||||
[AcceptVerbs(HttpVerbs.Post)]
|
||||
public ActionResult Index(string tabName, FormCollection input) {
|
||||
[HttpPost, ActionName("Index")]
|
||||
public ActionResult IndexPOST(string tabName) {
|
||||
var viewModel = new SettingsIndexViewModel { Site = _siteService.GetSiteSettings().As<SiteSettings>() };
|
||||
viewModel.EditorModel = _modelManager.UpdateEditorModel(viewModel.Site.ContentItem, this);
|
||||
|
||||
if (!TryUpdateModel(viewModel, input.ToValueProvider())) {
|
||||
if (!TryUpdateModel(viewModel)) {
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Routing;
|
||||
using System.Web.Routing;
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.Blogs.Models;
|
||||
using Orchard.ContentManagement;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{4A9C04A6-0986-4A92-A610-5F59FF273FB9}</ProjectGuid>
|
||||
<ProjectTypeGuids>{F85E285D-A4E0-4152-9332-AB1D724D3325};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
|
||||
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Orchard.Pages</RootNamespace>
|
||||
|
||||
@@ -6,10 +6,9 @@ using Orchard.ContentManagement.Records;
|
||||
using Orchard.ContentManagement.ViewModels;
|
||||
|
||||
namespace Orchard.ContentManagement {
|
||||
public static class ContentCreateExtensions {
|
||||
|
||||
public static class ContentExtensions {
|
||||
|
||||
/* Item creation and accessing extension methods */
|
||||
/* Item creation extension methods */
|
||||
|
||||
public static T New<T>(this IContentManager manager, string contentType) where T : class, IContent {
|
||||
var contentItem = manager.New(contentType);
|
||||
@@ -23,6 +22,11 @@ namespace Orchard.ContentManagement {
|
||||
return part;
|
||||
}
|
||||
|
||||
|
||||
public static ContentItem Create(this IContentManager manager, string contentType) {
|
||||
return manager.Create<ContentItem>(contentType, init => { });
|
||||
}
|
||||
|
||||
public static T Create<T>(this IContentManager manager, string contentType) where T : class, IContent {
|
||||
return manager.Create<T>(contentType, init => { });
|
||||
}
|
||||
@@ -37,11 +41,39 @@ namespace Orchard.ContentManagement {
|
||||
return content;
|
||||
}
|
||||
|
||||
public static ContentItem Create(this IContentManager manager, string contentType, VersionOptions options) {
|
||||
return manager.Create<ContentItem>(contentType, options, init => { });
|
||||
}
|
||||
|
||||
public static T Create<T>(this IContentManager manager, string contentType, VersionOptions options) where T : class, IContent {
|
||||
return manager.Create<T>(contentType, options, init => { });
|
||||
}
|
||||
|
||||
public static T Create<T>(this IContentManager manager, string contentType, VersionOptions options, Action<T> initialize) where T : class, IContent {
|
||||
var content = manager.New<T>(contentType);
|
||||
if (content == null)
|
||||
return null;
|
||||
|
||||
initialize(content);
|
||||
manager.Create(content.ContentItem, options);
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ContentExtensions {
|
||||
|
||||
|
||||
|
||||
public static T Get<T>(this IContentManager manager, int id) where T : class, IContent {
|
||||
var contentItem = manager.Get(id);
|
||||
return contentItem == null ? null : contentItem.Get<T>();
|
||||
}
|
||||
|
||||
public static T Get<T>(this IContentManager manager, int id, VersionOptions options) where T : class, IContent {
|
||||
var contentItem = manager.Get(id, options);
|
||||
return contentItem == null ? null : contentItem.Get<T>();
|
||||
}
|
||||
|
||||
|
||||
/* Display and editor convenience extension methods */
|
||||
|
||||
|
||||
@@ -13,16 +13,19 @@ namespace Orchard.ContentManagement {
|
||||
private readonly IList<ContentPart> _parts;
|
||||
ContentItem IContent.ContentItem { get { return this; } }
|
||||
|
||||
public int Id { get; set; }
|
||||
public int Id { get { return Record == null ? 0 : Record.Id; } }
|
||||
public int Version { get { return VersionRecord == null ? 0 : VersionRecord.Number; } }
|
||||
|
||||
public string ContentType { get; set; }
|
||||
public ContentItemRecord Record { get; set; }
|
||||
public ContentItemRecord Record { get { return VersionRecord == null ? null : VersionRecord.ContentItemRecord; } }
|
||||
public ContentItemVersionRecord VersionRecord { get; set; }
|
||||
|
||||
public IEnumerable<ContentPart> Parts { get { return _parts; } }
|
||||
|
||||
public IContentManager ContentManager { get; set; }
|
||||
|
||||
public bool Has(Type partType) {
|
||||
return partType==typeof(ContentItem) || _parts.Any(part => partType.IsAssignableFrom(part.GetType()));
|
||||
return partType == typeof(ContentItem) || _parts.Any(part => partType.IsAssignableFrom(part.GetType()));
|
||||
}
|
||||
|
||||
public IContent Get(Type partType) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Autofac;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
@@ -11,16 +12,19 @@ using Orchard.UI.Navigation;
|
||||
namespace Orchard.ContentManagement {
|
||||
public class DefaultContentManager : IContentManager {
|
||||
private readonly IContext _context;
|
||||
private readonly IRepository<ContentItemRecord> _contentItemRepository;
|
||||
private readonly IRepository<ContentTypeRecord> _contentTypeRepository;
|
||||
private readonly IRepository<ContentItemRecord> _contentItemRepository;
|
||||
private readonly IRepository<ContentItemVersionRecord> _contentItemVersionRepository;
|
||||
|
||||
public DefaultContentManager(
|
||||
IContext context,
|
||||
IRepository<ContentTypeRecord> contentTypeRepository,
|
||||
IRepository<ContentItemRecord> contentItemRepository,
|
||||
IRepository<ContentTypeRecord> contentTypeRepository) {
|
||||
IRepository<ContentItemVersionRecord> contentItemVersionRepository) {
|
||||
_context = context;
|
||||
_contentItemRepository = contentItemRepository;
|
||||
_contentTypeRepository = contentTypeRepository;
|
||||
_contentItemRepository = contentItemRepository;
|
||||
_contentItemVersionRepository = contentItemVersionRepository;
|
||||
}
|
||||
|
||||
private IEnumerable<IContentHandler> _handlers;
|
||||
@@ -67,24 +71,66 @@ namespace Orchard.ContentManagement {
|
||||
}
|
||||
|
||||
public virtual ContentItem Get(int id) {
|
||||
// obtain root record to determine the model type
|
||||
var record = _contentItemRepository.Get(id);
|
||||
return Get(id, VersionOptions.Published);
|
||||
}
|
||||
|
||||
// no record of that id means content item doesn't exist
|
||||
if (record == null)
|
||||
public virtual ContentItem Get(int id, VersionOptions options) {
|
||||
ContentItemVersionRecord versionRecord = null;
|
||||
var appendLatestVersion = false;
|
||||
|
||||
// obtain the root records based on version options
|
||||
if (options.VersionRecordId != 0) {
|
||||
// explicit version record known
|
||||
versionRecord = _contentItemVersionRepository.Get(options.VersionRecordId);
|
||||
}
|
||||
else {
|
||||
var record = _contentItemRepository.Get(id);
|
||||
if (options.IsPublished) {
|
||||
versionRecord = _contentItemVersionRepository.Get(x => x.ContentItemRecord == record && x.Published);
|
||||
}
|
||||
else if (options.IsLatest) {
|
||||
versionRecord = _contentItemVersionRepository.Get(x => x.ContentItemRecord == record && x.Latest);
|
||||
}
|
||||
else if (options.IsDraft || options.IsDraftRequired) {
|
||||
versionRecord = _contentItemVersionRepository.Get(x => x.ContentItemRecord == record && x.Latest && !x.Published);
|
||||
if (versionRecord == null && options.IsDraftRequired) {
|
||||
versionRecord = _contentItemVersionRepository.Get(x => x.ContentItemRecord == record && x.Latest);
|
||||
appendLatestVersion = true;
|
||||
}
|
||||
}
|
||||
else if (options.VersionNumber != 0) {
|
||||
versionRecord = _contentItemVersionRepository.Get(x => x.ContentItemRecord == record && x.Number == options.VersionNumber);
|
||||
}
|
||||
|
||||
//TEMP: this is to transition people with old databases
|
||||
if (versionRecord == null && !record.Versions.Any() && options.IsPublished) {
|
||||
versionRecord = new ContentItemVersionRecord {
|
||||
ContentItemRecord = record,
|
||||
Latest = true,
|
||||
Published = true,
|
||||
Number = 1
|
||||
};
|
||||
record.Versions.Add(versionRecord);
|
||||
_contentItemVersionRepository.Create(versionRecord);
|
||||
}
|
||||
}
|
||||
|
||||
// no record means content item doesn't exist
|
||||
if (versionRecord == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// allocate instance and set record property
|
||||
var contentItem = New(record.ContentType.Name);
|
||||
contentItem.Id = record.Id;
|
||||
contentItem.Record = record;
|
||||
var contentItem = New(versionRecord.ContentItemRecord.ContentType.Name);
|
||||
contentItem.VersionRecord = versionRecord;
|
||||
|
||||
// create a context with a new instance to load
|
||||
var context = new LoadContentContext {
|
||||
Id = contentItem.Id,
|
||||
ContentType = contentItem.ContentType,
|
||||
ContentItemRecord = record,
|
||||
ContentItem = contentItem,
|
||||
ContentItemRecord = contentItem.Record,
|
||||
ContentItemVersionRecord = contentItem.VersionRecord,
|
||||
};
|
||||
|
||||
// invoke handlers to acquire state, or at least establish lazy loading callbacks
|
||||
@@ -95,26 +141,100 @@ namespace Orchard.ContentManagement {
|
||||
handler.Loaded(context);
|
||||
}
|
||||
|
||||
// when draft is required and not currently available a new version is appended
|
||||
if (appendLatestVersion) {
|
||||
return AppendLatestVersion(context.ContentItem);
|
||||
}
|
||||
|
||||
return context.ContentItem;
|
||||
}
|
||||
|
||||
public void Create(ContentItem contentItem) {
|
||||
public virtual ContentItem AppendLatestVersion(ContentItem existingContentItem) {
|
||||
var contentItemRecord = existingContentItem.Record;
|
||||
|
||||
// locate the existing and the current latest versions, allocate building version
|
||||
var existingItemVersionRecord = existingContentItem.VersionRecord;
|
||||
var buildingItemVersionRecord = new ContentItemVersionRecord {
|
||||
ContentItemRecord = contentItemRecord,
|
||||
Latest = true,
|
||||
Published = false
|
||||
};
|
||||
|
||||
if (existingItemVersionRecord.Latest == false) {
|
||||
var latestVersion = _contentItemVersionRepository.Get(x => x.ContentItemRecord == contentItemRecord && x.Latest);
|
||||
latestVersion.Latest = false;
|
||||
buildingItemVersionRecord.Number = latestVersion.Number + 1;
|
||||
}
|
||||
else {
|
||||
existingItemVersionRecord.Latest = false;
|
||||
buildingItemVersionRecord.Number = existingItemVersionRecord.Number + 1;
|
||||
}
|
||||
|
||||
|
||||
_contentItemVersionRepository.Create(buildingItemVersionRecord);
|
||||
|
||||
var buildingContentItem = New(existingContentItem.ContentType);
|
||||
buildingContentItem.VersionRecord = buildingItemVersionRecord;
|
||||
|
||||
var context = new VersionContentContext {
|
||||
Id = existingContentItem.Id,
|
||||
ContentType = existingContentItem.ContentType,
|
||||
ContentItemRecord = contentItemRecord,
|
||||
ExistingContentItem = existingContentItem,
|
||||
BuildingContentItem = buildingContentItem,
|
||||
ExistingItemVersionRecord = existingItemVersionRecord,
|
||||
BuildingItemVersionRecord = buildingItemVersionRecord,
|
||||
};
|
||||
foreach (var handler in Handlers) {
|
||||
handler.Versioning(context);
|
||||
}
|
||||
foreach (var handler in Handlers) {
|
||||
handler.Versioned(context);
|
||||
}
|
||||
|
||||
return context.BuildingContentItem;
|
||||
}
|
||||
|
||||
public virtual void Create(ContentItem contentItem) {
|
||||
Create(contentItem, VersionOptions.Published);
|
||||
}
|
||||
|
||||
public virtual void Create(ContentItem contentItem, VersionOptions options) {
|
||||
// produce root record to determine the model id
|
||||
var modelRecord = new ContentItemRecord { ContentType = AcquireContentTypeRecord(contentItem.ContentType) };
|
||||
_contentItemRepository.Create(modelRecord);
|
||||
contentItem.Record = modelRecord;
|
||||
contentItem.VersionRecord = new ContentItemVersionRecord {
|
||||
ContentItemRecord = new ContentItemRecord {
|
||||
ContentType = AcquireContentTypeRecord(contentItem.ContentType)
|
||||
},
|
||||
Number = 1,
|
||||
Latest = true,
|
||||
Published = true
|
||||
};
|
||||
// add to the collection manually for the created case
|
||||
contentItem.VersionRecord.ContentItemRecord.Versions.Add(contentItem.VersionRecord);
|
||||
|
||||
// version may be specified
|
||||
if (options.VersionNumber != 0) {
|
||||
contentItem.VersionRecord.Number = options.VersionNumber;
|
||||
}
|
||||
|
||||
// draft flag on create is required for explicitly-published content items
|
||||
if (options.IsDraft) {
|
||||
contentItem.VersionRecord.Published = false;
|
||||
}
|
||||
|
||||
_contentItemRepository.Create(contentItem.Record);
|
||||
_contentItemVersionRepository.Create(contentItem.VersionRecord);
|
||||
|
||||
|
||||
// build a context with the initialized instance to create
|
||||
var context = new CreateContentContext {
|
||||
Id = modelRecord.Id,
|
||||
ContentType = modelRecord.ContentType.Name,
|
||||
ContentItemRecord = modelRecord,
|
||||
Id = contentItem.Id,
|
||||
ContentType = contentItem.ContentType,
|
||||
ContentItemRecord = contentItem.Record,
|
||||
ContentItemVersionRecord = contentItem.VersionRecord,
|
||||
ContentItem = contentItem
|
||||
};
|
||||
|
||||
// set the id
|
||||
context.ContentItem.Id = context.Id;
|
||||
|
||||
|
||||
// invoke handlers to add information to persistent stores
|
||||
foreach (var handler in Handlers) {
|
||||
@@ -137,7 +257,7 @@ namespace Orchard.ContentManagement {
|
||||
}
|
||||
|
||||
public ItemDisplayModel<TContentPart> BuildDisplayModel<TContentPart>(TContentPart content, string displayType) where TContentPart : IContent {
|
||||
var itemView = new ItemDisplayModel<TContentPart> {Item = content};
|
||||
var itemView = new ItemDisplayModel<TContentPart> { Item = content };
|
||||
var context = new BuildDisplayModelContext(itemView, displayType);
|
||||
foreach (var handler in Handlers) {
|
||||
handler.BuildDisplayModel(context);
|
||||
|
||||
@@ -36,6 +36,15 @@ namespace Orchard.ContentManagement.Drivers {
|
||||
|
||||
void IContentHandler.Loaded(LoadContentContext context) { }
|
||||
|
||||
void IContentHandler.Versioning(VersionContentContext context) { }
|
||||
|
||||
void IContentHandler.Versioned(VersionContentContext context) { }
|
||||
|
||||
void IContentHandler.Removing(RemoveContentContext context) { }
|
||||
|
||||
void IContentHandler.Removed(RemoveContentContext context) { }
|
||||
|
||||
|
||||
void IContentHandler.GetItemMetadata(GetItemMetadataContext context) {
|
||||
_drivers.Invoke(driver => driver.GetItemMetadata(context), Logger);
|
||||
}
|
||||
@@ -63,6 +72,8 @@ namespace Orchard.ContentManagement.Drivers {
|
||||
result.Apply(context);
|
||||
}, Logger);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,6 +32,14 @@ namespace Orchard.ContentManagement.Drivers {
|
||||
|
||||
void IContentHandler.Loaded(LoadContentContext context) { }
|
||||
|
||||
void IContentHandler.Versioning(VersionContentContext context) { }
|
||||
|
||||
void IContentHandler.Versioned(VersionContentContext context) { }
|
||||
|
||||
void IContentHandler.Removing(RemoveContentContext context) { }
|
||||
|
||||
void IContentHandler.Removed(RemoveContentContext context) { }
|
||||
|
||||
void IContentHandler.GetItemMetadata(GetItemMetadataContext context) { }
|
||||
|
||||
void IContentHandler.BuildDisplayModel(BuildDisplayModelContext context) {
|
||||
|
||||
@@ -33,6 +33,22 @@ namespace Orchard.ContentManagement.Handlers {
|
||||
Filters.Add(new InlineStorageFilter<TPart> { OnLoaded = handler });
|
||||
}
|
||||
|
||||
protected void OnVersioning<TPart>(Action<VersionContentContext, TPart, TPart> handler) where TPart : class, IContent {
|
||||
Filters.Add(new InlineStorageFilter<TPart> { OnVersioning = handler });
|
||||
}
|
||||
|
||||
protected void OnVersioned<TPart>(Action<VersionContentContext, TPart, TPart> handler) where TPart : class, IContent {
|
||||
Filters.Add(new InlineStorageFilter<TPart> { OnVersioned = handler });
|
||||
}
|
||||
|
||||
protected void OnRemoving<TPart>(Action<RemoveContentContext, TPart> handler) where TPart : class, IContent {
|
||||
Filters.Add(new InlineStorageFilter<TPart> { OnRemoving = handler });
|
||||
}
|
||||
|
||||
protected void OnRemoved<TPart>(Action<RemoveContentContext, TPart> handler) where TPart : class, IContent {
|
||||
Filters.Add(new InlineStorageFilter<TPart> { OnRemoved = handler });
|
||||
}
|
||||
|
||||
protected void OnGetItemMetadata<TPart>(Action<GetItemMetadataContext, TPart> handler) where TPart : class, IContent {
|
||||
Filters.Add(new InlineTemplateFilter<TPart> { OnGetItemMetadata = handler });
|
||||
}
|
||||
@@ -54,6 +70,10 @@ namespace Orchard.ContentManagement.Handlers {
|
||||
public Action<CreateContentContext, TPart> OnCreated { get; set; }
|
||||
public Action<LoadContentContext, TPart> OnLoading { get; set; }
|
||||
public Action<LoadContentContext, TPart> OnLoaded { get; set; }
|
||||
public Action<VersionContentContext, TPart, TPart> OnVersioning { get; set; }
|
||||
public Action<VersionContentContext, TPart, TPart> OnVersioned { get; set; }
|
||||
public Action<RemoveContentContext, TPart> OnRemoving { get; set; }
|
||||
public Action<RemoveContentContext, TPart> OnRemoved { get; set; }
|
||||
protected override void Activated(ActivatedContentContext context, TPart instance) {
|
||||
if (OnActivated != null) OnActivated(context, instance);
|
||||
}
|
||||
@@ -69,6 +89,18 @@ namespace Orchard.ContentManagement.Handlers {
|
||||
protected override void Loaded(LoadContentContext context, TPart instance) {
|
||||
if (OnLoaded != null) OnLoaded(context, instance);
|
||||
}
|
||||
protected override void Versioning(VersionContentContext context, TPart existing, TPart building) {
|
||||
if (OnVersioning != null) OnVersioning(context, existing, building);
|
||||
}
|
||||
protected override void Versioned(VersionContentContext context, TPart existing, TPart building) {
|
||||
if (OnVersioned != null) OnVersioned(context, existing, building);
|
||||
}
|
||||
protected override void Removing(RemoveContentContext context, TPart instance) {
|
||||
if (OnRemoving != null) OnRemoving(context, instance);
|
||||
}
|
||||
protected override void Removed(RemoveContentContext context, TPart instance) {
|
||||
if (OnRemoved != null) OnRemoved(context, instance);
|
||||
}
|
||||
}
|
||||
|
||||
class InlineTemplateFilter<TPart> : TemplateFilterBase<TPart> where TPart : class, IContent {
|
||||
@@ -129,6 +161,28 @@ namespace Orchard.ContentManagement.Handlers {
|
||||
filter.Loaded(context);
|
||||
Loaded(context);
|
||||
}
|
||||
void IContentHandler.Versioning(VersionContentContext context) {
|
||||
foreach (var filter in Filters.OfType<IContentStorageFilter>())
|
||||
filter.Versioning(context);
|
||||
Versioning(context);
|
||||
}
|
||||
|
||||
void IContentHandler.Versioned(VersionContentContext context) {
|
||||
foreach (var filter in Filters.OfType<IContentStorageFilter>())
|
||||
filter.Versioned(context);
|
||||
Versioned(context);
|
||||
}
|
||||
void IContentHandler.Removing(RemoveContentContext context) {
|
||||
foreach (var filter in Filters.OfType<IContentStorageFilter>())
|
||||
filter.Removing(context);
|
||||
Removing(context);
|
||||
}
|
||||
|
||||
void IContentHandler.Removed(RemoveContentContext context) {
|
||||
foreach (var filter in Filters.OfType<IContentStorageFilter>())
|
||||
filter.Removed(context);
|
||||
Removed(context);
|
||||
}
|
||||
|
||||
|
||||
void IContentHandler.GetItemMetadata(GetItemMetadataContext context) {
|
||||
@@ -155,15 +209,21 @@ namespace Orchard.ContentManagement.Handlers {
|
||||
protected virtual void Activating(ActivatingContentContext context) { }
|
||||
protected virtual void Activated(ActivatedContentContext context) { }
|
||||
|
||||
protected virtual void Creating(CreateContentContext context) { }
|
||||
protected virtual void Created(CreateContentContext context) { }
|
||||
|
||||
protected virtual void Loading(LoadContentContext context) { }
|
||||
protected virtual void Loaded(LoadContentContext context) { }
|
||||
|
||||
protected virtual void Creating(CreateContentContext context) { }
|
||||
protected virtual void Created(CreateContentContext context) { }
|
||||
protected virtual void Versioning(VersionContentContext context) { }
|
||||
protected virtual void Versioned(VersionContentContext context) { }
|
||||
|
||||
protected virtual void Removing(RemoveContentContext context) { }
|
||||
protected virtual void Removed(RemoveContentContext context) { }
|
||||
|
||||
protected virtual void GetItemMetadata(GetItemMetadataContext context) { }
|
||||
protected virtual void BuildDisplayModel(BuildDisplayModelContext context) { }
|
||||
protected virtual void BuildEditorModel(BuildEditorModelContext context) { }
|
||||
protected virtual void UpdateEditorModel(UpdateEditorModelContext context) {}
|
||||
protected virtual void UpdateEditorModel(UpdateEditorModelContext context) { }
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,9 @@ namespace Orchard.ContentManagement.Handlers {
|
||||
public class CreateContentContext {
|
||||
public int Id { get; set; }
|
||||
public string ContentType { get; set; }
|
||||
public ContentItemRecord ContentItemRecord { get; set; }
|
||||
|
||||
public ContentItem ContentItem { get; set; }
|
||||
public ContentItemRecord ContentItemRecord { get; set; }
|
||||
public ContentItemVersionRecord ContentItemVersionRecord { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,10 @@ namespace Orchard.ContentManagement.Handlers {
|
||||
void Created(CreateContentContext context);
|
||||
void Loading(LoadContentContext context);
|
||||
void Loaded(LoadContentContext context);
|
||||
void Versioning(VersionContentContext context);
|
||||
void Versioned(VersionContentContext context);
|
||||
void Removing(RemoveContentContext context);
|
||||
void Removed(RemoveContentContext context);
|
||||
|
||||
void GetItemMetadata(GetItemMetadataContext context);
|
||||
void BuildDisplayModel(BuildDisplayModelContext context);
|
||||
|
||||
@@ -4,6 +4,10 @@ namespace Orchard.ContentManagement.Handlers {
|
||||
void Creating(CreateContentContext context);
|
||||
void Created(CreateContentContext context);
|
||||
void Loading(LoadContentContext context);
|
||||
void Loaded(LoadContentContext context);
|
||||
void Loaded(LoadContentContext context);
|
||||
void Versioning(VersionContentContext context);
|
||||
void Versioned(VersionContentContext context);
|
||||
void Removing(RemoveContentContext context);
|
||||
void Removed(RemoveContentContext context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,29 @@ namespace Orchard.ContentManagement.Handlers {
|
||||
public class LoadContentContext {
|
||||
public int Id { get; set; }
|
||||
public string ContentType { get; set; }
|
||||
public ContentItemRecord ContentItemRecord { get; set; }
|
||||
public ContentItem ContentItem { get; set; }
|
||||
public ContentItemRecord ContentItemRecord { get; set; }
|
||||
public ContentItemVersionRecord ContentItemVersionRecord { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
public class RemoveContentContext {
|
||||
public int Id { get; set; }
|
||||
public string ContentType { get; set; }
|
||||
public ContentItem ContentItem { get; set; }
|
||||
public ContentItemRecord ContentItemRecord { get; set; }
|
||||
}
|
||||
|
||||
public class VersionContentContext {
|
||||
public int Id { get; set; }
|
||||
public string ContentType { get; set; }
|
||||
|
||||
public ContentItemRecord ContentItemRecord { get; set; }
|
||||
public ContentItemVersionRecord ExistingItemVersionRecord { get; set; }
|
||||
public ContentItemVersionRecord BuildingItemVersionRecord { get; set; }
|
||||
|
||||
public ContentItem ExistingContentItem { get; set; }
|
||||
public ContentItem BuildingContentItem { get; set; }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Orchard.ContentManagement.Handlers {
|
||||
}
|
||||
|
||||
protected override void Loading(LoadContentContext context, ContentPart<TRecord> instance) {
|
||||
var record = _repository.Get(instance.ContentItem.Id);
|
||||
var record = _repository.Get(context.Id);
|
||||
if (record != null) {
|
||||
instance.Record = record;
|
||||
}
|
||||
@@ -30,5 +30,52 @@ namespace Orchard.ContentManagement.Handlers {
|
||||
_repository.Create(instance.Record);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Versioning(VersionContentContext context, ContentPart<TRecord> existing, ContentPart<TRecord> building) {
|
||||
building.Record = existing.Record;
|
||||
}
|
||||
}
|
||||
|
||||
public class StorageVersionFilter<TRecord> : StorageFilterBase<ContentPart<TRecord>> where TRecord : ContentPartVersionRecord, new() {
|
||||
private readonly IRepository<TRecord> _repository;
|
||||
|
||||
public StorageVersionFilter(IRepository<TRecord> repository) {
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
public bool AutomaticallyCreateMissingRecord { get; set; }
|
||||
|
||||
protected override void Activated(ActivatedContentContext context, ContentPart<TRecord> instance) {
|
||||
instance.Record = new TRecord();
|
||||
}
|
||||
|
||||
protected override void Creating(CreateContentContext context, ContentPart<TRecord> instance) {
|
||||
instance.Record.ContentItemRecord = context.ContentItemRecord;
|
||||
instance.Record.ContentItemVersionRecord = context.ContentItemVersionRecord;
|
||||
_repository.Create(instance.Record);
|
||||
}
|
||||
|
||||
protected override void Loading(LoadContentContext context, ContentPart<TRecord> instance) {
|
||||
var record = _repository.Get(context.ContentItemVersionRecord.Id);
|
||||
if (record != null) {
|
||||
instance.Record = record;
|
||||
}
|
||||
else if (AutomaticallyCreateMissingRecord) {
|
||||
instance.Record.ContentItemRecord = context.ContentItemRecord;
|
||||
instance.Record.ContentItemVersionRecord = context.ContentItemVersionRecord;
|
||||
_repository.Create(instance.Record);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Versioning(VersionContentContext context, ContentPart<TRecord> existing, ContentPart<TRecord> building) {
|
||||
// move known ORM values over
|
||||
_repository.Copy(existing.Record, building.Record);
|
||||
|
||||
// only the up-reference to the particular version differs at this point
|
||||
building.Record.ContentItemVersionRecord = context.BuildingItemVersionRecord;
|
||||
|
||||
// push the new instance into the transaction and session
|
||||
_repository.Create(building.Record);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,10 @@ namespace Orchard.ContentManagement.Handlers {
|
||||
protected virtual void Created(CreateContentContext context, TPart instance) { }
|
||||
protected virtual void Loading(LoadContentContext context, TPart instance) { }
|
||||
protected virtual void Loaded(LoadContentContext context, TPart instance) { }
|
||||
protected virtual void Versioning(VersionContentContext context, TPart existing, TPart building) { }
|
||||
protected virtual void Versioned(VersionContentContext context, TPart existing, TPart building) { }
|
||||
protected virtual void Removing(RemoveContentContext context, TPart instance) { }
|
||||
protected virtual void Removed(RemoveContentContext context, TPart instance) { }
|
||||
|
||||
|
||||
void IContentStorageFilter.Activated(ActivatedContentContext context) {
|
||||
@@ -32,5 +36,25 @@ namespace Orchard.ContentManagement.Handlers {
|
||||
if (context.ContentItem.Is<TPart>())
|
||||
Loaded(context, context.ContentItem.As<TPart>());
|
||||
}
|
||||
|
||||
void IContentStorageFilter.Versioning(VersionContentContext context) {
|
||||
if (context.ExistingContentItem.Is<TPart>() || context.BuildingContentItem.Is<TPart>())
|
||||
Versioning(context, context.ExistingContentItem.As<TPart>(), context.BuildingContentItem.As<TPart>());
|
||||
}
|
||||
|
||||
void IContentStorageFilter.Versioned(VersionContentContext context) {
|
||||
if (context.ExistingContentItem.Is<TPart>() || context.BuildingContentItem.Is<TPart>())
|
||||
Versioned(context, context.ExistingContentItem.As<TPart>(), context.BuildingContentItem.As<TPart>());
|
||||
}
|
||||
|
||||
void IContentStorageFilter.Removing(RemoveContentContext context) {
|
||||
if (context.ContentItem.Is<TPart>())
|
||||
Removing(context, context.ContentItem.As<TPart>());
|
||||
}
|
||||
|
||||
void IContentStorageFilter.Removed(RemoveContentContext context) {
|
||||
if (context.ContentItem.Is<TPart>())
|
||||
Removed(context, context.ContentItem.As<TPart>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.ContentManagement.ViewModels;
|
||||
|
||||
namespace Orchard.ContentManagement {
|
||||
@@ -7,9 +6,14 @@ namespace Orchard.ContentManagement {
|
||||
IEnumerable<ContentType> GetContentTypes();
|
||||
|
||||
ContentItem New(string contentType);
|
||||
|
||||
void Create(ContentItem contentItem);
|
||||
void Create(ContentItem contentItem, VersionOptions options);
|
||||
|
||||
ContentItem Get(int id);
|
||||
ContentItem Get(int id, VersionOptions options);
|
||||
|
||||
ContentItem AppendLatestVersion(ContentItem sourceVersion);
|
||||
|
||||
IContentQuery<ContentItem> Query();
|
||||
|
||||
@@ -19,4 +23,20 @@ namespace Orchard.ContentManagement {
|
||||
ItemEditorModel<TContent> BuildEditorModel<TContent>(TContent content) where TContent : IContent;
|
||||
ItemEditorModel<TContent> UpdateEditorModel<TContent>(TContent content, IUpdateModel updater) where TContent : IContent;
|
||||
}
|
||||
|
||||
public class VersionOptions {
|
||||
public static VersionOptions Latest { get { return new VersionOptions { IsLatest = true }; } }
|
||||
public static VersionOptions Published { get { return new VersionOptions { IsPublished = true }; } }
|
||||
public static VersionOptions Draft { get { return new VersionOptions { IsDraft = true }; } }
|
||||
public static VersionOptions DraftRequired { get { return new VersionOptions { IsDraft = true, IsDraftRequired = true }; } }
|
||||
public static VersionOptions Number(int version) { return new VersionOptions { VersionNumber = version }; }
|
||||
public static VersionOptions VersionRecord(int id) { return new VersionOptions { VersionRecordId = id }; }
|
||||
|
||||
public bool IsLatest { get; private set; }
|
||||
public bool IsPublished { get; private set; }
|
||||
public bool IsDraft { get; private set; }
|
||||
public bool IsDraftRequired { get; private set; }
|
||||
public int VersionNumber { get; private set; }
|
||||
public int VersionRecordId { get; private set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Orchard.ContentManagement.Records {
|
||||
public class ContentItemRecord {
|
||||
public ContentItemRecord() {
|
||||
// ReSharper disable DoNotCallOverridableMethodsInConstructor
|
||||
Versions = new List<ContentItemVersionRecord>();
|
||||
// ReSharper restore DoNotCallOverridableMethodsInConstructor
|
||||
}
|
||||
|
||||
public virtual int Id { get; set; }
|
||||
public virtual ContentTypeRecord ContentType { get; set; }
|
||||
public virtual IList<ContentItemVersionRecord> Versions { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -36,25 +36,32 @@ namespace Orchard.ContentManagement.Records {
|
||||
|
||||
class Alteration<TPartRecord> : IAlteration where TPartRecord : ContentPartRecord {
|
||||
public void Override(AutoMapping<ContentItemRecord> mapping) {
|
||||
|
||||
// public TPartRecord TPartRecord {get;set;}
|
||||
var name = typeof(TPartRecord).Name;
|
||||
|
||||
|
||||
var syntheticMethod = new DynamicMethod(name, typeof(TPartRecord), null, typeof(ContentItemRecord));
|
||||
var syntheticProperty = new FakePropertyInfo(syntheticMethod);
|
||||
var syntheticProperty = new SyntheticPropertyInfo(syntheticMethod);
|
||||
|
||||
// record => record.TPartRecord
|
||||
var parameter = Expression.Parameter(typeof(ContentItemRecord), "record");
|
||||
var syntheticExpression = (Expression<Func<ContentItemRecord, TPartRecord>>)Expression.Lambda(
|
||||
typeof(Func<ContentItemRecord, TPartRecord>),
|
||||
Expression.Property(parameter, syntheticProperty),
|
||||
parameter);
|
||||
|
||||
mapping.HasOne(syntheticExpression).Access.NoOp().Fetch.Select();
|
||||
mapping.References(syntheticExpression)
|
||||
.Access.NoOp()
|
||||
.Column("Id")
|
||||
.Unique()
|
||||
.Not.Insert()
|
||||
.Not.Update()
|
||||
.Cascade.All();
|
||||
}
|
||||
|
||||
private class FakePropertyInfo : PropertyInfo {
|
||||
private class SyntheticPropertyInfo : PropertyInfo {
|
||||
private readonly DynamicMethod _getMethod;
|
||||
|
||||
public FakePropertyInfo(DynamicMethod dynamicMethod) {
|
||||
public SyntheticPropertyInfo(DynamicMethod dynamicMethod) {
|
||||
_getMethod = dynamicMethod;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Orchard.ContentManagement.Records {
|
||||
public class ContentItemVersionRecord {
|
||||
public virtual int Id { get; set; }
|
||||
public virtual ContentItemRecord ContentItemRecord { get; set; }
|
||||
public virtual int Number { get; set; }
|
||||
|
||||
public virtual bool Published { get; set; }
|
||||
public virtual bool Latest { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -27,8 +27,12 @@ namespace Orchard.ContentManagement.Records {
|
||||
class Alteration<T> : IAlteration where T : ContentPartRecord {
|
||||
public void Override(object mappingObj) {
|
||||
var mapping = (AutoMapping<T>)mappingObj;
|
||||
mapping.Id(x => x.Id).GeneratedBy.Foreign("ContentItemRecord");
|
||||
mapping.HasOne(x => x.ContentItemRecord).Constrained();
|
||||
|
||||
mapping.Id(x => x.Id)
|
||||
.GeneratedBy.Foreign("ContentItemRecord");
|
||||
|
||||
mapping.HasOne(x => x.ContentItemRecord)
|
||||
.Constrained();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Orchard.ContentManagement.Records {
|
||||
public abstract class ContentPartVersionRecord {
|
||||
public virtual int Id { get; set; }
|
||||
public virtual ContentItemRecord ContentItemRecord { get; set; }
|
||||
public virtual ContentItemVersionRecord ContentItemVersionRecord { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using FluentNHibernate.Automapping;
|
||||
using FluentNHibernate.Automapping.Alterations;
|
||||
|
||||
namespace Orchard.ContentManagement.Records {
|
||||
public class ContentPartVersionRecordAlteration : IAutoMappingAlteration {
|
||||
public void Alter(AutoPersistenceModel model) {
|
||||
|
||||
model.OverrideAll(mapping => {
|
||||
var genericArguments = mapping.GetType().GetGenericArguments();
|
||||
if (!genericArguments.Single().IsSubclassOf(typeof(ContentPartVersionRecord))) {
|
||||
return;
|
||||
}
|
||||
|
||||
var type = typeof(Alteration<>).MakeGenericType(genericArguments);
|
||||
var alteration = (IAlteration)Activator.CreateInstance(type);
|
||||
alteration.Override(mapping);
|
||||
});
|
||||
}
|
||||
|
||||
interface IAlteration {
|
||||
void Override(object mapping);
|
||||
}
|
||||
|
||||
class Alteration<T> : IAlteration where T : ContentPartVersionRecord {
|
||||
public void Override(object mappingObj) {
|
||||
var mapping = (AutoMapping<T>)mappingObj;
|
||||
|
||||
mapping.Id(x => x.Id)
|
||||
.GeneratedBy.Foreign("ContentItemVersionRecord");
|
||||
|
||||
mapping.HasOne(x => x.ContentItemVersionRecord)
|
||||
.Constrained();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,14 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using Orchard.ContentManagement.Records;
|
||||
|
||||
namespace Orchard.Data {
|
||||
public interface IRepository<T> {
|
||||
void Create(T entity);
|
||||
void Update(T entity);
|
||||
void Delete(T entity);
|
||||
void Copy(T source, T target);
|
||||
|
||||
T Get(int id);
|
||||
T Get(Expression<Func<T, bool>> predicate);
|
||||
@@ -18,7 +20,8 @@ namespace Orchard.Data {
|
||||
IEnumerable<T> Fetch(Expression<Func<T, bool>> predicate);
|
||||
IEnumerable<T> Fetch(Expression<Func<T, bool>> predicate, Action<Orderable<T>> order);
|
||||
IEnumerable<T> Fetch(Expression<Func<T, bool>> predicate, Action<Orderable<T>> order, int skip, int count);
|
||||
|
||||
|
||||
[Obsolete]
|
||||
void Transaction(Action action);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ using System;
|
||||
using NHibernate;
|
||||
|
||||
namespace Orchard.Data {
|
||||
public interface ISessionLocator {
|
||||
public interface ISessionLocator {
|
||||
ISession For(Type entityType);
|
||||
}
|
||||
}
|
||||
@@ -44,6 +44,10 @@ namespace Orchard.Data {
|
||||
Delete(entity);
|
||||
}
|
||||
|
||||
void IRepository<T>.Copy(T source, T target) {
|
||||
Copy(source, target);
|
||||
}
|
||||
|
||||
T IRepository<T>.Get(int id) {
|
||||
return Get(id);
|
||||
}
|
||||
@@ -114,6 +118,14 @@ namespace Orchard.Data {
|
||||
Session.Delete(entity);
|
||||
}
|
||||
|
||||
public virtual void Copy(T source, T target) {
|
||||
Logger.Debug("Delete {0}", source, target);
|
||||
var metadata = Session.SessionFactory.GetClassMetadata(typeof (T));
|
||||
var values = metadata.GetPropertyValues(source, EntityMode.Poco);
|
||||
metadata.SetPropertyValues(target, values, EntityMode.Poco);
|
||||
}
|
||||
|
||||
|
||||
public virtual int Count(Expression<Func<T, bool>> predicate) {
|
||||
return Fetch(predicate).Count();
|
||||
}
|
||||
|
||||
@@ -41,8 +41,12 @@ namespace Orchard.Environment {
|
||||
|
||||
public IEnumerable<Type> GetRecordTypes() {
|
||||
var types = _extensionManager.ActiveExtensions().SelectMany(x => x.ExportedTypes);
|
||||
var recordTypes = types.Where(IsRecordType)
|
||||
.Concat(new[] { typeof(ContentItemRecord), typeof(ContentPartRecord), typeof(ContentTypeRecord) });
|
||||
var coreRecords = new[] {
|
||||
typeof (ContentTypeRecord),
|
||||
typeof (ContentItemRecord),
|
||||
typeof (ContentItemVersionRecord),
|
||||
};
|
||||
var recordTypes = types.Where(IsRecordType).Concat(coreRecords);
|
||||
return recordTypes;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +1,31 @@
|
||||
using System.Web.Mvc;
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.Security;
|
||||
using Orchard.Settings;
|
||||
|
||||
namespace Orchard.Mvc.Filters {
|
||||
[UsedImplicitly]
|
||||
public class AntiForgeryAuthorizationFilter : FilterProvider, IAuthorizationFilter {
|
||||
private readonly ISiteService _siteService;
|
||||
private readonly IAuthenticationService _authenticationService;
|
||||
|
||||
public AntiForgeryAuthorizationFilter(ISiteService siteService) {
|
||||
public AntiForgeryAuthorizationFilter(ISiteService siteService, IAuthenticationService authenticationService) {
|
||||
_siteService = siteService;
|
||||
_authenticationService = authenticationService;
|
||||
}
|
||||
|
||||
public void OnAuthorization(AuthorizationContext filterContext) {
|
||||
if (!(filterContext.HttpContext.Request.HttpMethod == "POST" && filterContext.RequestContext.HttpContext.Request.IsAuthenticated))
|
||||
// not a post: no work to do
|
||||
if (filterContext.HttpContext.Request.HttpMethod != "POST")
|
||||
return;
|
||||
|
||||
|
||||
// not logged in: no attack vector
|
||||
if (_authenticationService.GetAuthenticatedUser() == null)
|
||||
return;
|
||||
|
||||
var siteSalt = _siteService.GetSiteSettings().SiteSalt;
|
||||
ValidateAntiForgeryTokenAttribute validator = new ValidateAntiForgeryTokenAttribute { Salt = siteSalt };
|
||||
|
||||
var validator = new ValidateAntiForgeryTokenAttribute { Salt = siteSalt };
|
||||
validator.OnAuthorization(filterContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +66,9 @@
|
||||
<HintPath>..\..\lib\linqnhibernate\NHibernate.Linq.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>
|
||||
@@ -168,8 +171,11 @@
|
||||
<Compile Include="ContentManagement\IUpdateModel.cs" />
|
||||
<Compile Include="ContentManagement\Records\ContentItemRecord.cs" />
|
||||
<Compile Include="ContentManagement\Records\ContentItemRecordAlteration.cs" />
|
||||
<Compile Include="ContentManagement\Records\ContentItemVersionRecord.cs" />
|
||||
<Compile Include="ContentManagement\Records\ContentPartRecord.cs" />
|
||||
<Compile Include="ContentManagement\Records\ContentPartRecordAlteration.cs" />
|
||||
<Compile Include="ContentManagement\Records\ContentPartVersionRecord.cs" />
|
||||
<Compile Include="ContentManagement\Records\ContentPartVersionRecordAlteration.cs" />
|
||||
<Compile Include="ContentManagement\Records\ContentTypeRecord.cs" />
|
||||
<Compile Include="ContentManagement\ViewModels\ItemDisplayModel.cs" />
|
||||
<Compile Include="ContentManagement\ViewModels\ItemEditorModel.cs" />
|
||||
|
||||
Reference in New Issue
Block a user