From 5667e6a99951caaac61a302cb0cf46e360a99bbe Mon Sep 17 00:00:00 2001 From: khavas Date: Tue, 18 May 2010 13:08:47 -0700 Subject: [PATCH 1/4] Added ContentType metadata feature to allow dynamic mapping. --HG-- branch : dev --- src/Orchard.5.0.ReSharper | 103 ++++++++++++++++++ .../ContentTypeMetaDataTests.cs | 63 +++++++++++ .../ContentManagement/DatabaseSetup.cs | 25 +++++ .../Orchard.Framework.Tests.csproj | 4 + .../Handlers/HasCommentsHandler.cs | 3 - .../Orchard.Setup/Services/SetupService.cs | 22 ++++ .../Orchard.Tags/Handlers/HasTagsHandler.cs | 5 +- .../Drivers/AutomaticContentPartDriver.cs | 2 +- .../Drivers/ContentItemDriver.cs | 2 +- .../Drivers/ContentPartDriver.cs | 20 +++- .../Handlers/ContentItemBuilder.cs | 6 + .../MetaData/ContentPartHandler.cs | 40 +++++++ .../MetaData/ContentPartInfo.cs | 10 ++ .../MetaData/Models/ContentTypePart.cs | 11 ++ .../Records/ContentTypePartNameRecord.cs | 6 + .../MetaData/Records/ContentTypePartRecord.cs | 6 + .../MetaData/Services/ContentTypeService.cs | 81 ++++++++++++++ .../MetaData/Services/IContentTypeService.cs | 13 +++ .../Records/ContentTypeRecord.cs | 8 +- src/Orchard/Orchard.Framework.csproj | 7 ++ 20 files changed, 425 insertions(+), 12 deletions(-) create mode 100644 src/Orchard.5.0.ReSharper create mode 100644 src/Orchard.Tests/ContentManagement/ContentTypeMetaDataTests.cs create mode 100644 src/Orchard.Tests/ContentManagement/DatabaseSetup.cs create mode 100644 src/Orchard/ContentManagement/MetaData/ContentPartHandler.cs create mode 100644 src/Orchard/ContentManagement/MetaData/ContentPartInfo.cs create mode 100644 src/Orchard/ContentManagement/MetaData/Models/ContentTypePart.cs create mode 100644 src/Orchard/ContentManagement/MetaData/Records/ContentTypePartNameRecord.cs create mode 100644 src/Orchard/ContentManagement/MetaData/Records/ContentTypePartRecord.cs create mode 100644 src/Orchard/ContentManagement/MetaData/Services/ContentTypeService.cs create mode 100644 src/Orchard/ContentManagement/MetaData/Services/IContentTypeService.cs diff --git a/src/Orchard.5.0.ReSharper b/src/Orchard.5.0.ReSharper new file mode 100644 index 000000000..21ba39891 --- /dev/null +++ b/src/Orchard.5.0.ReSharper @@ -0,0 +1,103 @@ + + + + + SOLUTION + + + END_OF_LINE + END_OF_LINE + ALWAYS_ADD + ALWAYS_ADD + ALWAYS_ADD + ALWAYS_ADD + ALWAYS_ADD + ALWAYS_ADD + END_OF_LINE + END_OF_LINE + + public + protected + internal + private + new + abstract + virtual + override + sealed + static + readonly + extern + unsafe + volatile + + END_OF_LINE + END_OF_LINE + + + + $object$_On$event$ + $event$Handler + + + + + + + + + + + + + + + + + + + + + + + + + $object$_On$event$ + $event$Handler + + + + + + + + + + + + + + $object$_On$event$ + $event$Handler + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Orchard.Tests/ContentManagement/ContentTypeMetaDataTests.cs b/src/Orchard.Tests/ContentManagement/ContentTypeMetaDataTests.cs new file mode 100644 index 000000000..dc2853d13 --- /dev/null +++ b/src/Orchard.Tests/ContentManagement/ContentTypeMetaDataTests.cs @@ -0,0 +1,63 @@ +using Autofac; +using NHibernate; +using NUnit.Framework; +using Orchard.ContentManagement.MetaData.Records; +using Orchard.ContentManagement.MetaData.Services; +using Orchard.Data; +using Orchard.ContentManagement; +using Orchard.ContentManagement.Records; + + +namespace Orchard.Tests.ContentManagement{ + [TestFixture] + 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(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/DatabaseSetup.cs b/src/Orchard.Tests/ContentManagement/DatabaseSetup.cs new file mode 100644 index 000000000..a57aaa6b9 --- /dev/null +++ b/src/Orchard.Tests/ContentManagement/DatabaseSetup.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Configuration; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TeamSystem.Data.UnitTesting; + +namespace Orchard.Tests.ContentManagement +{ + [TestClass()] + public class DatabaseSetup + { + + [AssemblyInitialize()] + public static void IntializeAssembly(TestContext ctx) + { + // Setup the test database based on setting in the + // configuration file + DatabaseTestClass.TestService.DeployDatabaseProject(); + DatabaseTestClass.TestService.GenerateData(); + } + + } +} diff --git a/src/Orchard.Tests/Orchard.Framework.Tests.csproj b/src/Orchard.Tests/Orchard.Framework.Tests.csproj index f36cac6bf..756c40f2f 100644 --- a/src/Orchard.Tests/Orchard.Framework.Tests.csproj +++ b/src/Orchard.Tests/Orchard.Framework.Tests.csproj @@ -64,6 +64,8 @@ False ..\..\lib\machine.migrations\Machine.Migrations.NHibernate.dll + + False ..\..\lib\moq\Moq.dll @@ -133,6 +135,8 @@ Code + + Code diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Handlers/HasCommentsHandler.cs b/src/Orchard.Web/Modules/Orchard.Comments/Handlers/HasCommentsHandler.cs index 9458348ac..dfa82586e 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Handlers/HasCommentsHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.Comments/Handlers/HasCommentsHandler.cs @@ -14,9 +14,6 @@ namespace Orchard.Comments.Handlers { IRepository hasCommentsRepository, ICommentService commentService) { - Filters.Add(new ActivatingFilter("sandboxpage")); - Filters.Add(new ActivatingFilter("blogpost")); - Filters.Add(new ActivatingFilter("page")); Filters.Add(StorageFilter.For(hasCommentsRepository)); OnActivated((ctx, x) => { diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs b/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs index a61e4955a..a27a4eb42 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs @@ -3,6 +3,9 @@ using System.Linq; using System.Web; using Orchard.Comments.Models; using Orchard.ContentManagement; +using Orchard.ContentManagement.MetaData.Models; +using Orchard.ContentManagement.MetaData.Records; +using Orchard.ContentManagement.Records; using Orchard.Core.Common.Models; using Orchard.Core.Navigation.Models; using Orchard.Core.Settings.Models; @@ -14,6 +17,7 @@ using Orchard.Environment.ShellBuilders; using Orchard.Environment.Topology; using Orchard.Environment.Topology.Models; using Orchard.Localization; +using Orchard.ContentManagement.MetaData.Services; using Orchard.Security; using Orchard.Settings; using Orchard.Themes; @@ -159,6 +163,24 @@ namespace Orchard.Setup.Services { var authenticationService = environment.Resolve(); 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"); + + + } catch { environment.Resolve().Cancel(); diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Handlers/HasTagsHandler.cs b/src/Orchard.Web/Modules/Orchard.Tags/Handlers/HasTagsHandler.cs index aeb2b6c25..c1af0e6d2 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Handlers/HasTagsHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.Tags/Handlers/HasTagsHandler.cs @@ -10,10 +10,7 @@ namespace Orchard.Tags.Handlers { [UsedImplicitly] public class HasTagsHandler : ContentHandler { public HasTagsHandler(IRepository tagsRepository, IRepository tagsContentItemsRepository) { - Filters.Add(new ActivatingFilter("sandboxpage")); - Filters.Add(new ActivatingFilter("blogpost")); - Filters.Add(new ActivatingFilter("page")); - + OnLoading((context, tags) => { // provide names of all tags on demand diff --git a/src/Orchard/ContentManagement/Drivers/AutomaticContentPartDriver.cs b/src/Orchard/ContentManagement/Drivers/AutomaticContentPartDriver.cs index 2d927b5af..e66c8e276 100644 --- a/src/Orchard/ContentManagement/Drivers/AutomaticContentPartDriver.cs +++ b/src/Orchard/ContentManagement/Drivers/AutomaticContentPartDriver.cs @@ -1,5 +1,5 @@ namespace Orchard.ContentManagement.Drivers { - public abstract class AutomaticContentPartDriver : ContentPartDriver where TPart : class, IContent { + public abstract class AutomaticContentPartDriver : ContentPartDriver where TPart : ContentPart, new() { protected override string Prefix { get { return (typeof (TPart).Name); diff --git a/src/Orchard/ContentManagement/Drivers/ContentItemDriver.cs b/src/Orchard/ContentManagement/Drivers/ContentItemDriver.cs index 90ba0f121..d1f71ddb0 100644 --- a/src/Orchard/ContentManagement/Drivers/ContentItemDriver.cs +++ b/src/Orchard/ContentManagement/Drivers/ContentItemDriver.cs @@ -5,7 +5,7 @@ using Orchard.ContentManagement.Handlers; using Orchard.Mvc.ViewModels; namespace Orchard.ContentManagement.Drivers { - public abstract class ContentItemDriver : ContentPartDriver, IContentItemDriver where TContent : class, IContent { + public abstract class ContentItemDriver : ContentPartDriver, IContentItemDriver where TContent : ContentPart, new() { private readonly ContentType _contentType; protected virtual bool UseDefaultTemplate { get { return false; } } diff --git a/src/Orchard/ContentManagement/Drivers/ContentPartDriver.cs b/src/Orchard/ContentManagement/Drivers/ContentPartDriver.cs index 53c466aa8..70ece4268 100644 --- a/src/Orchard/ContentManagement/Drivers/ContentPartDriver.cs +++ b/src/Orchard/ContentManagement/Drivers/ContentPartDriver.cs @@ -1,13 +1,18 @@ -using Orchard.ContentManagement.Handlers; +using System.Collections.Generic; +using Orchard.ContentManagement.Handlers; +using Orchard.ContentManagement.MetaData; namespace Orchard.ContentManagement.Drivers { + public interface IContentPartDriver : IEvents { DriverResult BuildDisplayModel(BuildDisplayModelContext context); DriverResult BuildEditorModel(BuildEditorModelContext context); DriverResult UpdateEditorModel(UpdateEditorModelContext context); + + IEnumerable GetPartInfo(); } - public abstract class ContentPartDriver : IContentPartDriver where TContent : class, IContent { + public abstract class ContentPartDriver : IContentPartDriver where TContent : ContentPart, new() { protected virtual string Prefix { get { return ""; } } protected virtual string Zone { get { return "body"; } } @@ -46,5 +51,16 @@ namespace Orchard.ContentManagement.Drivers { public CombinedResult Combined(params DriverResult[] results) { return new CombinedResult(results); } + + public IEnumerable GetPartInfo() + { + var contentPartInfo = new List() { + new ContentPartInfo() + {partName = typeof(TContent).Name,Factory = () => new TContent()} + }; + + return contentPartInfo; + } + } } \ No newline at end of file diff --git a/src/Orchard/ContentManagement/Handlers/ContentItemBuilder.cs b/src/Orchard/ContentManagement/Handlers/ContentItemBuilder.cs index 4c6960eed..fc8449d6c 100644 --- a/src/Orchard/ContentManagement/Handlers/ContentItemBuilder.cs +++ b/src/Orchard/ContentManagement/Handlers/ContentItemBuilder.cs @@ -15,5 +15,11 @@ _item.Weld(part); return this; } + + public ContentItemBuilder Weld(ContentPart contentPart) { + _item.Weld(contentPart); + return this; + } + } } diff --git a/src/Orchard/ContentManagement/MetaData/ContentPartHandler.cs b/src/Orchard/ContentManagement/MetaData/ContentPartHandler.cs new file mode 100644 index 000000000..9ecb104f5 --- /dev/null +++ b/src/Orchard/ContentManagement/MetaData/ContentPartHandler.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using JetBrains.Annotations; +using Orchard.ContentManagement.Handlers; +using Orchard.ContentManagement.MetaData.Records; +using Orchard.ContentManagement.MetaData.Services; +using Orchard.Data; +using Orchard.ContentManagement.Drivers; +using Orchard.ContentManagement.Records; + +namespace Orchard.ContentManagement.MetaData +{ + [UsedImplicitly] + public class ContentPartHandler : ContentHandler + { + private readonly IEnumerable _contentPartInfos; + private readonly IContentTypeService _contentTypeService; + + public ContentPartHandler(IEnumerable contentPartDrivers, IOrchardServices orchardServices, IContentTypeService contentTypeService) { + _contentTypeService = contentTypeService; + _contentPartInfos = contentPartDrivers.SelectMany(cpp => cpp.GetPartInfo()); + } + + protected override void Activating(ActivatingContentContext context) { + var contentTypeRecord = _contentTypeService.GetContentTypeRecord(context.ContentType) ?? new ContentTypeRecord(); + if (contentTypeRecord.ContentParts != null){ + foreach (var contentTypePartRecord in contentTypeRecord.ContentParts){ + var record = contentTypePartRecord; + var contentPart = _contentPartInfos.Single(x => x.partName == record.PartName).Factory(); + context.Builder.Weld(contentPart); + } + } + + } + + } + +} diff --git a/src/Orchard/ContentManagement/MetaData/ContentPartInfo.cs b/src/Orchard/ContentManagement/MetaData/ContentPartInfo.cs new file mode 100644 index 000000000..8122efbd7 --- /dev/null +++ b/src/Orchard/ContentManagement/MetaData/ContentPartInfo.cs @@ -0,0 +1,10 @@ +using System; + +namespace Orchard.ContentManagement.MetaData +{ + public class ContentPartInfo + { + public string partName; + public Func Factory; + } +} diff --git a/src/Orchard/ContentManagement/MetaData/Models/ContentTypePart.cs b/src/Orchard/ContentManagement/MetaData/Models/ContentTypePart.cs new file mode 100644 index 000000000..f4def626f --- /dev/null +++ b/src/Orchard/ContentManagement/MetaData/Models/ContentTypePart.cs @@ -0,0 +1,11 @@ +using System.Web.Mvc; +using Orchard.ContentManagement; +using Orchard.ContentManagement.MetaData.Records; + +namespace Orchard.ContentManagement.MetaData.Models +{ + public class ContentTypePart : ContentPart + { + + } +} diff --git a/src/Orchard/ContentManagement/MetaData/Records/ContentTypePartNameRecord.cs b/src/Orchard/ContentManagement/MetaData/Records/ContentTypePartNameRecord.cs new file mode 100644 index 000000000..7f0caddb2 --- /dev/null +++ b/src/Orchard/ContentManagement/MetaData/Records/ContentTypePartNameRecord.cs @@ -0,0 +1,6 @@ +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 new file mode 100644 index 000000000..93de671dc --- /dev/null +++ b/src/Orchard/ContentManagement/MetaData/Records/ContentTypePartRecord.cs @@ -0,0 +1,6 @@ +namespace Orchard.ContentManagement.MetaData.Records { + public class ContentTypePartRecord { + public virtual int Id { get; set; } + public virtual string PartName { get; set; } + } +} diff --git a/src/Orchard/ContentManagement/MetaData/Services/ContentTypeService.cs b/src/Orchard/ContentManagement/MetaData/Services/ContentTypeService.cs new file mode 100644 index 000000000..236283c73 --- /dev/null +++ b/src/Orchard/ContentManagement/MetaData/Services/ContentTypeService.cs @@ -0,0 +1,81 @@ +using System; +using System.Linq; +using Orchard.ContentManagement.MetaData.Records; +using Orchard.Data; +using System.Collections.Generic; +using JetBrains.Annotations; +using Orchard.ContentManagement.Records; + +namespace Orchard.ContentManagement.MetaData.Services +{ + [UsedImplicitly] + public class ContentTypeService : IContentTypeService + { + private readonly IRepository _contentTypeRecord; + private readonly IRepository _contentTypePartNameRecord; + private readonly IRepository _contentTypePartRecord; + + public ContentTypeService(IRepository contentTypePartRecord, IRepository contentTypeRecord, IRepository contentTypePartNameRecord) + { + _contentTypeRecord = contentTypeRecord; + _contentTypePartNameRecord = contentTypePartNameRecord; + _contentTypePartRecord = contentTypePartRecord; + } + + public void MapContentTypeToContentPart(string contentType, string contentPart) { + var contentTypeRecord = GetContentTypeRecord(contentType) ?? new ContentTypeRecord(); + contentTypeRecord.Name = contentType; + var contentTypePartRecord = new ContentTypePartRecord() { + PartName = contentPart + }; + if (contentTypeRecord.ContentParts==null) { + contentTypeRecord.ContentParts = new List { contentTypePartRecord }; + } + else { + contentTypeRecord.ContentParts.Add(contentTypePartRecord); + } + + _contentTypeRecord.Update(contentTypeRecord); + } + + public void UnMapContentTypeToContentPart(string contentType, string contentPart) { + var contentTypeRecord = GetContentTypeRecord(contentType) ?? new ContentTypeRecord(); + var contentTypePartRecord = contentTypeRecord.ContentParts.Single(x => x.PartName == contentPart); + if (contentTypePartRecord != null) + { + _contentTypePartRecord.Delete(contentTypePartRecord); + 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 == contentPart); + return contentTypePart != null; + } + + + public void AddContentTypePartNameToMetaData(string contentTypePartName) { + var contentTypePartNameRecord = new ContentTypePartNameRecord() { + PartName = contentTypePartName + }; + + _contentTypePartNameRecord.Update(contentTypePartNameRecord); + } + + public ContentTypeRecord GetContentTypeRecord(string contentTypeName) { + var contentTypeCount = _contentTypeRecord.Table.Count(x => x.Name == contentTypeName); + if (contentTypeCount > 0) { + var contentTypeRecord = _contentTypeRecord.Table.Single(x => x.Name == contentTypeName); + return contentTypeRecord; + } + else { + return null; + } + + } + + } +} diff --git a/src/Orchard/ContentManagement/MetaData/Services/IContentTypeService.cs b/src/Orchard/ContentManagement/MetaData/Services/IContentTypeService.cs new file mode 100644 index 000000000..c3cd8ce15 --- /dev/null +++ b/src/Orchard/ContentManagement/MetaData/Services/IContentTypeService.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +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); + } +} diff --git a/src/Orchard/ContentManagement/Records/ContentTypeRecord.cs b/src/Orchard/ContentManagement/Records/ContentTypeRecord.cs index f908ceff3..9aa43c07b 100644 --- a/src/Orchard/ContentManagement/Records/ContentTypeRecord.cs +++ b/src/Orchard/ContentManagement/Records/ContentTypeRecord.cs @@ -1,6 +1,12 @@ -namespace Orchard.ContentManagement.Records { +using System.Collections.Generic; +using Orchard.ContentManagement.MetaData.Records; +using Orchard.Data.Conventions; + +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/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index 62227f8d3..1b3d63aa9 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -152,6 +152,7 @@ + @@ -182,6 +183,12 @@ + + + + + + From 106eff8d3efeabc3b8dd9da8a868bb42816088ed Mon Sep 17 00:00:00 2001 From: khavas Date: Wed, 19 May 2010 10:12:04 -0700 Subject: [PATCH 2/4] ContentType MetaData UI --HG-- branch : dev --- .../Modules/Orchard.MetaData/AdminMenu.cs | 25 +++ .../Controllers/MetaDataController.cs | 79 +++++++++ .../Modules/Orchard.MetaData/Module.txt | 7 + .../Orchard.MetaData/Orchard.MetaData.csproj | 124 ++++++++++++++ .../Modules/Orchard.MetaData/Permissions.cs | 65 +++++++ .../Properties/AssemblyInfo.cs | 35 ++++ .../Orchard.MetaData/Styles/ContentTypes.css | 35 ++++ .../ViewModels/ContentTypesViewModel.cs | 31 ++++ .../Views/MetaData/ContentTypeList.ascx | 79 +++++++++ .../Modules/Orchard.MetaData/Views/Web.config | 34 ++++ .../Modules/Orchard.MetaData/Web.config | 158 ++++++++++++++++++ src/Orchard.sln | 5 + .../MetaData/Services/ContentTypeService.cs | 8 + .../MetaData/Services/IContentTypeService.cs | 3 + 14 files changed, 688 insertions(+) create mode 100644 src/Orchard.Web/Modules/Orchard.MetaData/AdminMenu.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MetaData/Controllers/MetaDataController.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MetaData/Module.txt create mode 100644 src/Orchard.Web/Modules/Orchard.MetaData/Orchard.MetaData.csproj create mode 100644 src/Orchard.Web/Modules/Orchard.MetaData/Permissions.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MetaData/Properties/AssemblyInfo.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MetaData/Styles/ContentTypes.css create mode 100644 src/Orchard.Web/Modules/Orchard.MetaData/ViewModels/ContentTypesViewModel.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MetaData/Views/MetaData/ContentTypeList.ascx create mode 100644 src/Orchard.Web/Modules/Orchard.MetaData/Views/Web.config create mode 100644 src/Orchard.Web/Modules/Orchard.MetaData/Web.config diff --git a/src/Orchard.Web/Modules/Orchard.MetaData/AdminMenu.cs b/src/Orchard.Web/Modules/Orchard.MetaData/AdminMenu.cs new file mode 100644 index 000000000..96d27c343 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MetaData/AdminMenu.cs @@ -0,0 +1,25 @@ +using System.Linq; + +using Orchard.UI.Navigation; + +namespace Orchard.MetaData { + public class AdminMenu : INavigationProvider { + //private readonly IBlogService _blogService; + + public AdminMenu() { + //_blogService = blogService; + } + + public string MenuName { get { return "admin"; } } + + public void GetNavigation(NavigationBuilder builder) + { + builder.Add("Content Types", "5", + menu => menu + .Add("Content Types", "1.0", item => item.Action("ContentTypeList", "MetaData", new { area = "Orchard.MetaData" }).Permission(Permissions.ManageMetaData)) + ); + } + + + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MetaData/Controllers/MetaDataController.cs b/src/Orchard.Web/Modules/Orchard.MetaData/Controllers/MetaDataController.cs new file mode 100644 index 000000000..18a1e7f2c --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MetaData/Controllers/MetaDataController.cs @@ -0,0 +1,79 @@ +using System.Web.Mvc; +using Orchard.ContentManagement.MetaData.Services; +using Orchard.Themes; +using Orchard.Data; +using Orchard.ContentManagement.Records; +using Orchard.ContentManagement.MetaData.Records; +using Orchard.MetaData.ViewModels; + +namespace Orchard.MetaData.Controllers +{ + [Themed] + public class MetaDataController : Controller + { + private readonly IRepository _ctps; + private readonly IContentTypeService _contentTypeService; + + public MetaDataController(IRepository ctps, IContentTypeService contentTypeService){ + _ctps = ctps; + _contentTypeService = contentTypeService; + } + + // + // GET: /ContentTypeList/ + + public ActionResult ContentTypeList(string id) { + var contentTypes = _contentTypeService.GetContentTypes(); + var contentTypePartNames = _contentTypeService.GetContentTypePartNames(); + + var model = new ContentTypesIndexViewModel(); + + foreach(ContentTypeRecord contentType in contentTypes) { + var contentTypeEntry = new ContentTypeEntry() {Name = contentType.Name,DisplayName = contentType.Name}; + + if (contentType.Name==id) { + foreach(ContentTypePartNameRecord contentTypePartNameRecord in contentTypePartNames) { + var contentTypePartEntry = new ContentTypePartEntry() { Name = contentTypePartNameRecord.PartName }; + foreach(var contentTypePartEntryTest in contentType.ContentParts) { + if (contentTypePartEntryTest.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) + { + ContentTypeRecord contentTypeRecord = _contentTypeService.GetContentTypeRecord(id); + while (contentTypeRecord.ContentParts.Count>0) { + _contentTypeService.UnMapContentTypeToContentPart(contentTypeRecord.Name, contentTypeRecord.ContentParts[0].PartName); + } + //foreach(var contentTypePartNameRecord in contentTypeRecord.ContentParts) { + // _contentTypeService.UnMapContentTypeToContentPart(contentTypeRecord.Name,contentTypePartNameRecord.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 = id }); + + + } + + + } +} diff --git a/src/Orchard.Web/Modules/Orchard.MetaData/Module.txt b/src/Orchard.Web/Modules/Orchard.MetaData/Module.txt new file mode 100644 index 000000000..a1aa2af92 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MetaData/Module.txt @@ -0,0 +1,7 @@ +name: MetaData +antiforgery: enabled +features: + Orchard.MetaData: + Description: Module for managing Orchard MetaData + Dependencies: Common, XmlRpc + Category: MetaData \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MetaData/Orchard.MetaData.csproj b/src/Orchard.Web/Modules/Orchard.MetaData/Orchard.MetaData.csproj new file mode 100644 index 000000000..fb54061a8 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MetaData/Orchard.MetaData.csproj @@ -0,0 +1,124 @@ + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {23E04990-2A8D-41B8-9908-6DDB71EA3B23} + {F85E285D-A4E0-4152-9332-AB1D724D3325};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Orchard.MetaData + Orchard.MetaData + v3.5 + false + + + true + full + false + ..\..\bin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\ + TRACE + prompt + 4 + + + + + + 3.5 + + + 3.5 + + + 3.5 + + + False + ..\..\..\..\lib\aspnetmvc\System.Web.Mvc.dll + + + 3.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6} + Orchard.Framework + + + {9916839C-39FC-4CEB-A5AF-89CA7E87119F} + Orchard.Core + + + + + + + + + + + + + + + + + + + + + + False + True + 33002 + / + + + False + False + + + False + + + + + \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MetaData/Permissions.cs b/src/Orchard.Web/Modules/Orchard.MetaData/Permissions.cs new file mode 100644 index 000000000..521e33e2b --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MetaData/Permissions.cs @@ -0,0 +1,65 @@ +using System.Collections.Generic; +using System.Linq; +using Orchard.Security.Permissions; + +namespace Orchard.MetaData { + public class Permissions : IPermissionProvider { + public static readonly Permission ManageMetaData = new Permission { Description = "Manage MetaData", Name = "ManageMetaData" };//q: Should edit_MetaData be ManageMetaData? + + public static readonly Permission PublishOthersMetaDataPost = new Permission { Description = "Publish or unpublish MetaData post for others", Name = "PublishOthersMetaDataPost", ImpliedBy = new[] { ManageMetaData } }; + public static readonly Permission PublishMetaDataPost = new Permission { Description = "Publish or unpublish MetaData post", Name = "PublishMetaDataPost", ImpliedBy = new[] { PublishOthersMetaDataPost } }; + public static readonly Permission EditOthersMetaDataPost = new Permission { Description = "Edit any MetaData posts", Name = "EditOthersMetaDataPost", ImpliedBy = new[] { PublishOthersMetaDataPost } }; + public static readonly Permission EditMetaDataPost = new Permission { Description = "Edit own MetaData posts", Name = "EditMetaDataPost", ImpliedBy = new[] { EditOthersMetaDataPost, PublishMetaDataPost } }; + public static readonly Permission DeleteOthersMetaDataPost = new Permission { Description = "Delete MetaData post for others", Name = "DeleteOthersMetaDataPost", ImpliedBy = new[] { ManageMetaData } }; + public static readonly Permission DeleteMetaDataPost = new Permission { Description = "Delete MetaData post", Name = "DeleteMetaDataPost", ImpliedBy = new[] { DeleteOthersMetaDataPost } }; + + public static readonly Permission MetaListOthersMetaData = new Permission { ImpliedBy = new[] { EditOthersMetaDataPost, PublishOthersMetaDataPost, DeleteOthersMetaDataPost } }; + public static readonly Permission MetaListMetaData = new Permission { ImpliedBy = new[] { EditMetaDataPost, PublishMetaDataPost, DeleteMetaDataPost } }; + + public string ModuleName { + get { + return "MetaData"; + } + } + + public IEnumerable GetPermissions() { + return new Permission[] { + ManageMetaData, + EditMetaDataPost, + EditOthersMetaDataPost, + PublishMetaDataPost, + PublishOthersMetaDataPost, + DeleteMetaDataPost, + DeleteOthersMetaDataPost, + }; + } + + public IEnumerable GetDefaultStereotypes() { + return new[] { + new PermissionStereotype { + Name = "Administrator", + Permissions = new[] {ManageMetaData} + }, + new PermissionStereotype { + Name = "Editor", + Permissions = new[] {PublishOthersMetaDataPost,EditOthersMetaDataPost,DeleteOthersMetaDataPost} + }, + new PermissionStereotype { + Name = "Moderator", + //Permissions = new[] {} + }, + new PermissionStereotype { + Name = "Author", + Permissions = new[] {PublishMetaDataPost,EditMetaDataPost,DeleteMetaDataPost} + }, + new PermissionStereotype { + Name = "Contributor", + Permissions = new[] {EditMetaDataPost} + }, + }; + } + + } +} + + diff --git a/src/Orchard.Web/Modules/Orchard.MetaData/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.MetaData/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..a7fe0e116 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MetaData/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Orchard.MetaData")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("Orchard.MetaData")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("9b958fbe-1d0d-4975-9a1b-7e3ff5bed510")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/Orchard.Web/Modules/Orchard.MetaData/Styles/ContentTypes.css b/src/Orchard.Web/Modules/Orchard.MetaData/Styles/ContentTypes.css new file mode 100644 index 000000000..6c7f0ddd4 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MetaData/Styles/ContentTypes.css @@ -0,0 +1,35 @@ + +.ContentTypeList +{ + width: 100px; + float:left; +} +.ContentTypePartList +{ + width: 200px; + float: left; + margin-left: 20px; +} +.ContentTypePartListRow +{ + height:5px; + padding:0px; +} +.ContentTypePartListRowItem +{ + background:#EAEAEA; + + padding:0px; + vertical-align:top; + margin:1px; + padding-top: 5px; +} + +.SelectedContentPart { + background:#D1F2A5; + border-color:#BCD994; +} +.UnSelectedContentPart { + background:#EAEAEA; + border-color:#CCC; +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MetaData/ViewModels/ContentTypesViewModel.cs b/src/Orchard.Web/Modules/Orchard.MetaData/ViewModels/ContentTypesViewModel.cs new file mode 100644 index 000000000..2fd0bc744 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MetaData/ViewModels/ContentTypesViewModel.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using Orchard.Mvc.ViewModels; + +namespace Orchard.MetaData.ViewModels +{ + public class ContentTypesIndexViewModel : BaseViewModel { + public IList ContentTypes { get; set; } + public IList ContentTypeParts { get; set; } + public ContentTypesIndexViewModel() { + ContentTypes=new List(); + ContentTypeParts = new List(); + } + public ContentTypeEntry SelectedContentType { get; set; } + } + + public class ContentTypeEntry { + public string Name { get; set; } + public string DisplayName { get; set; } + public IList ContentTypeParts { get; set; } + public ContentTypeEntry(){ + ContentTypeParts = new List(); + } + } + + public class ContentTypePartEntry { + public string Name { get; set; } + public bool Selected { get; set; } + } + + +} diff --git a/src/Orchard.Web/Modules/Orchard.MetaData/Views/MetaData/ContentTypeList.ascx b/src/Orchard.Web/Modules/Orchard.MetaData/Views/MetaData/ContentTypeList.ascx new file mode 100644 index 000000000..532150494 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MetaData/Views/MetaData/ContentTypeList.ascx @@ -0,0 +1,79 @@ + +<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl" %> +<%@ Import Namespace="Orchard.MetaData.ViewModels"%> +<% Html.RegisterStyle("ContentTypes.css"); %> + +
+ + + + + + + <% foreach (var item in Model.ContentTypes) { %> + + <% + string contentTypeClass = ""; + if (Model.SelectedContentType!=null && Model.SelectedContentType.Name == item.Name) + { + contentTypeClass = "SelectedContentPart"; + }else{ + contentTypeClass = "UnSelectedContentPart"; + } + %> + + + + + <% } %> + +
+ Content Types +
+ <%= Html.ActionLink(item.Name, "ContentTypeList", new {id=item.Name})%> +
+
+ +<%if (Model.SelectedContentType!=null) {%> + +
+ + + + + +<% +using (Html.BeginFormAntiForgeryPost(Url.Action("Save",new {id=Model.SelectedContentType.Name}))) { %> + + <% foreach (var item in Model.ContentTypeParts) { %> + + + + + + + <% } %> + +
+ + + Included Content Part +
+ <%if (item.Selected) + {%> + " type="checkbox" checked="checked" /><%} + else {%> + " type="checkbox" /><%}%> + + <%= Html.Encode(item.Name)%> +
+

+ " /> +

+ <% } %> +
+<%} %> + + + + diff --git a/src/Orchard.Web/Modules/Orchard.MetaData/Views/Web.config b/src/Orchard.Web/Modules/Orchard.MetaData/Views/Web.config new file mode 100644 index 000000000..7022197d4 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MetaData/Views/Web.config @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Modules/Orchard.MetaData/Web.config b/src/Orchard.Web/Modules/Orchard.MetaData/Web.config new file mode 100644 index 000000000..93b2ed5eb --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MetaData/Web.config @@ -0,0 +1,158 @@ + + + + + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Orchard.sln b/src/Orchard.sln index 6a548748d..ded3346ea 100644 --- a/src/Orchard.sln +++ b/src/Orchard.sln @@ -63,6 +63,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Modules", "Orchard. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Profile", "Orchard.Profile\Orchard.Profile.csproj", "{94E694A2-D140-468D-A277-C5FCE1D13E9B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.MetaData", "Orchard.Web\Modules\Orchard.MetaData\Orchard.MetaData.csproj", "{23E04990-2A8D-41B8-9908-6DDB71EA3B23}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -177,6 +179,8 @@ Global {94E694A2-D140-468D-A277-C5FCE1D13E9B}.Debug|Any CPU.Build.0 = Debug|Any CPU {94E694A2-D140-468D-A277-C5FCE1D13E9B}.Release|Any CPU.ActiveCfg = Release|Any CPU {94E694A2-D140-468D-A277-C5FCE1D13E9B}.Release|Any CPU.Build.0 = Release|Any CPU + {23E04990-2A8D-41B8-9908-6DDB71EA3B23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {23E04990-2A8D-41B8-9908-6DDB71EA3B23}.Release|Any CPU.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -202,6 +206,7 @@ Global {72457126-E118-4171-A08F-9A709EE4B7FC} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5} {CDE24A24-01D3-403C-84B9-37722E18DFB7} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5} {17F86780-9A1F-4AA1-86F1-875EEC2730C7} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5} + {23E04990-2A8D-41B8-9908-6DDB71EA3B23} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5} {5E5E7A21-C7B2-44D8-8593-2F9541AE041D} = {383DBA32-4A3E-48D1-AAC3-75377A694452} {4AB4B5B6-277E-4FF6-B69B-7AE9E16D2A56} = {383DBA32-4A3E-48D1-AAC3-75377A694452} {33B1BC8D-E292-4972-A363-22056B207156} = {383DBA32-4A3E-48D1-AAC3-75377A694452} diff --git a/src/Orchard/ContentManagement/MetaData/Services/ContentTypeService.cs b/src/Orchard/ContentManagement/MetaData/Services/ContentTypeService.cs index 236283c73..b51574664 100644 --- a/src/Orchard/ContentManagement/MetaData/Services/ContentTypeService.cs +++ b/src/Orchard/ContentManagement/MetaData/Services/ContentTypeService.cs @@ -77,5 +77,13 @@ namespace Orchard.ContentManagement.MetaData.Services } + public IEnumerable GetContentTypes() { + return _contentTypeRecord.Table.ToList(); + } + + public IEnumerable GetContentTypePartNames() { + return _contentTypePartNameRecord.Table.ToList(); + } + } } diff --git a/src/Orchard/ContentManagement/MetaData/Services/IContentTypeService.cs b/src/Orchard/ContentManagement/MetaData/Services/IContentTypeService.cs index c3cd8ce15..6b71fd20d 100644 --- a/src/Orchard/ContentManagement/MetaData/Services/IContentTypeService.cs +++ b/src/Orchard/ContentManagement/MetaData/Services/IContentTypeService.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Orchard.ContentManagement.MetaData.Records; using Orchard.ContentManagement.Records; namespace Orchard.ContentManagement.MetaData.Services @@ -9,5 +10,7 @@ namespace Orchard.ContentManagement.MetaData.Services void AddContentTypePartNameToMetaData(string contentTypePartName); ContentTypeRecord GetContentTypeRecord(string contentTypeName); bool ValidateContentTypeToContentPartMapping(string contentType, string contentPart); + IEnumerable GetContentTypes(); + IEnumerable GetContentTypePartNames(); } } From 04a2e0c3c36c07a2dd817f6877360e06d117e760 Mon Sep 17 00:00:00 2001 From: khavas Date: Wed, 19 May 2010 15:12:05 -0700 Subject: [PATCH 3/4] MetaData Review Changes --HG-- branch : dev --- .../ContentTypeMetaDataTests.cs | 1 + .../ContentManagement/DatabaseSetup.cs | 25 --------- .../Orchard.Framework.Tests.csproj | 3 -- .../Modules/Orchard.MetaData/AdminMenu.cs | 8 +-- .../Controllers/MetaDataController.cs | 47 ++++++++-------- .../Modules/Orchard.MetaData/Permissions.cs | 32 ----------- .../Properties/AssemblyInfo.cs | 1 - .../Views/MetaData/ContentTypeList.ascx | 10 ++-- .../Orchard.Setup/Services/SetupService.cs | 3 -- .../Drivers/ContentPartDriver.cs | 2 +- .../MetaData/ContentPartHandler.cs | 6 ++- .../MetaData/ContentPartInfo.cs | 4 +- .../MetaData/Models/ContentTypePart.cs | 11 ---- .../MetaData/Records/ContentTypePartRecord.cs | 2 +- .../MetaData/Services/ContentTypeService.cs | 54 ++++++++++--------- .../MetaData/Services/IContentTypeService.cs | 1 + .../Records/ContentPartRecord.cs | 3 ++ src/Orchard/Orchard.Framework.csproj | 4 +- 18 files changed, 78 insertions(+), 139 deletions(-) delete mode 100644 src/Orchard.Tests/ContentManagement/DatabaseSetup.cs delete mode 100644 src/Orchard/ContentManagement/MetaData/Models/ContentTypePart.cs diff --git a/src/Orchard.Tests/ContentManagement/ContentTypeMetaDataTests.cs b/src/Orchard.Tests/ContentManagement/ContentTypeMetaDataTests.cs index dc2853d13..ce2649630 100644 --- a/src/Orchard.Tests/ContentManagement/ContentTypeMetaDataTests.cs +++ b/src/Orchard.Tests/ContentManagement/ContentTypeMetaDataTests.cs @@ -25,6 +25,7 @@ namespace Orchard.Tests.ContentManagement{ typeof(ContentTypeRecord), typeof(ContentItemRecord), typeof(ContentTypePartRecord), + typeof(ContentTypePartNameRecord), typeof(ContentItemVersionRecord)); } diff --git a/src/Orchard.Tests/ContentManagement/DatabaseSetup.cs b/src/Orchard.Tests/ContentManagement/DatabaseSetup.cs deleted file mode 100644 index a57aaa6b9..000000000 --- a/src/Orchard.Tests/ContentManagement/DatabaseSetup.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Data; -using System.Data.Common; -using System.Configuration; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Microsoft.VisualStudio.TeamSystem.Data.UnitTesting; - -namespace Orchard.Tests.ContentManagement -{ - [TestClass()] - public class DatabaseSetup - { - - [AssemblyInitialize()] - public static void IntializeAssembly(TestContext ctx) - { - // Setup the test database based on setting in the - // configuration file - DatabaseTestClass.TestService.DeployDatabaseProject(); - DatabaseTestClass.TestService.GenerateData(); - } - - } -} diff --git a/src/Orchard.Tests/Orchard.Framework.Tests.csproj b/src/Orchard.Tests/Orchard.Framework.Tests.csproj index 756c40f2f..5eda30e2e 100644 --- a/src/Orchard.Tests/Orchard.Framework.Tests.csproj +++ b/src/Orchard.Tests/Orchard.Framework.Tests.csproj @@ -64,8 +64,6 @@ False ..\..\lib\machine.migrations\Machine.Migrations.NHibernate.dll - - False ..\..\lib\moq\Moq.dll @@ -136,7 +134,6 @@ Code - Code diff --git a/src/Orchard.Web/Modules/Orchard.MetaData/AdminMenu.cs b/src/Orchard.Web/Modules/Orchard.MetaData/AdminMenu.cs index 96d27c343..ad2c436d5 100644 --- a/src/Orchard.Web/Modules/Orchard.MetaData/AdminMenu.cs +++ b/src/Orchard.Web/Modules/Orchard.MetaData/AdminMenu.cs @@ -1,14 +1,8 @@ -using System.Linq; - + using Orchard.UI.Navigation; namespace Orchard.MetaData { public class AdminMenu : INavigationProvider { - //private readonly IBlogService _blogService; - - public AdminMenu() { - //_blogService = blogService; - } public string MenuName { get { return "admin"; } } diff --git a/src/Orchard.Web/Modules/Orchard.MetaData/Controllers/MetaDataController.cs b/src/Orchard.Web/Modules/Orchard.MetaData/Controllers/MetaDataController.cs index 18a1e7f2c..dee0f6eec 100644 --- a/src/Orchard.Web/Modules/Orchard.MetaData/Controllers/MetaDataController.cs +++ b/src/Orchard.Web/Modules/Orchard.MetaData/Controllers/MetaDataController.cs @@ -1,41 +1,46 @@ using System.Web.Mvc; using Orchard.ContentManagement.MetaData.Services; -using Orchard.Themes; -using Orchard.Data; -using Orchard.ContentManagement.Records; -using Orchard.ContentManagement.MetaData.Records; +using Orchard.Localization; using Orchard.MetaData.ViewModels; +using Orchard.UI.Admin; namespace Orchard.MetaData.Controllers { - [Themed] + [Admin] public class MetaDataController : Controller { - private readonly IRepository _ctps; private readonly IContentTypeService _contentTypeService; + public IOrchardServices Services { get; set; } - public MetaDataController(IRepository ctps, IContentTypeService contentTypeService){ - _ctps = ctps; + public MetaDataController(IOrchardServices services, IContentTypeService contentTypeService) + { _contentTypeService = contentTypeService; + Services = services; + T = NullLocalizer.Instance; } + private 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(ContentTypeRecord contentType in contentTypes) { - var contentTypeEntry = new ContentTypeEntry() {Name = contentType.Name,DisplayName = contentType.Name}; + foreach(var contentType in contentTypes) { + var contentTypeEntry = new ContentTypeEntry {Name = contentType.Name,DisplayName = contentType.Name}; if (contentType.Name==id) { - foreach(ContentTypePartNameRecord contentTypePartNameRecord in contentTypePartNames) { - var contentTypePartEntry = new ContentTypePartEntry() { Name = contentTypePartNameRecord.PartName }; + foreach(var contentTypePartNameRecord in contentTypePartNames) { + var contentTypePartEntry = new ContentTypePartEntry { Name = contentTypePartNameRecord.PartName }; foreach(var contentTypePartEntryTest in contentType.ContentParts) { - if (contentTypePartEntryTest.PartName==contentTypePartEntry.Name) { + if (contentTypePartEntryTest.PartName.PartName==contentTypePartEntry.Name) { contentTypePartEntry.Selected = true; } } @@ -44,8 +49,7 @@ namespace Orchard.MetaData.Controllers model.SelectedContentType = contentTypeEntry; } model.ContentTypes.Add(contentTypeEntry); - }; - + } return View(model); } @@ -55,13 +59,14 @@ namespace Orchard.MetaData.Controllers [HttpPost] public ActionResult Save(string id, FormCollection collection) { - ContentTypeRecord contentTypeRecord = _contentTypeService.GetContentTypeRecord(id); + 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); + _contentTypeService.UnMapContentTypeToContentPart(contentTypeRecord.Name, contentTypeRecord.ContentParts[0].PartName.PartName); } - //foreach(var contentTypePartNameRecord in contentTypeRecord.ContentParts) { - // _contentTypeService.UnMapContentTypeToContentPart(contentTypeRecord.Name,contentTypePartNameRecord.PartName); - //} foreach(var formKey in collection.AllKeys) { if (formKey.Contains("part_")) { var partName = formKey.Replace("part_", ""); @@ -69,7 +74,7 @@ namespace Orchard.MetaData.Controllers } } - return RedirectToAction("ContentTypeList", new { id = id }); + return RedirectToAction("ContentTypeList", new { id }); } diff --git a/src/Orchard.Web/Modules/Orchard.MetaData/Permissions.cs b/src/Orchard.Web/Modules/Orchard.MetaData/Permissions.cs index 521e33e2b..d0bbb35ed 100644 --- a/src/Orchard.Web/Modules/Orchard.MetaData/Permissions.cs +++ b/src/Orchard.Web/Modules/Orchard.MetaData/Permissions.cs @@ -1,20 +1,10 @@ using System.Collections.Generic; -using System.Linq; using Orchard.Security.Permissions; namespace Orchard.MetaData { public class Permissions : IPermissionProvider { public static readonly Permission ManageMetaData = new Permission { Description = "Manage MetaData", Name = "ManageMetaData" };//q: Should edit_MetaData be ManageMetaData? - public static readonly Permission PublishOthersMetaDataPost = new Permission { Description = "Publish or unpublish MetaData post for others", Name = "PublishOthersMetaDataPost", ImpliedBy = new[] { ManageMetaData } }; - public static readonly Permission PublishMetaDataPost = new Permission { Description = "Publish or unpublish MetaData post", Name = "PublishMetaDataPost", ImpliedBy = new[] { PublishOthersMetaDataPost } }; - public static readonly Permission EditOthersMetaDataPost = new Permission { Description = "Edit any MetaData posts", Name = "EditOthersMetaDataPost", ImpliedBy = new[] { PublishOthersMetaDataPost } }; - public static readonly Permission EditMetaDataPost = new Permission { Description = "Edit own MetaData posts", Name = "EditMetaDataPost", ImpliedBy = new[] { EditOthersMetaDataPost, PublishMetaDataPost } }; - public static readonly Permission DeleteOthersMetaDataPost = new Permission { Description = "Delete MetaData post for others", Name = "DeleteOthersMetaDataPost", ImpliedBy = new[] { ManageMetaData } }; - public static readonly Permission DeleteMetaDataPost = new Permission { Description = "Delete MetaData post", Name = "DeleteMetaDataPost", ImpliedBy = new[] { DeleteOthersMetaDataPost } }; - - public static readonly Permission MetaListOthersMetaData = new Permission { ImpliedBy = new[] { EditOthersMetaDataPost, PublishOthersMetaDataPost, DeleteOthersMetaDataPost } }; - public static readonly Permission MetaListMetaData = new Permission { ImpliedBy = new[] { EditMetaDataPost, PublishMetaDataPost, DeleteMetaDataPost } }; public string ModuleName { get { @@ -25,12 +15,6 @@ namespace Orchard.MetaData { public IEnumerable GetPermissions() { return new Permission[] { ManageMetaData, - EditMetaDataPost, - EditOthersMetaDataPost, - PublishMetaDataPost, - PublishOthersMetaDataPost, - DeleteMetaDataPost, - DeleteOthersMetaDataPost, }; } @@ -40,22 +24,6 @@ namespace Orchard.MetaData { Name = "Administrator", Permissions = new[] {ManageMetaData} }, - new PermissionStereotype { - Name = "Editor", - Permissions = new[] {PublishOthersMetaDataPost,EditOthersMetaDataPost,DeleteOthersMetaDataPost} - }, - new PermissionStereotype { - Name = "Moderator", - //Permissions = new[] {} - }, - new PermissionStereotype { - Name = "Author", - Permissions = new[] {PublishMetaDataPost,EditMetaDataPost,DeleteMetaDataPost} - }, - new PermissionStereotype { - Name = "Contributor", - Permissions = new[] {EditMetaDataPost} - }, }; } diff --git a/src/Orchard.Web/Modules/Orchard.MetaData/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.MetaData/Properties/AssemblyInfo.cs index a7fe0e116..9ce2239ad 100644 --- a/src/Orchard.Web/Modules/Orchard.MetaData/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.MetaData/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/src/Orchard.Web/Modules/Orchard.MetaData/Views/MetaData/ContentTypeList.ascx b/src/Orchard.Web/Modules/Orchard.MetaData/Views/MetaData/ContentTypeList.ascx index 532150494..c0b78eead 100644 --- a/src/Orchard.Web/Modules/Orchard.MetaData/Views/MetaData/ContentTypeList.ascx +++ b/src/Orchard.Web/Modules/Orchard.MetaData/Views/MetaData/ContentTypeList.ascx @@ -15,13 +15,13 @@ <% foreach (var item in Model.ContentTypes) { %> <% - string contentTypeClass = ""; + var contentTypeClass = ""; if (Model.SelectedContentType!=null && Model.SelectedContentType.Name == item.Name) { - contentTypeClass = "SelectedContentPart"; - }else{ - contentTypeClass = "UnSelectedContentPart"; - } + contentTypeClass = "SelectedContentPart"; + }else{ + contentTypeClass = "UnSelectedContentPart"; + } %> diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs b/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs index a27a4eb42..77007d0fa 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs @@ -3,9 +3,6 @@ using System.Linq; using System.Web; using Orchard.Comments.Models; using Orchard.ContentManagement; -using Orchard.ContentManagement.MetaData.Models; -using Orchard.ContentManagement.MetaData.Records; -using Orchard.ContentManagement.Records; using Orchard.Core.Common.Models; using Orchard.Core.Navigation.Models; using Orchard.Core.Settings.Models; diff --git a/src/Orchard/ContentManagement/Drivers/ContentPartDriver.cs b/src/Orchard/ContentManagement/Drivers/ContentPartDriver.cs index 70ece4268..91b12f342 100644 --- a/src/Orchard/ContentManagement/Drivers/ContentPartDriver.cs +++ b/src/Orchard/ContentManagement/Drivers/ContentPartDriver.cs @@ -56,7 +56,7 @@ namespace Orchard.ContentManagement.Drivers { { var contentPartInfo = new List() { new ContentPartInfo() - {partName = typeof(TContent).Name,Factory = () => new TContent()} + {PartName = typeof(TContent).Name,Factory = () => new TContent()} }; return contentPartInfo; diff --git a/src/Orchard/ContentManagement/MetaData/ContentPartHandler.cs b/src/Orchard/ContentManagement/MetaData/ContentPartHandler.cs index 9ecb104f5..598ce88bd 100644 --- a/src/Orchard/ContentManagement/MetaData/ContentPartHandler.cs +++ b/src/Orchard/ContentManagement/MetaData/ContentPartHandler.cs @@ -25,10 +25,12 @@ namespace Orchard.ContentManagement.MetaData protected override void Activating(ActivatingContentContext context) { var contentTypeRecord = _contentTypeService.GetContentTypeRecord(context.ContentType) ?? new ContentTypeRecord(); + if (contentTypeRecord.ContentParts != null){ foreach (var contentTypePartRecord in contentTypeRecord.ContentParts){ - var record = contentTypePartRecord; - var contentPart = _contentPartInfos.Single(x => x.partName == record.PartName).Factory(); + //var record = contentTypePartRecord; + + var contentPart = _contentPartInfos.Single(x => x.PartName == contentTypePartRecord.PartName.PartName).Factory(); context.Builder.Weld(contentPart); } } diff --git a/src/Orchard/ContentManagement/MetaData/ContentPartInfo.cs b/src/Orchard/ContentManagement/MetaData/ContentPartInfo.cs index 8122efbd7..23a731cbf 100644 --- a/src/Orchard/ContentManagement/MetaData/ContentPartInfo.cs +++ b/src/Orchard/ContentManagement/MetaData/ContentPartInfo.cs @@ -4,7 +4,7 @@ namespace Orchard.ContentManagement.MetaData { public class ContentPartInfo { - public string partName; - public Func Factory; + public string PartName { get; set; } + public Func Factory { get; set; } } } diff --git a/src/Orchard/ContentManagement/MetaData/Models/ContentTypePart.cs b/src/Orchard/ContentManagement/MetaData/Models/ContentTypePart.cs deleted file mode 100644 index f4def626f..000000000 --- a/src/Orchard/ContentManagement/MetaData/Models/ContentTypePart.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Web.Mvc; -using Orchard.ContentManagement; -using Orchard.ContentManagement.MetaData.Records; - -namespace Orchard.ContentManagement.MetaData.Models -{ - public class ContentTypePart : ContentPart - { - - } -} diff --git a/src/Orchard/ContentManagement/MetaData/Records/ContentTypePartRecord.cs b/src/Orchard/ContentManagement/MetaData/Records/ContentTypePartRecord.cs index 93de671dc..e723d18e7 100644 --- a/src/Orchard/ContentManagement/MetaData/Records/ContentTypePartRecord.cs +++ b/src/Orchard/ContentManagement/MetaData/Records/ContentTypePartRecord.cs @@ -1,6 +1,6 @@ namespace Orchard.ContentManagement.MetaData.Records { public class ContentTypePartRecord { public virtual int Id { get; set; } - public virtual string PartName { 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 index b51574664..a4f1d022b 100644 --- a/src/Orchard/ContentManagement/MetaData/Services/ContentTypeService.cs +++ b/src/Orchard/ContentManagement/MetaData/Services/ContentTypeService.cs @@ -11,22 +11,34 @@ namespace Orchard.ContentManagement.MetaData.Services [UsedImplicitly] public class ContentTypeService : IContentTypeService { - private readonly IRepository _contentTypeRecord; - private readonly IRepository _contentTypePartNameRecord; - private readonly IRepository _contentTypePartRecord; + private readonly IRepository _contentTypeRepository; + private readonly IRepository _contentTypePartNameRepository; + private readonly IRepository _contentTypePartRepository; - public ContentTypeService(IRepository contentTypePartRecord, IRepository contentTypeRecord, IRepository contentTypePartNameRecord) + public ContentTypeService(IRepository contentTypePartRepository, IRepository contentTypeRepository, IRepository contentTypePartNameRepository) { - _contentTypeRecord = contentTypeRecord; - _contentTypePartNameRecord = contentTypePartNameRecord; - _contentTypePartRecord = contentTypePartRecord; + _contentTypeRepository = contentTypeRepository; + _contentTypePartNameRepository = contentTypePartNameRepository; + _contentTypePartRepository = contentTypePartRepository; + } + + public ContentTypePartNameRecord GetContentPartNameRecord(string name) { + return _contentTypePartNameRepository.Fetch(x => x.PartName == name).Single(); } public void MapContentTypeToContentPart(string contentType, string contentPart) { var contentTypeRecord = GetContentTypeRecord(contentType) ?? new ContentTypeRecord(); contentTypeRecord.Name = contentType; + var contentTypePartNameRecord = + _contentTypePartNameRepository.Fetch(x => x.PartName == contentPart).SingleOrDefault(); + if (contentTypePartNameRecord==null) { + contentTypePartNameRecord=new ContentTypePartNameRecord(){PartName = contentPart}; + _contentTypePartNameRepository.Update(contentTypePartNameRecord); + contentTypePartNameRecord = + _contentTypePartNameRepository.Fetch(x => x.PartName == contentPart).SingleOrDefault(); + } var contentTypePartRecord = new ContentTypePartRecord() { - PartName = contentPart + PartName = contentTypePartNameRecord }; if (contentTypeRecord.ContentParts==null) { contentTypeRecord.ContentParts = new List { contentTypePartRecord }; @@ -35,15 +47,17 @@ namespace Orchard.ContentManagement.MetaData.Services contentTypeRecord.ContentParts.Add(contentTypePartRecord); } - _contentTypeRecord.Update(contentTypeRecord); + _contentTypeRepository.Update(contentTypeRecord); } public void UnMapContentTypeToContentPart(string contentType, string contentPart) { var contentTypeRecord = GetContentTypeRecord(contentType) ?? new ContentTypeRecord(); - var contentTypePartRecord = contentTypeRecord.ContentParts.Single(x => x.PartName == contentPart); + var contentTypePartNameRecord = _contentTypePartNameRepository.Fetch(x => x.PartName == contentPart).Single(); + + var contentTypePartRecord = contentTypeRecord.ContentParts.SingleOrDefault(x => x.PartName == contentTypePartNameRecord); if (contentTypePartRecord != null) { - _contentTypePartRecord.Delete(contentTypePartRecord); + _contentTypePartRepository.Delete(contentTypePartRecord); contentTypeRecord.ContentParts.Remove(contentTypePartRecord); } } @@ -52,7 +66,7 @@ namespace Orchard.ContentManagement.MetaData.Services var contentTypeRecord = GetContentTypeRecord(contentType) ?? new ContentTypeRecord(); if (contentTypeRecord.ContentParts.Count==0) return false; - var contentTypePart = contentTypeRecord.ContentParts.Single(x => x.PartName == contentPart); + var contentTypePart = contentTypeRecord.ContentParts.Single(x => x.PartName.PartName == contentPart); return contentTypePart != null; } @@ -62,27 +76,19 @@ namespace Orchard.ContentManagement.MetaData.Services PartName = contentTypePartName }; - _contentTypePartNameRecord.Update(contentTypePartNameRecord); + _contentTypePartNameRepository.Update(contentTypePartNameRecord); } public ContentTypeRecord GetContentTypeRecord(string contentTypeName) { - var contentTypeCount = _contentTypeRecord.Table.Count(x => x.Name == contentTypeName); - if (contentTypeCount > 0) { - var contentTypeRecord = _contentTypeRecord.Table.Single(x => x.Name == contentTypeName); - return contentTypeRecord; - } - else { - return null; - } - + return _contentTypeRepository.Fetch(x => x.Name == contentTypeName).SingleOrDefault(); } public IEnumerable GetContentTypes() { - return _contentTypeRecord.Table.ToList(); + return _contentTypeRepository.Table.ToList(); } public IEnumerable GetContentTypePartNames() { - return _contentTypePartNameRecord.Table.ToList(); + return _contentTypePartNameRepository.Table.ToList(); } } diff --git a/src/Orchard/ContentManagement/MetaData/Services/IContentTypeService.cs b/src/Orchard/ContentManagement/MetaData/Services/IContentTypeService.cs index 6b71fd20d..2ab533896 100644 --- a/src/Orchard/ContentManagement/MetaData/Services/IContentTypeService.cs +++ b/src/Orchard/ContentManagement/MetaData/Services/IContentTypeService.cs @@ -12,5 +12,6 @@ namespace Orchard.ContentManagement.MetaData.Services bool ValidateContentTypeToContentPartMapping(string contentType, string contentPart); IEnumerable GetContentTypes(); IEnumerable GetContentTypePartNames(); + ContentTypePartNameRecord GetContentPartNameRecord(string name); } } diff --git a/src/Orchard/ContentManagement/Records/ContentPartRecord.cs b/src/Orchard/ContentManagement/Records/ContentPartRecord.cs index b51db5f85..df2c6f019 100644 --- a/src/Orchard/ContentManagement/Records/ContentPartRecord.cs +++ b/src/Orchard/ContentManagement/Records/ContentPartRecord.cs @@ -1,6 +1,9 @@ +using Orchard.Data.Conventions; + namespace Orchard.ContentManagement.Records { public abstract class ContentPartRecord { public virtual int Id { get; set; } + [CascadeAllDeleteOrphan] public virtual ContentItemRecord ContentItemRecord { get; set; } } } diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index 1b3d63aa9..17d230cb7 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -185,7 +185,6 @@ - @@ -465,6 +464,9 @@ + + +