From 83f1de1fc926af735bf92b641e25dcbace8f66b8 Mon Sep 17 00:00:00 2001 From: Louis DeJardin Date: Fri, 4 Jun 2010 13:37:34 -0700 Subject: [PATCH] Adding fields to metadata definitions Refactoring some component and record names Made content definition model immutable, with builder pattern for creation and alteration Moving records and storage out of base framework assembly Splitting into separate ContentTypeRecord and ContentTypeDefinitionRecord Changing MetaData module's MetaDataController to AdminController Introduced a ContentHandlerBase : IContentHandler to provide virtual no-op implementation of fairly large interface --HG-- branch : dev --- .../Providers/CommonAspectProviderTests.cs | 3 - .../Common/Services/RoutableServiceTests.cs | 3 - .../Orchard.Core.Tests.csproj | 1 + .../Scheduling/ScheduledTaskExecutorTests.cs | 3 - .../Scheduling/ScheduledTaskManagerTests.cs | 3 - .../Metadata/ContentDefinitionManagerTests.cs | 211 +++++++++++++ .../Users/Controllers/AdminControllerTests.cs | 3 - .../Users/Services/MembershipServiceTests.cs | 5 +- .../ContentManagement/ContentQueryTests.cs | 5 +- .../ContentTypeMetaDataTests.cs | 62 ---- .../DefaultContentManagerTests.cs | 3 - .../ContentTypeDefinitionBuilderTests.cs | 130 ++++++++ .../Orchard.Framework.Tests.csproj | 2 +- src/Orchard.Web/Core/Orchard.Core.csproj | 6 + .../Metadata/ContentDefinitionManager.cs | 150 ++++++++++ .../Records/ContentFieldDefinitionRecord.cs | 6 + .../Records/ContentPartDefinitionRecord.cs | 19 ++ .../ContentPartFieldDefinitionRecord.cs | 8 + .../Records/ContentTypeDefinitionRecord.cs | 19 ++ .../ContentTypePartDefinitionRecord.cs | 7 + .../Modules/Orchard.MetaData/AdminMenu.cs | 2 +- .../Controllers/AdminController.cs | 82 ++++++ .../Controllers/MetaDataController.cs | 84 ------ .../Orchard.MetaData/Orchard.MetaData.csproj | 4 +- .../{MetaData => Admin}/ContentTypeList.ascx | 0 .../Orchard.Setup/Services/SetupService.cs | 25 +- src/Orchard/ContentManagement/ContentField.cs | 12 + src/Orchard/ContentManagement/ContentItem.cs | 2 + src/Orchard/ContentManagement/ContentPart.cs | 4 + .../Drivers/ContentItemDriverHandler.cs | 28 +- .../Handlers/ContentHandlerBase.cs | 65 ++++ .../Handlers/IContentHandler.cs | 3 +- .../Builders/ContentPartDefinitionBuilder.cs | 19 ++ .../Builders/ContentTypeDefinitionBuilder.cs | 103 +++++++ .../MetaData/ContentPartHandler.cs | 25 +- .../MetaData/IContentDefinitionManager.cs | 33 +++ .../MetaData/Models/ContentFieldDefinition.cs | 9 + .../MetaData/Models/ContentPartDefinition.cs | 36 +++ .../MetaData/Models/ContentTypeDefinition.cs | 32 ++ .../Records/ContentTypePartNameRecord.cs | 6 - .../MetaData/Records/ContentTypePartRecord.cs | 6 - .../MetaData/Services/ContentTypeService.cs | 81 ----- .../MetaData/Services/IContentTypeService.cs | 17 -- .../MetaData/Services/SettingsFormatter.cs | 24 ++ .../Records/ContentTypeRecord.cs | 14 +- src/Orchard/Data/SessionLocator.cs | 6 +- src/Orchard/Orchard.Framework.csproj | 278 +++++++++++++----- 47 files changed, 1222 insertions(+), 427 deletions(-) create mode 100644 src/Orchard.Core.Tests/Settings/Metadata/ContentDefinitionManagerTests.cs delete mode 100644 src/Orchard.Tests/ContentManagement/ContentTypeMetaDataTests.cs create mode 100644 src/Orchard.Tests/ContentManagement/MetaData/Builders/ContentTypeDefinitionBuilderTests.cs create mode 100644 src/Orchard.Web/Core/Settings/Metadata/ContentDefinitionManager.cs create mode 100644 src/Orchard.Web/Core/Settings/Metadata/Records/ContentFieldDefinitionRecord.cs create mode 100644 src/Orchard.Web/Core/Settings/Metadata/Records/ContentPartDefinitionRecord.cs create mode 100644 src/Orchard.Web/Core/Settings/Metadata/Records/ContentPartFieldDefinitionRecord.cs create mode 100644 src/Orchard.Web/Core/Settings/Metadata/Records/ContentTypeDefinitionRecord.cs create mode 100644 src/Orchard.Web/Core/Settings/Metadata/Records/ContentTypePartDefinitionRecord.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MetaData/Controllers/AdminController.cs delete mode 100644 src/Orchard.Web/Modules/Orchard.MetaData/Controllers/MetaDataController.cs rename src/Orchard.Web/Modules/Orchard.MetaData/Views/{MetaData => Admin}/ContentTypeList.ascx (100%) create mode 100644 src/Orchard/ContentManagement/ContentField.cs create mode 100644 src/Orchard/ContentManagement/Handlers/ContentHandlerBase.cs create mode 100644 src/Orchard/ContentManagement/MetaData/Builders/ContentPartDefinitionBuilder.cs create mode 100644 src/Orchard/ContentManagement/MetaData/Builders/ContentTypeDefinitionBuilder.cs create mode 100644 src/Orchard/ContentManagement/MetaData/IContentDefinitionManager.cs create mode 100644 src/Orchard/ContentManagement/MetaData/Models/ContentFieldDefinition.cs create mode 100644 src/Orchard/ContentManagement/MetaData/Models/ContentPartDefinition.cs create mode 100644 src/Orchard/ContentManagement/MetaData/Models/ContentTypeDefinition.cs delete mode 100644 src/Orchard/ContentManagement/MetaData/Records/ContentTypePartNameRecord.cs delete mode 100644 src/Orchard/ContentManagement/MetaData/Records/ContentTypePartRecord.cs delete mode 100644 src/Orchard/ContentManagement/MetaData/Services/ContentTypeService.cs delete mode 100644 src/Orchard/ContentManagement/MetaData/Services/IContentTypeService.cs create mode 100644 src/Orchard/ContentManagement/MetaData/Services/SettingsFormatter.cs diff --git a/src/Orchard.Core.Tests/Common/Providers/CommonAspectProviderTests.cs b/src/Orchard.Core.Tests/Common/Providers/CommonAspectProviderTests.cs index d62bae234..73cbde057 100644 --- a/src/Orchard.Core.Tests/Common/Providers/CommonAspectProviderTests.cs +++ b/src/Orchard.Core.Tests/Common/Providers/CommonAspectProviderTests.cs @@ -6,7 +6,6 @@ using JetBrains.Annotations; using Moq; using NUnit.Framework; using Orchard.ContentManagement.Aspects; -using Orchard.ContentManagement.MetaData.Records; using Orchard.Core.Common; using Orchard.Core.Common.Handlers; using Orchard.Core.Common.Models; @@ -47,8 +46,6 @@ namespace Orchard.Core.Tests.Common.Providers { get { return new[] { typeof(ContentTypeRecord), - typeof(ContentTypePartRecord), - typeof(ContentTypePartNameRecord), typeof(ContentItemRecord), typeof(ContentItemVersionRecord), typeof(CommonRecord), diff --git a/src/Orchard.Core.Tests/Common/Services/RoutableServiceTests.cs b/src/Orchard.Core.Tests/Common/Services/RoutableServiceTests.cs index 69bb981db..695589dbb 100644 --- a/src/Orchard.Core.Tests/Common/Services/RoutableServiceTests.cs +++ b/src/Orchard.Core.Tests/Common/Services/RoutableServiceTests.cs @@ -6,7 +6,6 @@ using NUnit.Framework; using Orchard.ContentManagement; using Orchard.ContentManagement.Drivers; using Orchard.ContentManagement.Handlers; -using Orchard.ContentManagement.MetaData.Records; using Orchard.ContentManagement.Records; using Orchard.Core.Common.Models; using Orchard.Core.Common.Services; @@ -182,8 +181,6 @@ namespace Orchard.Core.Tests.Common.Services { return new[] { typeof(RoutableRecord), typeof(ContentTypeRecord), - typeof(ContentTypePartRecord), - typeof(ContentTypePartNameRecord), typeof(ContentItemRecord), typeof(ContentItemVersionRecord), typeof(CommonRecord), diff --git a/src/Orchard.Core.Tests/Orchard.Core.Tests.csproj b/src/Orchard.Core.Tests/Orchard.Core.Tests.csproj index 307f9ed26..1d07df81b 100644 --- a/src/Orchard.Core.Tests/Orchard.Core.Tests.csproj +++ b/src/Orchard.Core.Tests/Orchard.Core.Tests.csproj @@ -109,6 +109,7 @@ + diff --git a/src/Orchard.Core.Tests/Scheduling/ScheduledTaskExecutorTests.cs b/src/Orchard.Core.Tests/Scheduling/ScheduledTaskExecutorTests.cs index e7a7955dd..cf3d73786 100644 --- a/src/Orchard.Core.Tests/Scheduling/ScheduledTaskExecutorTests.cs +++ b/src/Orchard.Core.Tests/Scheduling/ScheduledTaskExecutorTests.cs @@ -4,7 +4,6 @@ using Autofac; using Moq; using NUnit.Framework; using Orchard.ContentManagement; -using Orchard.ContentManagement.MetaData.Records; using Orchard.ContentManagement.Records; using Orchard.Core.Scheduling.Models; using Orchard.Core.Scheduling.Services; @@ -39,8 +38,6 @@ namespace Orchard.Core.Tests.Scheduling { get { return new[] { typeof(ContentTypeRecord), - typeof(ContentTypePartRecord), - typeof(ContentTypePartNameRecord), typeof(ContentItemRecord), typeof(ContentItemVersionRecord), typeof(ScheduledTaskRecord), diff --git a/src/Orchard.Core.Tests/Scheduling/ScheduledTaskManagerTests.cs b/src/Orchard.Core.Tests/Scheduling/ScheduledTaskManagerTests.cs index baf3063c3..fe58b9a06 100644 --- a/src/Orchard.Core.Tests/Scheduling/ScheduledTaskManagerTests.cs +++ b/src/Orchard.Core.Tests/Scheduling/ScheduledTaskManagerTests.cs @@ -5,7 +5,6 @@ using Autofac; using Moq; using NUnit.Framework; using Orchard.ContentManagement; -using Orchard.ContentManagement.MetaData.Records; using Orchard.ContentManagement.Records; using Orchard.Core.Scheduling.Models; using Orchard.Core.Scheduling.Services; @@ -42,8 +41,6 @@ namespace Orchard.Core.Tests.Scheduling { get { return new[] { typeof(ContentTypeRecord), - typeof(ContentTypePartRecord), - typeof(ContentTypePartNameRecord), typeof(ContentItemRecord), typeof(ContentItemVersionRecord), typeof(ScheduledTaskRecord), diff --git a/src/Orchard.Core.Tests/Settings/Metadata/ContentDefinitionManagerTests.cs b/src/Orchard.Core.Tests/Settings/Metadata/ContentDefinitionManagerTests.cs new file mode 100644 index 000000000..440c38864 --- /dev/null +++ b/src/Orchard.Core.Tests/Settings/Metadata/ContentDefinitionManagerTests.cs @@ -0,0 +1,211 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml.Linq; +using Autofac; +using Moq; +using NHibernate; +using NUnit.Framework; +using Orchard.ContentManagement.MetaData; +using Orchard.ContentManagement.MetaData.Builders; +using Orchard.ContentManagement.MetaData.Models; +using Orchard.ContentManagement.MetaData.Services; +using Orchard.Core.Settings.Metadata; +using Orchard.Core.Settings.Metadata.Records; +using Orchard.Data; +using Orchard.Tests; +using Orchard.Tests.Utility; + +namespace Orchard.Core.Tests.Settings.Metadata { + [TestFixture] + public class ContentDefinitionManagerTests { + private string _databaseFileName; + private ISessionFactory _sessionFactory; + private ISession _session; + private IContainer _container; + + [TestFixtureSetUp] + public void InitFixture() { + _databaseFileName = Path.GetTempFileName(); + _sessionFactory = DataUtility.CreateSessionFactory( + _databaseFileName, + typeof(ContentTypeDefinitionRecord), + typeof(ContentTypePartDefinitionRecord), + typeof(ContentPartDefinitionRecord), + typeof(ContentPartFieldDefinitionRecord), + typeof(ContentFieldDefinitionRecord) + ); + } + + [SetUp] + public void Init() { + var builder = new ContainerBuilder(); + builder.RegisterAutoMocking(); + builder.RegisterType().As(); + builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)); + builder.RegisterType(typeof(SettingsFormatter)) + .As(typeof(IMapper>)) + .As(typeof(IMapper, XElement>)); + _container = builder.Build(); + + _container.Mock() + .Setup(x => x.For(It.IsAny())) + .Returns(() => _session); + + _session = _sessionFactory.OpenSession(); + foreach (var killType in new[] { typeof(ContentTypeDefinitionRecord), typeof(ContentPartDefinitionRecord), typeof(ContentFieldDefinitionRecord) }) { + foreach (var killRecord in _session.CreateCriteria(killType).List()) { + _session.Delete(killRecord); + } + } + _session.Flush(); + } + + void ResetSession() { + _session.Flush(); + _session.Dispose(); + _session = _sessionFactory.OpenSession(); + } + + [TearDown] + public void Term() { + _session.Dispose(); + } + + [TestFixtureTearDown] + public void TermFixture() { + File.Delete(_databaseFileName); + } + + [Test] + public void NoTypesAreAvailableByDefault() { + var types = _container.Resolve().ListTypeDefinitions(); + Assert.That(types.Count(), Is.EqualTo(0)); + } + + [Test] + public void TypeRecordsAreReturned() { + var repository = _container.Resolve>(); + repository.Create(new ContentTypeDefinitionRecord { Name = "alpha" }); + repository.Create(new ContentTypeDefinitionRecord { Name = "beta" }); + ResetSession(); + var types = _container.Resolve().ListTypeDefinitions(); + Assert.That(types.Count(), Is.EqualTo(2)); + } + + [Test] + public void TypeSettingsAreParsed() { + var repository = _container.Resolve>(); + repository.Create(new ContentTypeDefinitionRecord { Name = "alpha", Settings = "" }); + ResetSession(); + var alpha = _container.Resolve().ListTypeDefinitions().Single(); + Assert.That(alpha.Settings["a"], Is.EqualTo("1")); + Assert.That(alpha.Settings["b"], Is.EqualTo("2")); + } + + [Test] + public void ContentTypesWithSettingsCanBeCreatedAndModified() { + var manager = _container.Resolve(); + manager.StoreTypeDefinition(new ContentTypeDefinitionBuilder() + .Named("alpha") + .WithSetting("a", "1") + .WithSetting("b", "2") + .Build()); + + manager.StoreTypeDefinition(new ContentTypeDefinitionBuilder() + .Named("beta") + .WithSetting("c", "3") + .WithSetting("d", "4") + .Build()); + + ResetSession(); + + var types1 = manager.ListTypeDefinitions(); + Assert.That(types1.Count(), Is.EqualTo(2)); + var alpha1 = types1.Single(t => t.Name == "alpha"); + Assert.That(alpha1.Settings["a"], Is.EqualTo("1")); + manager.StoreTypeDefinition(new ContentTypeDefinitionBuilder(alpha1).WithSetting("a", "5").Build()); + ResetSession(); + + var types2 = manager.ListTypeDefinitions(); + Assert.That(types2.Count(), Is.EqualTo(2)); + var alpha2 = types2.Single(t => t.Name == "alpha"); + Assert.That(alpha2.Settings["a"], Is.EqualTo("5")); + Assert.That(alpha2.Settings["a"], Is.EqualTo("5")); + } + + [Test] + public void StubPartDefinitionsAreCreatedWhenContentTypesAreStored() { + var manager = _container.Resolve(); + manager.StoreTypeDefinition(new ContentTypeDefinitionBuilder() + .Named("alpha") + .WithPart("foo", pb => { }) + .Build()); + + ResetSession(); + + var fooRecord = _container.Resolve>().Fetch(r => r.Name == "foo").SingleOrDefault(); + Assert.That(fooRecord, Is.Not.Null); + Assert.That(fooRecord.Name, Is.EqualTo("foo")); + + var foo = manager.GetPartDefinition("foo"); + Assert.That(foo, Is.Not.Null); + Assert.That(foo.Name, Is.EqualTo("foo")); + + var alpha = manager.GetTypeDefinition("alpha"); + Assert.That(alpha, Is.Not.Null); + Assert.That(alpha.Parts.Count(), Is.EqualTo(1)); + Assert.That(alpha.Parts.Single().PartDefinition.Name, Is.EqualTo("foo")); + } + + [Test] + public void GettingDefinitionsByNameCanReturnNullAndWillAcceptNullEmptyOrInvalidNames() { + var manager = _container.Resolve(); + Assert.That(manager.GetTypeDefinition("no such name"), Is.Null); + Assert.That(manager.GetTypeDefinition(string.Empty), Is.Null); + Assert.That(manager.GetTypeDefinition(null), Is.Null); + Assert.That(manager.GetPartDefinition("no such name"), Is.Null); + Assert.That(manager.GetPartDefinition(string.Empty), Is.Null); + Assert.That(manager.GetPartDefinition(null), Is.Null); + } + + [Test] + public void PartsAreRemovedWhenNotReferencedButPartDefinitionRemains() { + var manager = _container.Resolve(); + manager.StoreTypeDefinition( + new ContentTypeDefinitionBuilder() + .Named("alpha") + .WithPart("foo", pb => { }) + .WithPart("bar", pb => { }) + .Build()); + + AssertThatTypeHasParts("alpha","foo","bar"); + Assert.That(manager.ListPartDefinitions().Count(), Is.EqualTo(2)); + ResetSession(); + AssertThatTypeHasParts("alpha","foo","bar"); + Assert.That(manager.ListPartDefinitions().Count(), Is.EqualTo(2)); + + manager.StoreTypeDefinition( + new ContentTypeDefinitionBuilder(manager.GetTypeDefinition("alpha")) + .WithPart("frap", pb => { }) + .RemovePart("bar") + .Build()); + + AssertThatTypeHasParts("alpha","foo","frap"); + Assert.That(manager.ListPartDefinitions().Count(), Is.EqualTo(3)); + ResetSession(); + AssertThatTypeHasParts("alpha","foo","frap"); + Assert.That(manager.ListPartDefinitions().Count(), Is.EqualTo(3)); + } + + private void AssertThatTypeHasParts(string typeName, params string[] partNames) { + var type = _container.Resolve().GetTypeDefinition(typeName); + Assert.That(type, Is.Not.Null); + Assert.That(type.Parts.Count(), Is.EqualTo(partNames.Count())); + foreach(var partName in partNames) { + Assert.That(type.Parts.Select(p=>p.PartDefinition.Name), Has.Some.EqualTo(partName)); + } + } + } +} diff --git a/src/Orchard.Tests.Modules/Users/Controllers/AdminControllerTests.cs b/src/Orchard.Tests.Modules/Users/Controllers/AdminControllerTests.cs index 54dfd37f3..5b1f3a49f 100644 --- a/src/Orchard.Tests.Modules/Users/Controllers/AdminControllerTests.cs +++ b/src/Orchard.Tests.Modules/Users/Controllers/AdminControllerTests.cs @@ -6,7 +6,6 @@ using System.Web.Routing; using Autofac; using Moq; using NUnit.Framework; -using Orchard.ContentManagement.MetaData.Records; using Orchard.Data; using Orchard.Environment; using Orchard.ContentManagement; @@ -47,8 +46,6 @@ namespace Orchard.Tests.Modules.Users.Controllers { get { return new[] { typeof(UserRecord), typeof(ContentTypeRecord), - typeof(ContentTypePartRecord), - typeof(ContentTypePartNameRecord), typeof(ContentItemRecord), typeof(ContentItemVersionRecord), }; diff --git a/src/Orchard.Tests.Modules/Users/Services/MembershipServiceTests.cs b/src/Orchard.Tests.Modules/Users/Services/MembershipServiceTests.cs index 81551167c..ea7ee2f3d 100644 --- a/src/Orchard.Tests.Modules/Users/Services/MembershipServiceTests.cs +++ b/src/Orchard.Tests.Modules/Users/Services/MembershipServiceTests.cs @@ -3,7 +3,6 @@ using System.Web.Security; using Autofac; using NHibernate; using NUnit.Framework; -using Orchard.ContentManagement.MetaData.Records; using Orchard.Data; using Orchard.ContentManagement; using Orchard.ContentManagement.Handlers; @@ -42,9 +41,7 @@ namespace Orchard.Tests.Modules.Users.Services { typeof(UserRecord), typeof(ContentItemVersionRecord), typeof(ContentItemRecord), - typeof(ContentTypeRecord), - typeof(ContentTypePartRecord), - typeof(ContentTypePartNameRecord)); + typeof(ContentTypeRecord)); } [TestFixtureTearDown] diff --git a/src/Orchard.Tests/ContentManagement/ContentQueryTests.cs b/src/Orchard.Tests/ContentManagement/ContentQueryTests.cs index 55d9960e5..8b37ebe65 100644 --- a/src/Orchard.Tests/ContentManagement/ContentQueryTests.cs +++ b/src/Orchard.Tests/ContentManagement/ContentQueryTests.cs @@ -2,7 +2,6 @@ using Autofac; using NHibernate; using NUnit.Framework; -using Orchard.ContentManagement.MetaData.Records; using Orchard.Data; using Orchard.ContentManagement; using Orchard.ContentManagement.Handlers; @@ -28,9 +27,7 @@ namespace Orchard.Tests.ContentManagement { typeof(EpsilonRecord), typeof(ContentItemVersionRecord), typeof(ContentItemRecord), - typeof(ContentTypeRecord), - typeof(ContentTypePartRecord), - typeof(ContentTypePartNameRecord)); + typeof(ContentTypeRecord)); } [TestFixtureTearDown] diff --git a/src/Orchard.Tests/ContentManagement/ContentTypeMetaDataTests.cs b/src/Orchard.Tests/ContentManagement/ContentTypeMetaDataTests.cs deleted file mode 100644 index 94a31ebba..000000000 --- a/src/Orchard.Tests/ContentManagement/ContentTypeMetaDataTests.cs +++ /dev/null @@ -1,62 +0,0 @@ -using Autofac; -using NHibernate; -using NUnit.Framework; -using Orchard.ContentManagement; -using Orchard.ContentManagement.MetaData.Records; -using Orchard.ContentManagement.MetaData.Services; -using Orchard.ContentManagement.Records; -using Orchard.Data; - - -namespace Orchard.Tests.ContentManagement{ - [TestFixture] - public class ContentTypeMetaDataTests - { - private IContainer _container; - 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(ContentTypePartRecord), - typeof(ContentTypePartNameRecord), - typeof(ContentItemVersionRecord)); - } - - [TestFixtureTearDown] - public void TermFixture() - { - - } - - [SetUp] - public void Init() - { - var builder = new ContainerBuilder(); - builder.RegisterType().As(); - builder.RegisterType().As(); - builder.RegisterType().As(); - builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)); - _session = _sessionFactory.OpenSession(); - builder.RegisterInstance(new DefaultContentManagerTests.TestSessionLocator(_session)).As(); - - _container = builder.Build(); - } - - [Test] - public void MapandUnMapContentTypeToContentPart() - { - var contentTypeService = _container.Resolve(); - contentTypeService.MapContentTypeToContentPart("foo", "bar"); - Assert.IsTrue(contentTypeService.ValidateContentTypeToContentPartMapping("foo","bar"),"Content Type not successfully mapped"); - contentTypeService.UnMapContentTypeToContentPart("foo", "bar"); - Assert.IsFalse(contentTypeService.ValidateContentTypeToContentPartMapping("foo", "bar"), "Content Type mapping not successfully deleted"); - } - } -} diff --git a/src/Orchard.Tests/ContentManagement/DefaultContentManagerTests.cs b/src/Orchard.Tests/ContentManagement/DefaultContentManagerTests.cs index 6341d4f4c..36de12e5d 100644 --- a/src/Orchard.Tests/ContentManagement/DefaultContentManagerTests.cs +++ b/src/Orchard.Tests/ContentManagement/DefaultContentManagerTests.cs @@ -4,7 +4,6 @@ using System.Linq; using Autofac; using NHibernate; using NUnit.Framework; -using Orchard.ContentManagement.MetaData.Records; using Orchard.Data; using Orchard.ContentManagement; using Orchard.ContentManagement.Handlers; @@ -26,8 +25,6 @@ namespace Orchard.Tests.ContentManagement { _sessionFactory = DataUtility.CreateSessionFactory( databaseFileName, typeof(ContentTypeRecord), - typeof(ContentTypePartRecord), - typeof(ContentTypePartNameRecord), typeof(ContentItemRecord), typeof(ContentItemVersionRecord), typeof(GammaRecord), diff --git a/src/Orchard.Tests/ContentManagement/MetaData/Builders/ContentTypeDefinitionBuilderTests.cs b/src/Orchard.Tests/ContentManagement/MetaData/Builders/ContentTypeDefinitionBuilderTests.cs new file mode 100644 index 000000000..be8549f18 --- /dev/null +++ b/src/Orchard.Tests/ContentManagement/MetaData/Builders/ContentTypeDefinitionBuilderTests.cs @@ -0,0 +1,130 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NUnit.Framework; +using Orchard.ContentManagement.MetaData.Builders; + +namespace Orchard.Tests.ContentManagement.MetaData.Builders { + [TestFixture] + public class ContentTypeDefinitionBuilderTests { + [Test] + public void ContentTypeNameAndSettingsFromScratch() { + var contentTypeDefinition = new ContentTypeDefinitionBuilder() + .Named("alpha") + .WithSetting("a", "1") + .WithSetting("b", "2") + .Build(); + Assert.That(contentTypeDefinition.Name, Is.EqualTo("alpha")); + Assert.That(contentTypeDefinition.Settings.Count(), Is.EqualTo(2)); + Assert.That(contentTypeDefinition.Settings["a"], Is.EqualTo("1")); + Assert.That(contentTypeDefinition.Settings["b"], Is.EqualTo("2")); + } + + [Test] + public void ContentRebuildWithoutModification() { + var contentTypeDefinition1 = new ContentTypeDefinitionBuilder() + .Named("alpha") + .WithSetting("a", "1") + .WithSetting("b", "2") + .Build(); + var contentTypeDefinition2 = new ContentTypeDefinitionBuilder(contentTypeDefinition1) + .Build(); + Assert.That(contentTypeDefinition1, Is.Not.SameAs(contentTypeDefinition2)); + Assert.That(contentTypeDefinition2.Name, Is.EqualTo("alpha")); + Assert.That(contentTypeDefinition2.Settings.Count(), Is.EqualTo(2)); + Assert.That(contentTypeDefinition2.Settings["a"], Is.EqualTo("1")); + Assert.That(contentTypeDefinition2.Settings["b"], Is.EqualTo("2")); + } + + [Test] + public void ContentRebuildWithModification() { + var contentTypeDefinition1 = new ContentTypeDefinitionBuilder() + .Named("alpha") + .WithSetting("a", "1") + .WithSetting("b", "2") + .Build(); + var contentTypeDefinition2 = new ContentTypeDefinitionBuilder(contentTypeDefinition1) + .Named("beta") + .WithSetting("b", "22") + .WithSetting("c", "3") + .Build(); + Assert.That(contentTypeDefinition1, Is.Not.SameAs(contentTypeDefinition2)); + Assert.That(contentTypeDefinition1.Name, Is.EqualTo("alpha")); + Assert.That(contentTypeDefinition1.Settings.Count(), Is.EqualTo(2)); + Assert.That(contentTypeDefinition1.Settings["a"], Is.EqualTo("1")); + Assert.That(contentTypeDefinition1.Settings["b"], Is.EqualTo("2")); + Assert.That(contentTypeDefinition2.Name, Is.EqualTo("beta")); + Assert.That(contentTypeDefinition2.Settings.Count(), Is.EqualTo(3)); + Assert.That(contentTypeDefinition2.Settings["a"], Is.EqualTo("1")); + Assert.That(contentTypeDefinition2.Settings["b"], Is.EqualTo("22")); + Assert.That(contentTypeDefinition2.Settings["c"], Is.EqualTo("3")); + } + + [Test] + public void AddingPartWithSettings() { + var contentTypeDefinition = new ContentTypeDefinitionBuilder() + .Named("alpha") + .WithSetting("a", "1") + .WithSetting("b", "2") + .WithPart("foo", pb => pb.WithSetting("x", "10").WithSetting("y", "11")) + .Build(); + + Assert.That(contentTypeDefinition.Name, Is.EqualTo("alpha")); + Assert.That(contentTypeDefinition.Parts.Count(), Is.EqualTo(1)); + Assert.That(contentTypeDefinition.Parts.Single().PartDefinition.Name, Is.EqualTo("foo")); + Assert.That(contentTypeDefinition.Parts.Single().Settings.Count(), Is.EqualTo(2)); + Assert.That(contentTypeDefinition.Parts.Single().Settings["x"], Is.EqualTo("10")); + Assert.That(contentTypeDefinition.Parts.Single().Settings["y"], Is.EqualTo("11")); + } + + [Test] + public void CanAlterPartSettingsByNameDuringBuild() { + var contentTypeDefinition = new ContentTypeDefinitionBuilder() + .Named("alpha") + .WithSetting("a", "1") + .WithSetting("b", "2") + .WithPart("foo", pb => pb.WithSetting("x", "10")) + .WithPart("foo", pb => pb.WithSetting("y", "11")) + .Build(); + + Assert.That(contentTypeDefinition.Name, Is.EqualTo("alpha")); + Assert.That(contentTypeDefinition.Parts.Count(), Is.EqualTo(1)); + Assert.That(contentTypeDefinition.Parts.Single().PartDefinition.Name, Is.EqualTo("foo")); + Assert.That(contentTypeDefinition.Parts.Single().Settings.Count(), Is.EqualTo(2)); + Assert.That(contentTypeDefinition.Parts.Single().Settings["x"], Is.EqualTo("10")); + Assert.That(contentTypeDefinition.Parts.Single().Settings["y"], Is.EqualTo("11")); + } + + [Test] + public void CanAlterPartSettingsByNameDuringRebuild() { + var contentTypeDefinition1 = new ContentTypeDefinitionBuilder() + .Named("alpha") + .WithPart("foo", pb => pb.WithSetting("x", "10").WithSetting("y", "11")) + .Build(); + + var contentTypeDefinition2 = new ContentTypeDefinitionBuilder(contentTypeDefinition1) + .WithPart("foo", pb => pb.WithSetting("x", "12").WithSetting("z", "13")) + .Build(); + + Assert.That(contentTypeDefinition1.Name, Is.EqualTo("alpha")); + Assert.That(contentTypeDefinition1.Parts.Count(), Is.EqualTo(1)); + Assert.That(contentTypeDefinition1.Parts.Single().PartDefinition.Name, Is.EqualTo("foo")); + Assert.That(contentTypeDefinition1.Parts.Single().Settings.Count(), Is.EqualTo(2)); + Assert.That(contentTypeDefinition1.Parts.Single().Settings["x"], Is.EqualTo("10")); + Assert.That(contentTypeDefinition1.Parts.Single().Settings["y"], Is.EqualTo("11")); + Assert.That(contentTypeDefinition2.Name, Is.EqualTo("alpha")); + Assert.That(contentTypeDefinition2.Parts.Count(), Is.EqualTo(1)); + Assert.That(contentTypeDefinition2.Parts.Single().PartDefinition.Name, Is.EqualTo("foo")); + Assert.That(contentTypeDefinition2.Parts.Single().Settings.Count(), Is.EqualTo(3)); + Assert.That(contentTypeDefinition2.Parts.Single().Settings["x"], Is.EqualTo("12")); + Assert.That(contentTypeDefinition2.Parts.Single().Settings["y"], Is.EqualTo("11")); + Assert.That(contentTypeDefinition2.Parts.Single().Settings["z"], Is.EqualTo("13")); + } + + [Test, IgnoreAttribute("Merging not yet implemented")] + public void ContentMergeOverlaysSettings() { + Assert.Fail(); + } + } +} diff --git a/src/Orchard.Tests/Orchard.Framework.Tests.csproj b/src/Orchard.Tests/Orchard.Framework.Tests.csproj index 258137642..5d469d06c 100644 --- a/src/Orchard.Tests/Orchard.Framework.Tests.csproj +++ b/src/Orchard.Tests/Orchard.Framework.Tests.csproj @@ -148,12 +148,12 @@ Code - Code + diff --git a/src/Orchard.Web/Core/Orchard.Core.csproj b/src/Orchard.Web/Core/Orchard.Core.csproj index b7d14d395..b29aa2515 100644 --- a/src/Orchard.Web/Core/Orchard.Core.csproj +++ b/src/Orchard.Web/Core/Orchard.Core.csproj @@ -143,6 +143,12 @@ + + + + + + diff --git a/src/Orchard.Web/Core/Settings/Metadata/ContentDefinitionManager.cs b/src/Orchard.Web/Core/Settings/Metadata/ContentDefinitionManager.cs new file mode 100644 index 000000000..c3be204ac --- /dev/null +++ b/src/Orchard.Web/Core/Settings/Metadata/ContentDefinitionManager.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using Orchard.ContentManagement.MetaData; +using Orchard.ContentManagement.MetaData.Models; +using Orchard.Core.Settings.Metadata.Records; +using Orchard.Data; +using Orchard.Logging; +using Orchard.Utility.Extensions; + +namespace Orchard.Core.Settings.Metadata { + public class ContentDefinitionManager : Component, IContentDefinitionManager { + private readonly IRepository _typeDefinitionRepository; + private readonly IRepository _partDefinitionRepository; + private readonly IMapper> _settingsReader; + private readonly IMapper, XElement> _settingsWriter; + + public ContentDefinitionManager( + IRepository typeDefinitionRepository, + IRepository partDefinitionRepository, + IMapper> settingsReader, + IMapper, XElement> settingsWriter) { + _typeDefinitionRepository = typeDefinitionRepository; + _partDefinitionRepository = partDefinitionRepository; + _settingsReader = settingsReader; + _settingsWriter = settingsWriter; + } + + public ContentTypeDefinition GetTypeDefinition(string name) { + return _typeDefinitionRepository.Fetch(x => x.Name == name).Select(Build).SingleOrDefault(); + } + + public ContentPartDefinition GetPartDefinition(string name) { + return _partDefinitionRepository.Fetch(x => x.Name == name).Select(Build).SingleOrDefault(); + } + + public IEnumerable ListTypeDefinitions() { + return _typeDefinitionRepository.Fetch(x => !x.Hidden).Select(Build).ToReadOnlyCollection(); + } + + public IEnumerable ListPartDefinitions() { + return _partDefinitionRepository.Fetch(x => !x.Hidden).Select(Build).ToReadOnlyCollection(); + } + + public void StoreTypeDefinition(ContentTypeDefinition contentTypeDefinition) { + Apply(contentTypeDefinition, Acquire(contentTypeDefinition)); + } + + public void StorePartDefinition(ContentPartDefinition contentPartDefinition) { + throw new NotImplementedException(); + } + + private ContentTypeDefinitionRecord Acquire(ContentTypeDefinition contentTypeDefinition) { + var result = _typeDefinitionRepository.Fetch(x => x.Name == contentTypeDefinition.Name).SingleOrDefault(); + if (result == null) { + result = new ContentTypeDefinitionRecord { Name = contentTypeDefinition.Name }; + _typeDefinitionRepository.Create(result); + } + return result; + } + + private ContentPartDefinitionRecord Acquire(ContentPartDefinition contentPartDefinition) { + var result = _partDefinitionRepository.Fetch(x => x.Name == contentPartDefinition.Name).SingleOrDefault(); + if (result == null) { + result = new ContentPartDefinitionRecord { Name = contentPartDefinition.Name }; + _partDefinitionRepository.Create(result); + } + return result; + } + + private void Apply(ContentTypeDefinition model, ContentTypeDefinitionRecord record) { + record.Settings = _settingsWriter.Map(model.Settings).ToString(); + + var toRemove = record.ContentTypePartDefinitionRecords + .Where(partDefinitionRecord => !model.Parts.Any(part => partDefinitionRecord.ContentPartDefinitionRecord.Name == part.PartDefinition.Name)) + .ToList(); + + foreach (var remove in toRemove) { + record.ContentTypePartDefinitionRecords.Remove(remove); + } + + foreach (var part in model.Parts) { + var partName = part.PartDefinition.Name; + var typePartRecord = record.ContentTypePartDefinitionRecords.SingleOrDefault(r => r.ContentPartDefinitionRecord.Name == partName); + if (typePartRecord == null) { + typePartRecord = new ContentTypePartDefinitionRecord { ContentPartDefinitionRecord = Acquire(part.PartDefinition) }; + record.ContentTypePartDefinitionRecords.Add(typePartRecord); + } + Apply(part, typePartRecord); + } + } + + private void Apply(ContentTypeDefinition.Part model, ContentTypePartDefinitionRecord record) { + record.Settings = Compose(_settingsWriter.Map(model.Settings)); + } + + + + ContentTypeDefinition Build(ContentTypeDefinitionRecord source) { + return new ContentTypeDefinition( + source.Name, + source.ContentTypePartDefinitionRecords.Select(Build), + _settingsReader.Map(Parse(source.Settings))); + } + + ContentTypeDefinition.Part Build(ContentTypePartDefinitionRecord source) { + return new ContentTypeDefinition.Part( + Build(source.ContentPartDefinitionRecord), + _settingsReader.Map(Parse(source.Settings))); + } + + ContentPartDefinition Build(ContentPartDefinitionRecord source) { + return new ContentPartDefinition( + source.Name, + source.ContentPartFieldDefinitionRecords.Select(Build), + _settingsReader.Map(Parse(source.Settings))); + } + + ContentPartDefinition.Field Build(ContentPartFieldDefinitionRecord source) { + return new ContentPartDefinition.Field( + Build(source.ContentFieldDefinitionRecord), + source.Name, + _settingsReader.Map(Parse(source.Settings))); + } + + ContentFieldDefinition Build(ContentFieldDefinitionRecord source) { + return new ContentFieldDefinition(source.Name); + } + + XElement Parse(string settings) { + if (string.IsNullOrEmpty(settings)) + return null; + + try { + return XElement.Parse(settings); + } + catch (Exception ex) { + Logger.Error(ex, "Unable to parse settings xml"); + return null; + } + } + string Compose(XElement map) { + if (map == null) + return null; + + return map.ToString(); + } + } +} diff --git a/src/Orchard.Web/Core/Settings/Metadata/Records/ContentFieldDefinitionRecord.cs b/src/Orchard.Web/Core/Settings/Metadata/Records/ContentFieldDefinitionRecord.cs new file mode 100644 index 000000000..a8cf97aff --- /dev/null +++ b/src/Orchard.Web/Core/Settings/Metadata/Records/ContentFieldDefinitionRecord.cs @@ -0,0 +1,6 @@ +namespace Orchard.Core.Settings.Metadata.Records { + public class ContentFieldDefinitionRecord { + public virtual int Id { get; set; } + public virtual string Name { get; set; } + } +} diff --git a/src/Orchard.Web/Core/Settings/Metadata/Records/ContentPartDefinitionRecord.cs b/src/Orchard.Web/Core/Settings/Metadata/Records/ContentPartDefinitionRecord.cs new file mode 100644 index 000000000..76045f25b --- /dev/null +++ b/src/Orchard.Web/Core/Settings/Metadata/Records/ContentPartDefinitionRecord.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using Orchard.Data.Conventions; + +namespace Orchard.Core.Settings.Metadata.Records { + public class ContentPartDefinitionRecord { + public ContentPartDefinitionRecord() { + ContentPartFieldDefinitionRecords = new List(); + } + + public virtual int Id { get; set; } + public virtual string Name { get; set; } + public virtual bool Hidden { get; set; } + public virtual string Settings { get; set; } + + [CascadeAllDeleteOrphan] + public virtual IList ContentPartFieldDefinitionRecords { get; set; } + + } +} diff --git a/src/Orchard.Web/Core/Settings/Metadata/Records/ContentPartFieldDefinitionRecord.cs b/src/Orchard.Web/Core/Settings/Metadata/Records/ContentPartFieldDefinitionRecord.cs new file mode 100644 index 000000000..f85da77d0 --- /dev/null +++ b/src/Orchard.Web/Core/Settings/Metadata/Records/ContentPartFieldDefinitionRecord.cs @@ -0,0 +1,8 @@ +namespace Orchard.Core.Settings.Metadata.Records { + public class ContentPartFieldDefinitionRecord { + public virtual int Id { get; set; } + public virtual ContentFieldDefinitionRecord ContentFieldDefinitionRecord { get; set; } + public virtual string Name { get; set; } + public virtual string Settings { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Settings/Metadata/Records/ContentTypeDefinitionRecord.cs b/src/Orchard.Web/Core/Settings/Metadata/Records/ContentTypeDefinitionRecord.cs new file mode 100644 index 000000000..0f6806c19 --- /dev/null +++ b/src/Orchard.Web/Core/Settings/Metadata/Records/ContentTypeDefinitionRecord.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using Orchard.Data.Conventions; + +namespace Orchard.Core.Settings.Metadata.Records { + public class ContentTypeDefinitionRecord { + public ContentTypeDefinitionRecord() { + ContentTypePartDefinitionRecords = new List(); + } + + public virtual int Id { get; set; } + public virtual string Name { get; set; } + public virtual bool Hidden { get; set; } + public virtual string Settings { get; set; } + + [CascadeAllDeleteOrphan] + public virtual IList ContentTypePartDefinitionRecords { get; set; } + } + +} diff --git a/src/Orchard.Web/Core/Settings/Metadata/Records/ContentTypePartDefinitionRecord.cs b/src/Orchard.Web/Core/Settings/Metadata/Records/ContentTypePartDefinitionRecord.cs new file mode 100644 index 000000000..72a6fe137 --- /dev/null +++ b/src/Orchard.Web/Core/Settings/Metadata/Records/ContentTypePartDefinitionRecord.cs @@ -0,0 +1,7 @@ +namespace Orchard.Core.Settings.Metadata.Records { + public class ContentTypePartDefinitionRecord { + public virtual int Id { get; set; } + public virtual ContentPartDefinitionRecord ContentPartDefinitionRecord { get; set; } + public virtual string Settings { get; set; } + } +} diff --git a/src/Orchard.Web/Modules/Orchard.MetaData/AdminMenu.cs b/src/Orchard.Web/Modules/Orchard.MetaData/AdminMenu.cs index 24956fde2..dbba1d1be 100644 --- a/src/Orchard.Web/Modules/Orchard.MetaData/AdminMenu.cs +++ b/src/Orchard.Web/Modules/Orchard.MetaData/AdminMenu.cs @@ -12,7 +12,7 @@ namespace Orchard.MetaData { { builder.Add(T("Content Types"), "5", menu => menu - .Add(T("Content Types"), "1.0", item => item.Action("ContentTypeList", "MetaData", new { area = "Orchard.MetaData" }).Permission(Permissions.ManageMetaData)) + .Add(T("Content Types"), "1.0", item => item.Action("ContentTypeList", "Admin", new { area = "Orchard.MetaData" }).Permission(Permissions.ManageMetaData)) ); } diff --git a/src/Orchard.Web/Modules/Orchard.MetaData/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.MetaData/Controllers/AdminController.cs new file mode 100644 index 000000000..baae2d64c --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MetaData/Controllers/AdminController.cs @@ -0,0 +1,82 @@ +using System.Web.Mvc; +using Orchard.ContentManagement.MetaData; +using Orchard.Localization; +using Orchard.MetaData.ViewModels; + +namespace Orchard.MetaData.Controllers { + + public class AdminController : Controller { + private readonly IContentDefinitionManager _contentDefinitionManager; + public IOrchardServices Services { get; set; } + + public AdminController(IOrchardServices services, IContentDefinitionManager contentDefinitionManager) { + _contentDefinitionManager = contentDefinitionManager; + Services = services; + T = NullLocalizer.Instance; + } + + public Localizer T { get; set; } + // + // GET: /ContentTypeList/ + + public ActionResult ContentTypeList(string id) { + + if (!Services.Authorizer.Authorize(Permissions.ManageMetaData, T("Not allowed to manage MetaData"))) + return new HttpUnauthorizedResult(); + + var contentTypes = _contentDefinitionManager.ListTypeDefinitions(); + var contentParts = _contentDefinitionManager.ListPartDefinitions(); + + var model = new ContentTypesIndexViewModel(); + + foreach (var contentType in contentTypes) { + var contentTypeEntry = new ContentTypeEntry { Name = contentType.Name, DisplayName = contentType.Name }; + + if (contentType.Name == id) { + foreach (var contentTypePartNameRecord in contentParts) { + var contentTypePartEntry = new ContentTypePartEntry { Name = contentTypePartNameRecord.Name }; + foreach (var contentTypePartEntryTest in contentType.Parts) { + if (contentTypePartEntryTest.PartDefinition.Name == contentTypePartEntry.Name) { + contentTypePartEntry.Selected = true; + } + } + model.ContentTypeParts.Add(contentTypePartEntry); + } + model.SelectedContentType = contentTypeEntry; + } + model.ContentTypes.Add(contentTypeEntry); + } + return View(model); + } + + + // + // POST: /ContentTypeList/Save + [HttpPost] + public ActionResult Save(string id, FormCollection collection) { + if (!Services.Authorizer.Authorize(Permissions.ManageMetaData, T("Not allowed to manage MetaData"))) + return new HttpUnauthorizedResult(); + + var existingDefinition = _contentDefinitionManager.GetTypeDefinition(id); + + _contentDefinitionManager.AlterTypeDefinition(id, alter => { + foreach(var part in existingDefinition.Parts) { + alter.RemovePart(part.PartDefinition.Name); + } + foreach (var formKey in collection.AllKeys) { + if (formKey.Contains("part_")) { + var partName = formKey.Replace("part_", ""); + alter.WithPart(partName); + } + } + + }); + + return RedirectToAction("ContentTypeList", new { id }); + + + } + + + } +} diff --git a/src/Orchard.Web/Modules/Orchard.MetaData/Controllers/MetaDataController.cs b/src/Orchard.Web/Modules/Orchard.MetaData/Controllers/MetaDataController.cs deleted file mode 100644 index 2e6f991c5..000000000 --- a/src/Orchard.Web/Modules/Orchard.MetaData/Controllers/MetaDataController.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System.Web.Mvc; -using Orchard.ContentManagement.MetaData.Services; -using Orchard.Localization; -using Orchard.MetaData.ViewModels; -using Orchard.UI.Admin; - -namespace Orchard.MetaData.Controllers -{ - [Admin] - public class MetaDataController : Controller - { - private readonly IContentTypeService _contentTypeService; - public IOrchardServices Services { get; set; } - - public MetaDataController(IOrchardServices services, IContentTypeService contentTypeService) - { - _contentTypeService = contentTypeService; - Services = services; - T = NullLocalizer.Instance; - } - - public Localizer T { get; set; } - // - // GET: /ContentTypeList/ - - public ActionResult ContentTypeList(string id) { - - if (!Services.Authorizer.Authorize(Permissions.ManageMetaData, T("Not allowed to manage MetaData"))) - return new HttpUnauthorizedResult(); - - var contentTypes = _contentTypeService.GetContentTypes(); - var contentTypePartNames = _contentTypeService.GetContentTypePartNames(); - - var model = new ContentTypesIndexViewModel(); - - foreach(var contentType in contentTypes) { - var contentTypeEntry = new ContentTypeEntry {Name = contentType.Name,DisplayName = contentType.Name}; - - if (contentType.Name==id) { - foreach(var contentTypePartNameRecord in contentTypePartNames) { - var contentTypePartEntry = new ContentTypePartEntry { Name = contentTypePartNameRecord.PartName }; - foreach(var contentTypePartEntryTest in contentType.ContentParts) { - if (contentTypePartEntryTest.PartName.PartName==contentTypePartEntry.Name) { - contentTypePartEntry.Selected = true; - } - } - model.ContentTypeParts.Add(contentTypePartEntry); - } - model.SelectedContentType = contentTypeEntry; - } - model.ContentTypes.Add(contentTypeEntry); - } - return View(model); - } - - - // - // POST: /ContentTypeList/Save - [HttpPost] - public ActionResult Save(string id, FormCollection collection) - { - if (!Services.Authorizer.Authorize(Permissions.ManageMetaData, T("Not allowed to manage MetaData"))) - return new HttpUnauthorizedResult(); - - var contentTypeRecord = _contentTypeService.GetContentTypeRecord(id); - //using a while loop because we are removing items from the collection - while (contentTypeRecord.ContentParts.Count>0) { - _contentTypeService.UnMapContentTypeToContentPart(contentTypeRecord.Name, contentTypeRecord.ContentParts[0].PartName.PartName); - } - foreach(var formKey in collection.AllKeys) { - if (formKey.Contains("part_")) { - var partName = formKey.Replace("part_", ""); - _contentTypeService.MapContentTypeToContentPart(contentTypeRecord.Name,partName); - } - } - - return RedirectToAction("ContentTypeList", new { id }); - - - } - - - } -} diff --git a/src/Orchard.Web/Modules/Orchard.MetaData/Orchard.MetaData.csproj b/src/Orchard.Web/Modules/Orchard.MetaData/Orchard.MetaData.csproj index 5f6504dcd..5f110a3d1 100644 --- a/src/Orchard.Web/Modules/Orchard.MetaData/Orchard.MetaData.csproj +++ b/src/Orchard.Web/Modules/Orchard.MetaData/Orchard.MetaData.csproj @@ -66,7 +66,7 @@ - + @@ -74,7 +74,7 @@ - + diff --git a/src/Orchard.Web/Modules/Orchard.MetaData/Views/MetaData/ContentTypeList.ascx b/src/Orchard.Web/Modules/Orchard.MetaData/Views/Admin/ContentTypeList.ascx similarity index 100% rename from src/Orchard.Web/Modules/Orchard.MetaData/Views/MetaData/ContentTypeList.ascx rename to src/Orchard.Web/Modules/Orchard.MetaData/Views/Admin/ContentTypeList.ascx diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs b/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs index 26e50d90a..49cbb27d4 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs @@ -3,6 +3,8 @@ using System.Linq; using System.Web; using Orchard.Comments.Models; using Orchard.ContentManagement; +using Orchard.ContentManagement.MetaData; +using Orchard.ContentManagement.MetaData.Builders; using Orchard.Core.Common.Models; using Orchard.Core.Navigation.Models; using Orchard.Core.Settings.Models; @@ -79,7 +81,7 @@ namespace Orchard.Setup.Services { } var shellSettings = new ShellSettings(_shellSettings); - + if (string.IsNullOrEmpty(shellSettings.DataProvider)) { shellSettings.DataProvider = context.DatabaseProvider; shellSettings.DataConnectionString = context.DatabaseConnectionString; @@ -169,23 +171,10 @@ namespace Orchard.Setup.Services { authenticationService.SignIn(user, true); } - //Add ContentType mappings - var contentTypeService = environment.Resolve(); - - //Add ContentTypePartNames to MetaData - contentTypeService.AddContentTypePartNameToMetaData("HasComments"); - contentTypeService.AddContentTypePartNameToMetaData("HasTags"); - - //Add mappings from ContentTypes to ContentParts to MetaData - contentTypeService.MapContentTypeToContentPart("blogpost","HasComments"); - contentTypeService.MapContentTypeToContentPart("page", "HasComments"); - contentTypeService.MapContentTypeToContentPart("sandboxpage", "HasComments"); - contentTypeService.MapContentTypeToContentPart("blogpost", "HasTags"); - contentTypeService.MapContentTypeToContentPart("page", "HasTags"); - contentTypeService.MapContentTypeToContentPart("sandboxpage", "HasTags"); - - - + var contentDefinitionManager = environment.Resolve(); + contentDefinitionManager.AlterTypeDefinition("blogpost", cfg => cfg.WithPart("HasComments").WithPart("HasTags")); + contentDefinitionManager.AlterTypeDefinition("page", cfg => cfg.WithPart("HasComments").WithPart("HasTags")); + contentDefinitionManager.AlterTypeDefinition("sandboxpage", cfg => cfg.WithPart("HasComments").WithPart("HasTags")); } catch { environment.Resolve().Cancel(); diff --git a/src/Orchard/ContentManagement/ContentField.cs b/src/Orchard/ContentManagement/ContentField.cs new file mode 100644 index 000000000..953c94953 --- /dev/null +++ b/src/Orchard/ContentManagement/ContentField.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Orchard.ContentManagement.MetaData.Models; + +namespace Orchard.ContentManagement { + public class ContentField { + public string Name { get; set; } + public ContentFieldDefinition Definition { get; set; } + } +} diff --git a/src/Orchard/ContentManagement/ContentItem.cs b/src/Orchard/ContentManagement/ContentItem.cs index 42956b558..a6f751230 100644 --- a/src/Orchard/ContentManagement/ContentItem.cs +++ b/src/Orchard/ContentManagement/ContentItem.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Orchard.ContentManagement.MetaData.Models; using Orchard.ContentManagement.Records; namespace Orchard.ContentManagement { @@ -17,6 +18,7 @@ namespace Orchard.ContentManagement { public int Version { get { return VersionRecord == null ? 0 : VersionRecord.Number; } } public string ContentType { get; set; } + public ContentTypeDefinition TypeDefinition { get; set; } public ContentItemRecord Record { get { return VersionRecord == null ? null : VersionRecord.ContentItemRecord; } } public ContentItemVersionRecord VersionRecord { get; set; } diff --git a/src/Orchard/ContentManagement/ContentPart.cs b/src/Orchard/ContentManagement/ContentPart.cs index 180ea362f..f360ef5bc 100644 --- a/src/Orchard/ContentManagement/ContentPart.cs +++ b/src/Orchard/ContentManagement/ContentPart.cs @@ -1,8 +1,12 @@ +using Orchard.ContentManagement.MetaData.Models; 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.Part TypePartDefinition { get; set; } + public ContentPartDefinition PartDefinition { get; set; } } public class ContentPart : ContentPart { diff --git a/src/Orchard/ContentManagement/Drivers/ContentItemDriverHandler.cs b/src/Orchard/ContentManagement/Drivers/ContentItemDriverHandler.cs index ca2cbd200..f6d456c32 100644 --- a/src/Orchard/ContentManagement/Drivers/ContentItemDriverHandler.cs +++ b/src/Orchard/ContentManagement/Drivers/ContentItemDriverHandler.cs @@ -5,7 +5,7 @@ using Orchard.Logging; namespace Orchard.ContentManagement.Drivers { [UsedImplicitly] - public class ContentItemDriverHandler : IContentHandler { + public class ContentItemDriverHandler : ContentHandlerBase { private readonly IEnumerable _drivers; public ContentItemDriverHandler(IEnumerable drivers) { @@ -15,33 +15,17 @@ namespace Orchard.ContentManagement.Drivers { public ILogger Logger { get; set; } - IEnumerable IContentHandler.GetContentTypes() { + public override IEnumerable GetContentTypes() { var contentTypes = new List(); _drivers.Invoke(driver=>contentTypes.AddRange(driver.GetContentTypes()), Logger); return contentTypes; } - 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.Versioning(VersionContentContext context) { } - void IContentHandler.Versioned(VersionContentContext context) { } - void IContentHandler.Publishing(PublishContentContext context) { } - void IContentHandler.Published(PublishContentContext context) { } - void IContentHandler.Removing(RemoveContentContext context) { } - void IContentHandler.Removed(RemoveContentContext context) { } - void IContentHandler.Indexing(IndexContentContext context) { } - void IContentHandler.Indexed(IndexContentContext context) { } - - - void IContentHandler.GetContentItemMetadata(GetContentItemMetadataContext context) { + public override void GetContentItemMetadata(GetContentItemMetadataContext context) { _drivers.Invoke(driver => driver.GetContentItemMetadata(context), Logger); } - void IContentHandler.BuildDisplayModel(BuildDisplayModelContext context) { + public override void BuildDisplayModel(BuildDisplayModelContext context) { _drivers.Invoke(driver => { var result = driver.BuildDisplayModel(context); if (result != null) @@ -49,7 +33,7 @@ namespace Orchard.ContentManagement.Drivers { }, Logger); } - void IContentHandler.BuildEditorModel(BuildEditorModelContext context) { + public override void BuildEditorModel(BuildEditorModelContext context) { _drivers.Invoke(driver => { var result = driver.BuildEditorModel(context); if (result != null) @@ -57,7 +41,7 @@ namespace Orchard.ContentManagement.Drivers { }, Logger); } - void IContentHandler.UpdateEditorModel(UpdateEditorModelContext context) { + public override void UpdateEditorModel(UpdateEditorModelContext context) { _drivers.Invoke(driver => { var result = driver.UpdateEditorModel(context); if (result != null) diff --git a/src/Orchard/ContentManagement/Handlers/ContentHandlerBase.cs b/src/Orchard/ContentManagement/Handlers/ContentHandlerBase.cs new file mode 100644 index 000000000..f8026393a --- /dev/null +++ b/src/Orchard/ContentManagement/Handlers/ContentHandlerBase.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Orchard.ContentManagement.Handlers { + public class ContentHandlerBase : IContentHandler { + public virtual IEnumerable GetContentTypes() { + return Enumerable.Empty(); + } + + public virtual void Activating(ActivatingContentContext context) { + } + + public virtual void Activated(ActivatedContentContext context) { + } + + public virtual void Creating(CreateContentContext context) { + } + + public virtual void Created(CreateContentContext context) { + } + + public virtual void Loading(LoadContentContext context) { + } + + public virtual void Loaded(LoadContentContext context) { + } + + public virtual void Versioning(VersionContentContext context) { + } + + public virtual void Versioned(VersionContentContext context) { + } + + public virtual void Publishing(PublishContentContext context) { + } + + public virtual void Published(PublishContentContext context) { + } + + public virtual void Removing(RemoveContentContext context) { + } + + public virtual void Removed(RemoveContentContext context) { + } + + public virtual void Indexing(IndexContentContext context) { + } + + public virtual void Indexed(IndexContentContext context) { + } + + public virtual void GetContentItemMetadata(GetContentItemMetadataContext context) { + } + + public virtual void BuildDisplayModel(BuildDisplayModelContext context) { + } + + public virtual void BuildEditorModel(BuildEditorModelContext context) { + } + + public virtual void UpdateEditorModel(UpdateEditorModelContext context) { + } + } +} \ No newline at end of file diff --git a/src/Orchard/ContentManagement/Handlers/IContentHandler.cs b/src/Orchard/ContentManagement/Handlers/IContentHandler.cs index 846e6a1fd..7dc37cfa7 100644 --- a/src/Orchard/ContentManagement/Handlers/IContentHandler.cs +++ b/src/Orchard/ContentManagement/Handlers/IContentHandler.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Orchard.Events; namespace Orchard.ContentManagement.Handlers { diff --git a/src/Orchard/ContentManagement/MetaData/Builders/ContentPartDefinitionBuilder.cs b/src/Orchard/ContentManagement/MetaData/Builders/ContentPartDefinitionBuilder.cs new file mode 100644 index 000000000..4e9fc0de6 --- /dev/null +++ b/src/Orchard/ContentManagement/MetaData/Builders/ContentPartDefinitionBuilder.cs @@ -0,0 +1,19 @@ +using System; +using Orchard.ContentManagement.MetaData.Models; + +namespace Orchard.ContentManagement.MetaData.Builders { + public class ContentPartDefinitionBuilder { + public ContentPartDefinitionBuilder(ContentPartDefinition partDefinition) { + throw new NotImplementedException(); + } + + public ContentPartDefinition Build() { + throw new NotImplementedException(); + } + + public ContentPartDefinitionBuilder WithSetting(string name, string value) { + throw new NotImplementedException(); + } + + } +} \ No newline at end of file diff --git a/src/Orchard/ContentManagement/MetaData/Builders/ContentTypeDefinitionBuilder.cs b/src/Orchard/ContentManagement/MetaData/Builders/ContentTypeDefinitionBuilder.cs new file mode 100644 index 000000000..b2d997079 --- /dev/null +++ b/src/Orchard/ContentManagement/MetaData/Builders/ContentTypeDefinitionBuilder.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Orchard.ContentManagement.MetaData.Models; + +namespace Orchard.ContentManagement.MetaData.Builders { + public class ContentTypeDefinitionBuilder { + private string _name; + private readonly IList _parts; + private readonly IDictionary _settings; + + public ContentTypeDefinitionBuilder() + : this(new ContentTypeDefinition(null)) { + } + + public ContentTypeDefinitionBuilder(ContentTypeDefinition existing) { + if (existing == null) { + _parts = new List(); + _settings = new Dictionary(); + } + else { + _name = existing.Name; + _parts = existing.Parts.ToList(); + _settings = existing.Settings.ToDictionary(kv => kv.Key, kv => kv.Value); + } + } + + private void Init(ContentTypeDefinition existing) { + + } + + public ContentTypeDefinition Build() { + return new ContentTypeDefinition(_name, _parts, _settings); + } + + public ContentTypeDefinitionBuilder Named(string name) { + _name = name; + return this; + } + + public ContentTypeDefinitionBuilder WithSetting(string name, string value) { + _settings[name] = value; + return this; + } + + public ContentTypeDefinitionBuilder RemovePart(string partName) { + var existingPart = _parts.SingleOrDefault(x => x.PartDefinition.Name == partName); + if (existingPart != null) { + _parts.Remove(existingPart); + } + return this; + } + + public ContentTypeDefinitionBuilder WithPart(string partName) { + return WithPart(partName, configuration => { }); + } + + public ContentTypeDefinitionBuilder WithPart(string partName, Action configuration) { + return WithPart(new ContentPartDefinition(partName), configuration); + } + + public ContentTypeDefinitionBuilder WithPart(ContentPartDefinition partDefinition, Action configuration) { + var existingPart = _parts.SingleOrDefault(x => x.PartDefinition.Name == partDefinition.Name); + if (existingPart != null) { + _parts.Remove(existingPart); + } + else { + existingPart = new ContentTypeDefinition.Part(partDefinition, new Dictionary()); + } + var configurer = new PartConfigurerImpl(existingPart); + configuration(configurer); + _parts.Add(configurer.Build()); + return this; + } + + public abstract class PartConfigurer { + protected readonly IDictionary _settings; + + protected PartConfigurer(ContentTypeDefinition.Part part) { + _settings = part.Settings.ToDictionary(kv => kv.Key, kv => kv.Value); + } + + public PartConfigurer WithSetting(string name, string value) { + _settings[name] = value; + return this; + } + } + + class PartConfigurerImpl : PartConfigurer { + private readonly ContentPartDefinition _partDefinition; + + public PartConfigurerImpl(ContentTypeDefinition.Part part) + : base(part) { + _partDefinition = part.PartDefinition; + } + + public ContentTypeDefinition.Part Build() { + return new ContentTypeDefinition.Part(_partDefinition, _settings); + } + } + + } +} diff --git a/src/Orchard/ContentManagement/MetaData/ContentPartHandler.cs b/src/Orchard/ContentManagement/MetaData/ContentPartHandler.cs index 350e27371..4a4403115 100644 --- a/src/Orchard/ContentManagement/MetaData/ContentPartHandler.cs +++ b/src/Orchard/ContentManagement/MetaData/ContentPartHandler.cs @@ -1,32 +1,27 @@ using System.Collections.Generic; using System.Linq; using Orchard.ContentManagement.Handlers; -using Orchard.ContentManagement.MetaData.Services; using Orchard.ContentManagement.Drivers; namespace Orchard.ContentManagement.MetaData { - public class ContentPartHandler : ContentHandler { + public class ContentPartHandler : ContentHandlerBase { private readonly IEnumerable _contentPartDrivers; - private readonly IContentTypeService _contentTypeService; + private readonly IContentDefinitionManager _contentDefinitionManager; - public ContentPartHandler(IEnumerable contentPartDrivers, IContentTypeService contentTypeService) { + public ContentPartHandler(IEnumerable contentPartDrivers, IContentDefinitionManager contentDefinitionManager) { _contentPartDrivers = contentPartDrivers; - _contentTypeService = contentTypeService; + _contentDefinitionManager = contentDefinitionManager; } - protected override void Activating(ActivatingContentContext context) { - var contentTypeRecord = _contentTypeService.GetContentTypeRecord(context.ContentType); + public override void Activating(ActivatingContentContext context) { + var contentTypeRecord = _contentDefinitionManager.GetTypeDefinition(context.ContentType); if (contentTypeRecord == null) return; - var contentPartInfos = _contentPartDrivers.SelectMany(cpp => cpp.GetPartInfo()).ToList(); - - foreach (var contentTypePartRecord in contentTypeRecord.ContentParts) { - // We might have a part in the database, but the corresponding feature might not - // be enabled anymore, so we need to be resilient to that situation. - var contentPartInfo = contentPartInfos.SingleOrDefault(x => x.PartName == contentTypePartRecord.PartName.PartName); - if (contentPartInfo != null) { - context.Builder.Weld(contentPartInfo.Factory()); + 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()); } } } diff --git a/src/Orchard/ContentManagement/MetaData/IContentDefinitionManager.cs b/src/Orchard/ContentManagement/MetaData/IContentDefinitionManager.cs new file mode 100644 index 000000000..8b635f2a5 --- /dev/null +++ b/src/Orchard/ContentManagement/MetaData/IContentDefinitionManager.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using Orchard.ContentManagement.MetaData.Builders; +using Orchard.ContentManagement.MetaData.Models; + +namespace Orchard.ContentManagement.MetaData { + public interface IContentDefinitionManager : IDependency { + IEnumerable ListTypeDefinitions(); + IEnumerable ListPartDefinitions(); + + ContentTypeDefinition GetTypeDefinition(string name); + ContentPartDefinition GetPartDefinition(string name); + + void StoreTypeDefinition(ContentTypeDefinition contentTypeDefinition); + void StorePartDefinition(ContentPartDefinition contentPartDefinition); + } + + public static class ContentDefinitionManagerExtensions{ + public static void AlterTypeDefinition(this IContentDefinitionManager manager, string name, Action alteration) { + var typeDefinition = manager.GetTypeDefinition(name) ?? new ContentTypeDefinition(name); + var builder = new ContentTypeDefinitionBuilder(typeDefinition); + alteration(builder); + manager.StoreTypeDefinition(builder.Build()); + } + public static void AlterPartDefinition(this IContentDefinitionManager manager, string name, Action alteration) { + var partDefinition = manager.GetPartDefinition(name) ?? new ContentPartDefinition(name); + var builder = new ContentPartDefinitionBuilder(partDefinition); + alteration(builder); + manager.StorePartDefinition(builder.Build()); + } + } +} + diff --git a/src/Orchard/ContentManagement/MetaData/Models/ContentFieldDefinition.cs b/src/Orchard/ContentManagement/MetaData/Models/ContentFieldDefinition.cs new file mode 100644 index 000000000..6b60c4ffd --- /dev/null +++ b/src/Orchard/ContentManagement/MetaData/Models/ContentFieldDefinition.cs @@ -0,0 +1,9 @@ +namespace Orchard.ContentManagement.MetaData.Models { + public class ContentFieldDefinition { + public ContentFieldDefinition(string name) { + Name = name; + } + + public string Name { get; private set; } + } +} diff --git a/src/Orchard/ContentManagement/MetaData/Models/ContentPartDefinition.cs b/src/Orchard/ContentManagement/MetaData/Models/ContentPartDefinition.cs new file mode 100644 index 000000000..dd8bd4e9c --- /dev/null +++ b/src/Orchard/ContentManagement/MetaData/Models/ContentPartDefinition.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Orchard.Utility.Extensions; + +namespace Orchard.ContentManagement.MetaData.Models { + public class ContentPartDefinition { + public ContentPartDefinition(string name, IEnumerable fields, IDictionary settings) { + Name = name; + Fields = fields.ToReadOnlyCollection(); + Settings = settings; + } + + public ContentPartDefinition(string name) { + Name = name; + Fields = Enumerable.Empty(); + Settings = new Dictionary(); + } + + public string Name { get; private set; } + public IEnumerable Fields { get; private set; } + public IDictionary Settings { get; private set; } + + public class Field { + public Field(ContentFieldDefinition contentFieldDefinition, string name, IDictionary settings) { + FieldDefinition = contentFieldDefinition; + Name = name; + Settings = settings; + } + + public string Name { get; private set; } + public ContentFieldDefinition FieldDefinition { get; private set; } + public IDictionary Settings { get; private set; } + } + } +} diff --git a/src/Orchard/ContentManagement/MetaData/Models/ContentTypeDefinition.cs b/src/Orchard/ContentManagement/MetaData/Models/ContentTypeDefinition.cs new file mode 100644 index 000000000..ae9d2a114 --- /dev/null +++ b/src/Orchard/ContentManagement/MetaData/Models/ContentTypeDefinition.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Orchard.ContentManagement.MetaData.Models { + public class ContentTypeDefinition { + public ContentTypeDefinition(string name, IEnumerable parts, IDictionary settings) { + Name = name; + Parts = parts; + Settings = settings; + } + + public ContentTypeDefinition(string name) { + Name = name; + Parts = Enumerable.Empty(); + Settings = new Dictionary(); + } + + public string Name { get; private set; } + public IEnumerable Parts { get; private set; } + public IDictionary Settings { get; private set; } + + public class Part { + public Part(ContentPartDefinition contentPartDefinition, IDictionary settings) { + PartDefinition = contentPartDefinition; + Settings = settings; + } + + public ContentPartDefinition PartDefinition { get; private set; } + public IDictionary Settings { get; private set; } + } + } +} diff --git a/src/Orchard/ContentManagement/MetaData/Records/ContentTypePartNameRecord.cs b/src/Orchard/ContentManagement/MetaData/Records/ContentTypePartNameRecord.cs deleted file mode 100644 index 7f0caddb2..000000000 --- a/src/Orchard/ContentManagement/MetaData/Records/ContentTypePartNameRecord.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Orchard.ContentManagement.MetaData.Records { - public class ContentTypePartNameRecord { - public virtual int Id { get; set; } - public virtual string PartName { get; set; } - } -} diff --git a/src/Orchard/ContentManagement/MetaData/Records/ContentTypePartRecord.cs b/src/Orchard/ContentManagement/MetaData/Records/ContentTypePartRecord.cs deleted file mode 100644 index e723d18e7..000000000 --- a/src/Orchard/ContentManagement/MetaData/Records/ContentTypePartRecord.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Orchard.ContentManagement.MetaData.Records { - public class ContentTypePartRecord { - public virtual int Id { get; set; } - public virtual ContentTypePartNameRecord PartName { get; set; } - } -} diff --git a/src/Orchard/ContentManagement/MetaData/Services/ContentTypeService.cs b/src/Orchard/ContentManagement/MetaData/Services/ContentTypeService.cs deleted file mode 100644 index a0b71bb20..000000000 --- a/src/Orchard/ContentManagement/MetaData/Services/ContentTypeService.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using JetBrains.Annotations; -using Orchard.ContentManagement.MetaData.Records; -using Orchard.ContentManagement.Records; -using Orchard.Data; - -namespace Orchard.ContentManagement.MetaData.Services { - [UsedImplicitly] - public class ContentTypeService : IContentTypeService { - private readonly IRepository _contentTypeRepository; - private readonly IRepository _contentTypePartNameRepository; - private readonly IRepository _contentTypePartRepository; - - public ContentTypeService(IRepository contentTypePartRepository, IRepository contentTypeRepository, IRepository contentTypePartNameRepository) { - _contentTypeRepository = contentTypeRepository; - _contentTypePartNameRepository = contentTypePartNameRepository; - _contentTypePartRepository = contentTypePartRepository; - } - - public ContentTypeRecord GetContentTypeRecord(string contentTypeName) { - return _contentTypeRepository.Fetch(x => x.Name == contentTypeName).SingleOrDefault(); - } - - public ContentTypePartNameRecord GetContentPartNameRecord(string name) { - return _contentTypePartNameRepository.Fetch(x => x.PartName == name).SingleOrDefault(); - } - - public IEnumerable GetContentTypes() { - return _contentTypeRepository.Table.ToList(); - } - - public IEnumerable GetContentTypePartNames() { - return _contentTypePartNameRepository.Table.ToList(); - } - - public void MapContentTypeToContentPart(string contentType, string contentPart) { - // Create content type if needed - var contentTypeRecord = GetContentTypeRecord(contentType); - if (contentTypeRecord == null) { - contentTypeRecord = new ContentTypeRecord { Name = contentType }; - _contentTypeRepository.Create(contentTypeRecord); - } - - // Create part name if needed - var contentTypePartNameRecord = GetContentPartNameRecord(contentPart); - if (contentTypePartNameRecord == null) { - contentTypePartNameRecord = new ContentTypePartNameRecord { PartName = contentPart }; - _contentTypePartNameRepository.Create(contentTypePartNameRecord); - } - - // Add part name to content type - var contentTypePartRecord = new ContentTypePartRecord { PartName = contentTypePartNameRecord }; - contentTypeRecord.ContentParts.Add(contentTypePartRecord); - } - - public void UnMapContentTypeToContentPart(string contentType, string contentPart) { - var contentTypeRecord = GetContentTypeRecord(contentType); - var contentTypePartNameRecord = _contentTypePartNameRepository.Fetch(x => x.PartName == contentPart).Single(); - var contentTypePartRecord = contentTypeRecord.ContentParts.Single(x => x.PartName == contentTypePartNameRecord); - contentTypeRecord.ContentParts.Remove(contentTypePartRecord); - } - - public bool ValidateContentTypeToContentPartMapping(string contentType, string contentPart) { - var contentTypeRecord = GetContentTypeRecord(contentType) ?? new ContentTypeRecord(); - if (contentTypeRecord.ContentParts.Count == 0) - return false; - var contentTypePart = contentTypeRecord.ContentParts.Single(x => x.PartName.PartName == contentPart); - return contentTypePart != null; - } - - - public void AddContentTypePartNameToMetaData(string contentTypePartName) { - var contentTypePartNameRecord = new ContentTypePartNameRecord() { - PartName = contentTypePartName - }; - - _contentTypePartNameRepository.Update(contentTypePartNameRecord); - } - } -} diff --git a/src/Orchard/ContentManagement/MetaData/Services/IContentTypeService.cs b/src/Orchard/ContentManagement/MetaData/Services/IContentTypeService.cs deleted file mode 100644 index 2ab533896..000000000 --- a/src/Orchard/ContentManagement/MetaData/Services/IContentTypeService.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Collections.Generic; -using Orchard.ContentManagement.MetaData.Records; -using Orchard.ContentManagement.Records; - -namespace Orchard.ContentManagement.MetaData.Services -{ - public interface IContentTypeService : IDependency { - void MapContentTypeToContentPart(string contentType, string contentPart); - void UnMapContentTypeToContentPart(string contentType, string contentPart); - void AddContentTypePartNameToMetaData(string contentTypePartName); - ContentTypeRecord GetContentTypeRecord(string contentTypeName); - bool ValidateContentTypeToContentPartMapping(string contentType, string contentPart); - IEnumerable GetContentTypes(); - IEnumerable GetContentTypePartNames(); - ContentTypePartNameRecord GetContentPartNameRecord(string name); - } -} diff --git a/src/Orchard/ContentManagement/MetaData/Services/SettingsFormatter.cs b/src/Orchard/ContentManagement/MetaData/Services/SettingsFormatter.cs new file mode 100644 index 000000000..f7a32f8dc --- /dev/null +++ b/src/Orchard/ContentManagement/MetaData/Services/SettingsFormatter.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; + +namespace Orchard.ContentManagement.MetaData.Services { + public class SettingsFormatter : + IMapper>, + IMapper, XElement> { + + public IDictionary Map(XElement source) { + if (source == null) + return new Dictionary(); + + return source.Attributes().ToDictionary(attr => attr.Name.LocalName, attr => attr.Value); + } + + public XElement Map(IDictionary source) { + if (source == null) + return new XElement("settings"); + + return new XElement("settings", source.Select(kv => new XAttribute(kv.Key, kv.Value))); + } + } +} diff --git a/src/Orchard/ContentManagement/Records/ContentTypeRecord.cs b/src/Orchard/ContentManagement/Records/ContentTypeRecord.cs index b21774f3f..5d05fdc54 100644 --- a/src/Orchard/ContentManagement/Records/ContentTypeRecord.cs +++ b/src/Orchard/ContentManagement/Records/ContentTypeRecord.cs @@ -1,15 +1,7 @@ -using System.Collections.Generic; -using Orchard.ContentManagement.MetaData.Records; -using Orchard.Data.Conventions; - -namespace Orchard.ContentManagement.Records { - public class ContentTypeRecord { - public ContentTypeRecord() { - ContentParts = new List(); - } +namespace Orchard.ContentManagement.Records { + public class ContentTypeRecord { public virtual int Id { get; set; } public virtual string Name { get; set; } - [CascadeAllDeleteOrphan] - public virtual IList ContentParts { get; set; } } + } diff --git a/src/Orchard/Data/SessionLocator.cs b/src/Orchard/Data/SessionLocator.cs index 55085321b..42aebec6a 100644 --- a/src/Orchard/Data/SessionLocator.cs +++ b/src/Orchard/Data/SessionLocator.cs @@ -47,15 +47,15 @@ namespace Orchard.Data { } bool IInterceptor.OnLoad(object entity, object id, object[] state, string[] propertyNames, IType[] types) { - return true; + return false; } bool IInterceptor.OnFlushDirty(object entity, object id, object[] currentState, object[] previousState, string[] propertyNames, IType[] types) { - return true; + return false; } bool IInterceptor.OnSave(object entity, object id, object[] state, string[] propertyNames, IType[] types) { - return true; + return false; } void IInterceptor.OnDelete(object entity, object id, object[] state, string[] propertyNames, IType[] types) { diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index f43d1f4af..80aea76e8 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -119,6 +119,7 @@ 3.5 + False ..\..\lib\yaml\Yaml.dll @@ -129,6 +130,211 @@ + + Code + + + Code + + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + + + Code + + + Code + + + + + Code + + + Code + + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + @@ -182,10 +388,6 @@ - - - - @@ -209,18 +411,6 @@ - - - - - - - - - - - - @@ -290,60 +480,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -513,9 +651,7 @@ true - - - +