Relocating the files to match namespaces. Using new ItemDriver technology within blogs module.

--HG--
rename : src/Orchard/Models/Aspects/ICommonAspect.cs => src/Orchard/ContentManagement/Aspects/ICommonAspect.cs
rename : src/Orchard/Models/ContentExtensions.cs => src/Orchard/ContentManagement/ContentExtensions.cs
rename : src/Orchard/Models/ContentItem.cs => src/Orchard/ContentManagement/ContentItem.cs
rename : src/Orchard/Models/ContentItemMetadata.cs => src/Orchard/ContentManagement/ContentItemMetadata.cs
rename : src/Orchard/Models/ContentModule.cs => src/Orchard/ContentManagement/ContentModule.cs
rename : src/Orchard/Models/ContentPart.cs => src/Orchard/ContentManagement/ContentPart.cs
rename : src/Orchard/Models/ContentType.cs => src/Orchard/ContentManagement/ContentType.cs
rename : src/Orchard/Models/DefaultContentManager.cs => src/Orchard/ContentManagement/DefaultContentManager.cs
rename : src/Orchard/Models/DefaultContentQuery.cs => src/Orchard/ContentManagement/DefaultContentQuery.cs
rename : src/Orchard/Models/Diagram.cd => src/Orchard/ContentManagement/Diagram.cd
rename : src/Orchard/Models/Driver/ActivatedContentContext.cs => src/Orchard/ContentManagement/Driver/ActivatedContentContext.cs
rename : src/Orchard/Models/Driver/ActivatingContentContext.cs => src/Orchard/ContentManagement/Driver/ActivatingContentContext.cs
rename : src/Orchard/Models/Driver/ActivatingFilter.cs => src/Orchard/ContentManagement/Driver/ActivatingFilter.cs
rename : src/Orchard/Models/Driver/BuildDisplayModelContext.cs => src/Orchard/ContentManagement/Driver/BuildDisplayModelContext.cs
rename : src/Orchard/Models/Driver/BuildEditorModelContext.cs => src/Orchard/ContentManagement/Driver/BuildEditorModelContext.cs
rename : src/Orchard/Models/Driver/ContentHandler.cs => src/Orchard/ContentManagement/Driver/ContentHandler.cs
rename : src/Orchard/Models/Driver/ContentItemBuilder.cs => src/Orchard/ContentManagement/Driver/ContentItemBuilder.cs
rename : src/Orchard/Models/Driver/ContentItemTemplates.cs => src/Orchard/ContentManagement/Driver/ContentItemTemplates.cs
rename : src/Orchard/Models/Driver/CreateContentContext.cs => src/Orchard/ContentManagement/Driver/CreateContentContext.cs
rename : src/Orchard/Models/Driver/GetItemMetadataContext.cs => src/Orchard/ContentManagement/Driver/GetItemMetadataContext.cs
rename : src/Orchard/Models/Driver/IContentActivatingFilter.cs => src/Orchard/ContentManagement/Driver/IContentActivatingFilter.cs
rename : src/Orchard/Models/Driver/IContentFilter.cs => src/Orchard/ContentManagement/Driver/IContentFilter.cs
rename : src/Orchard/Models/Driver/IContentHandler.cs => src/Orchard/ContentManagement/Driver/IContentHandler.cs
rename : src/Orchard/Models/Driver/IContentStorageFilter.cs => src/Orchard/ContentManagement/Driver/IContentStorageFilter.cs
rename : src/Orchard/Models/Driver/IContentTemplateFilter.cs => src/Orchard/ContentManagement/Driver/IContentTemplateFilter.cs
rename : src/Orchard/Models/Driver/IUpdateModel.cs => src/Orchard/ContentManagement/Driver/IUpdateModel.cs
rename : src/Orchard/Models/Driver/LoadContentContext.cs => src/Orchard/ContentManagement/Driver/LoadContentContext.cs
rename : src/Orchard/Models/Driver/StorageFilter.cs => src/Orchard/ContentManagement/Driver/StorageFilter.cs
rename : src/Orchard/Models/Driver/StorageFilterBase.cs => src/Orchard/ContentManagement/Driver/StorageFilterBase.cs
rename : src/Orchard/Models/Driver/TemplateFilterBase.cs => src/Orchard/ContentManagement/Driver/TemplateFilterBase.cs
rename : src/Orchard/Models/Driver/TemplateFilterForRecord.cs => src/Orchard/ContentManagement/Driver/TemplateFilterForRecord.cs
rename : src/Orchard/Models/Driver/UpdateEditorModelContext.cs => src/Orchard/ContentManagement/Driver/UpdateEditorModelContext.cs
rename : src/Orchard/Models/Driver/ActivatedContentContext.cs => src/Orchard/ContentManagement/Handlers/ActivatedContentContext.cs
rename : src/Orchard/Models/Driver/ActivatingContentContext.cs => src/Orchard/ContentManagement/Handlers/ActivatingContentContext.cs
rename : src/Orchard/Models/Driver/ActivatingFilter.cs => src/Orchard/ContentManagement/Handlers/ActivatingFilter.cs
rename : src/Orchard/Models/Driver/BuildDisplayModelContext.cs => src/Orchard/ContentManagement/Handlers/BuildDisplayModelContext.cs
rename : src/Orchard/Models/Driver/BuildEditorModelContext.cs => src/Orchard/ContentManagement/Handlers/BuildEditorModelContext.cs
rename : src/Orchard/Models/Driver/ContentHandler.cs => src/Orchard/ContentManagement/Handlers/ContentHandler.cs
rename : src/Orchard/Models/Driver/ContentItemBuilder.cs => src/Orchard/ContentManagement/Handlers/ContentItemBuilder.cs
rename : src/Orchard/Models/Driver/ContentItemTemplates.cs => src/Orchard/ContentManagement/Handlers/ContentItemTemplates.cs
rename : src/Orchard/Models/Driver/CreateContentContext.cs => src/Orchard/ContentManagement/Handlers/CreateContentContext.cs
rename : src/Orchard/Models/Driver/GetItemMetadataContext.cs => src/Orchard/ContentManagement/Handlers/GetItemMetadataContext.cs
rename : src/Orchard/Models/Driver/IContentActivatingFilter.cs => src/Orchard/ContentManagement/Handlers/IContentActivatingFilter.cs
rename : src/Orchard/Models/Driver/IContentFilter.cs => src/Orchard/ContentManagement/Handlers/IContentFilter.cs
rename : src/Orchard/Models/Driver/IContentHandler.cs => src/Orchard/ContentManagement/Handlers/IContentHandler.cs
rename : src/Orchard/Models/Driver/IContentStorageFilter.cs => src/Orchard/ContentManagement/Handlers/IContentStorageFilter.cs
rename : src/Orchard/Models/Driver/IContentTemplateFilter.cs => src/Orchard/ContentManagement/Handlers/IContentTemplateFilter.cs
rename : src/Orchard/Models/Driver/IUpdateModel.cs => src/Orchard/ContentManagement/Handlers/IUpdateModel.cs
rename : src/Orchard/Models/Driver/LoadContentContext.cs => src/Orchard/ContentManagement/Handlers/LoadContentContext.cs
rename : src/Orchard/Models/Driver/StorageFilter.cs => src/Orchard/ContentManagement/Handlers/StorageFilter.cs
rename : src/Orchard/Models/Driver/StorageFilterBase.cs => src/Orchard/ContentManagement/Handlers/StorageFilterBase.cs
rename : src/Orchard/Models/Driver/TemplateFilterBase.cs => src/Orchard/ContentManagement/Handlers/TemplateFilterBase.cs
rename : src/Orchard/Models/Driver/TemplateFilterForRecord.cs => src/Orchard/ContentManagement/Handlers/TemplateFilterForRecord.cs
rename : src/Orchard/Models/Driver/UpdateEditorModelContext.cs => src/Orchard/ContentManagement/Handlers/UpdateEditorModelContext.cs
rename : src/Orchard/Models/IContent.cs => src/Orchard/ContentManagement/IContent.cs
rename : src/Orchard/Models/IContentDisplayInfo.cs => src/Orchard/ContentManagement/IContentDisplayInfo.cs
rename : src/Orchard/Models/IContentManager.cs => src/Orchard/ContentManagement/IContentManager.cs
rename : src/Orchard/Models/IContentQuery.cs => src/Orchard/ContentManagement/IContentQuery.cs
rename : src/Orchard/Models/PartDriver.cs => src/Orchard/ContentManagement/PartDriver.cs
rename : src/Orchard/Models/Records/ContentItemRecord.cs => src/Orchard/ContentManagement/Records/ContentItemRecord.cs
rename : src/Orchard/Models/Records/ContentItemRecordAlteration.cs => src/Orchard/ContentManagement/Records/ContentItemRecordAlteration.cs
rename : src/Orchard/Models/Records/ContentPartRecord.cs => src/Orchard/ContentManagement/Records/ContentPartRecord.cs
rename : src/Orchard/Models/Records/ContentPartRecordAlteration.cs => src/Orchard/ContentManagement/Records/ContentPartRecordAlteration.cs
rename : src/Orchard/Models/Records/ContentTypeRecord.cs => src/Orchard/ContentManagement/Records/ContentTypeRecord.cs
rename : src/Orchard/Models/ViewModels/ItemDisplayModel.cs => src/Orchard/ContentManagement/ViewModels/ItemDisplayModel.cs
rename : src/Orchard/Models/ViewModels/ItemEditorModel.cs => src/Orchard/ContentManagement/ViewModels/ItemEditorModel.cs
rename : src/Orchard/Models/ViewModels/TemplateViewModel.cs => src/Orchard/ContentManagement/ViewModels/TemplateViewModel.cs
extra : convert_revision : svn%3A5ff7c347-ad56-4c35-b696-ccb81de16e03/trunk%4044417
This commit is contained in:
loudej
2009-12-21 22:43:10 +00:00
parent c08d3813da
commit 75984135a9
84 changed files with 2871 additions and 113 deletions

View File

@@ -9,6 +9,7 @@ using Autofac.Modules;
using Moq;
using NUnit.Framework;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.ViewModels;

View File

@@ -0,0 +1,72 @@
using System.Collections.Generic;
using System.Linq;
using System.Web.Routing;
using JetBrains.Annotations;
using Orchard.Blogs.Models;
using Orchard.Blogs.Services;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement.ViewModels;
namespace Orchard.Blogs.Controllers {
[UsedImplicitly]
public class BlogDriver : ItemDriver<Blog> {
private readonly IContentManager _contentManager;
private readonly IBlogPostService _blogPostService;
public BlogDriver(IContentManager contentManager, IBlogPostService blogPostService) {
_contentManager = contentManager;
_blogPostService = blogPostService;
}
protected override string Prefix { get { return ""; } }
protected override string GetDisplayText(Blog item) {
return item.Name;
}
protected override RouteValueDictionary GetDisplayRouteValues(Blog blog) {
return new RouteValueDictionary {
{"Area", "Orchard.Blogs"},
{"Controller", "Blog"},
{"Action", "Item"},
{"blogSlug", blog.Slug}
};
}
protected override RouteValueDictionary GetEditorRouteValues(Blog blog) {
return new RouteValueDictionary {
{"Area", "Orchard.Blogs"},
{"Controller", "Blog"},
{"Action", "Edit"},
{"blogSlug", blog.Slug}
};
}
protected override DriverResult Display(Blog blog, string displayType) {
if (!displayType.StartsWith("Detail"))
return null;
var posts = _blogPostService.Get(blog);
IEnumerable<ItemDisplayModel<BlogPost>> model;
if (displayType.StartsWith("DetailAdmin")) {
model = posts.Select(bp => _contentManager.BuildDisplayModel(bp, "SummaryAdmin"));
}
else {
model = posts.Select(bp => _contentManager.BuildDisplayModel(bp, "Summary"));
}
return PartialView(model, "Parts/Blogs.BlogPost.List", "").Location("body");
}
protected override DriverResult Editor(Blog blog) {
return PartialView(blog, "Parts/Blogs.Blog.Fields").Location("primary", "1");
}
protected override DriverResult Editor(Blog blog, IUpdateModel updater) {
updater.TryUpdateModel(blog, Prefix, null, null);
return PartialView(blog, "Parts/Blogs.Blog.Fields").Location("primary", "1");
}
}
}

View File

@@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing;
using JetBrains.Annotations;
using Orchard.Blogs.Models;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
namespace Orchard.Blogs.Controllers {
[UsedImplicitly]
public class BlogPostDriver : ItemDriver<BlogPost> {
protected override string Prefix { get { return ""; } }
protected override string GetDisplayText(BlogPost post) {
return post.Title;
}
protected override RouteValueDictionary GetDisplayRouteValues(BlogPost post) {
return new RouteValueDictionary {
{"Area", "Orchard.Blogs"},
{"Controller", "BlogPost"},
{"Action", "Item"},
{"blogSlug", post.Blog.Slug},
{"postSlug", post.Slug},
};
}
protected override RouteValueDictionary GetEditorRouteValues(BlogPost post) {
return new RouteValueDictionary {
{"Area", "Orchard.Blogs"},
{"Controller", "BlogPost"},
{"Action", "Edit"},
{"blogSlug", post.Blog.Slug},
{"postSlug", post.Slug},
};
}
protected override DriverResult Editor(BlogPost post) {
return Combined(
PartialView(post, "Parts/Blogs.BlogPost.Fields").Location("primary", "1"),
PartialView(post, "Parts/Blogs.BlogPost.Publish").Location("secondary", "1")
);
}
protected override DriverResult Editor(BlogPost post, IUpdateModel updater) {
updater.TryUpdateModel(post, Prefix, null, null);
return Editor(post);
}
}
}

View File

@@ -3,7 +3,6 @@ using Orchard.Core.Common.Models;
using Orchard.Data;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.ViewModels;
namespace Orchard.Blogs.Models {
public class BlogHandler : ContentHandler {
@@ -17,15 +16,6 @@ namespace Orchard.Blogs.Models {
Filters.Add(new ActivatingFilter<RoutableAspect>("blog"));
Filters.Add(new StorageFilter<BlogRecord>(repository));
Filters.Add(new ContentItemTemplates<Blog>("Items/Blogs.Blog", "Summary DetailAdmin SummaryAdmin"));
OnGetEditorViewModel<Blog>((context, blog) =>
context.AddEditor(new TemplateViewModel(blog) { TemplateName = "Parts/Blogs.Blog.Fields", ZoneName = "primary", Position = "1" })
);
OnUpdateEditorViewModel<Blog>((context, blog) => {
context.AddEditor(new TemplateViewModel(blog) { TemplateName = "Parts/Blogs.Blog.Fields", ZoneName = "primary", Position = "1" });
context.Updater.TryUpdateModel(blog, "", null, null);
});
}
}
}
}

View File

@@ -27,63 +27,6 @@ namespace Orchard.Blogs.Models {
Filters.Add(new ContentItemTemplates<BlogPost>("Items/Blogs.BlogPost", "Summary SummaryAdmin"));
OnCreated<BlogPost>((context, bp) => bp.Blog.PostCount++);
OnGetItemMetadata<BlogPost>((context, bp) => {
context.Metadata.DisplayText = bp.Title;
context.Metadata.DisplayRouteValues =
new RouteValueDictionary(
new {
area = "Orchard.Blogs",
controller = "BlogPost",
action = "Item",
blogSlug = bp.Blog.Slug,
postSlug = bp.Slug
});
context.Metadata.EditorRouteValues =
new RouteValueDictionary(
new {
area = "Orchard.Blogs",
controller = "BlogPost",
action = "Edit",
blogSlug = bp.Blog.Slug,
postSlug = bp.Slug
});
});
OnGetDisplayViewModel<Blog>((context, blog) => {
if (!context.DisplayType.StartsWith("Detail"))
return;
var posts = blogPostService.Get(blog);
switch(context.DisplayType) {
case "Detail":
context.AddDisplay(
new TemplateViewModel(posts.Select(bp => contentManager.BuildDisplayModel(bp, "Summary"))) {
TemplateName = "Parts/Blogs.BlogPost.List",
ZoneName = "body"
});
break;
case "DetailAdmin":
context.AddDisplay(
new TemplateViewModel(posts.Select(bp => contentManager.BuildDisplayModel(bp, "SummaryAdmin"))) {
TemplateName = "Parts/Blogs.BlogPost.List",
ZoneName = "body"
});
break;
}
});
OnGetEditorViewModel<BlogPost>((context, blogPost) => {
context.AddEditor(new TemplateViewModel(blogPost) { TemplateName = "Parts/Blogs.BlogPost.Fields", ZoneName = "primary", Position = "1" });
context.AddEditor(new TemplateViewModel(blogPost) { TemplateName = "Parts/Blogs.BlogPost.Publish", ZoneName = "secondary", Position = "1" });
});
OnUpdateEditorViewModel<BlogPost>((context, blogPost) => {
context.AddEditor(new TemplateViewModel(blogPost) { TemplateName = "Parts/Blogs.BlogPost.Fields", ZoneName = "primary", Position = "1" });
context.AddEditor(new TemplateViewModel(blogPost) { TemplateName = "Parts/Blogs.BlogPost.Publish", ZoneName = "secondary", Position = "1" });
context.Updater.TryUpdateModel(blogPost, "", null, null);
});
}
}

View File

@@ -75,7 +75,9 @@
<ItemGroup>
<Compile Include="AdminMenu.cs" />
<Compile Include="Controllers\BlogAdminController.cs" />
<Compile Include="Controllers\BlogDriver.cs" />
<Compile Include="Controllers\BlogPostController.cs" />
<Compile Include="Controllers\BlogPostDriver.cs" />
<Compile Include="Extensions\HtmlHelperExtensions.cs" />
<Compile Include="Extensions\UriExtensions.cs" />
<Compile Include="Extensions\UrlHelperExtensions.cs" />

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Orchard.ContentManagement.Drivers;
using Orchard.Data;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Orchard.Security;
namespace Orchard.ContentManagement.Aspects {
public interface ICommonAspect : IContent {
DateTime? CreatedUtc { get; set; }
DateTime? ModifiedUtc { get; set; }
IUser Owner { get; set; }
IContent Container { get; set; }
}
}

View File

@@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.Records;
using Orchard.ContentManagement.ViewModels;
namespace Orchard.ContentManagement {
public static class ContentExtensions {
/* Item creation and accessing extension methods */
public static T New<T>(this IContentManager manager, string contentType) where T : class, IContent {
var contentItem = manager.New(contentType);
if (contentItem == null)
return null;
var part = contentItem.Get<T>();
if (part == null)
throw new InvalidCastException();
return part;
}
public static T Create<T>(this IContentManager manager, string contentType) where T : class, IContent {
return manager.Create<T>(contentType, init => { });
}
public static T Create<T>(this IContentManager manager, string contentType, Action<T> initialize) where T : class, IContent {
var content = manager.New<T>(contentType);
if (content == null)
return null;
initialize(content);
manager.Create(content.ContentItem);
return content;
}
public static T Get<T>(this IContentManager manager, int id) where T : class, IContent {
var contentItem = manager.Get(id);
return contentItem == null ? null : contentItem.Get<T>();
}
/* Display and editor convenience extension methods */
public static ItemDisplayModel<T> BuildDisplayModel<T>(this IContentManager manager, int id, string displayType) where T : class, IContent {
return manager.BuildDisplayModel(manager.Get<T>(id), displayType);
}
public static ItemEditorModel<T> BuildEditorModel<T>(this IContentManager manager, int id) where T : class, IContent {
return manager.BuildEditorModel(manager.Get<T>(id));
}
public static ItemEditorModel<T> UpdateEditorModel<T>(this IContentManager manager, int id, IUpdateModel updater) where T : class, IContent {
return manager.UpdateEditorModel(manager.Get<T>(id), updater);
}
/* Query related extension methods */
public static IContentQuery<TPart> Query<TPart>(this IContentManager manager)
where TPart : ContentPart {
return manager.Query().ForPart<TPart>();
}
public static IContentQuery<TPart, TRecord> Query<TPart, TRecord>(this IContentManager manager)
where TPart : ContentPart<TRecord>
where TRecord : ContentPartRecord {
return manager.Query().ForPart<TPart>().Join<TRecord>();
}
public static IContentQuery<ContentItem> Query(this IContentManager manager, params string[] contentTypeNames) {
return manager.Query().ForType(contentTypeNames);
}
public static IContentQuery<TPart> Query<TPart>(this IContentManager manager, params string[] contentTypeNames) where TPart : ContentPart {
return manager.Query().ForPart<TPart>().ForType(contentTypeNames);
}
public static IContentQuery<TPart,TRecord> Query<TPart,TRecord>(this IContentManager manager, params string[] contentTypeNames) where TPart : ContentPart<TRecord> where TRecord : ContentPartRecord {
return manager.Query().ForPart<TPart>().ForType(contentTypeNames).Join<TRecord>();
}
public static IEnumerable<T> List<T>(this IContentManager manager, params string[] contentTypeNames) where T : ContentPart {
return manager.Query<T>(contentTypeNames).List();
}
public static IEnumerable<T> List<T>(this IContentQuery query) where T : IContent {
return query.ForPart<T>().List();
}
public static IEnumerable<T> Slice<T>(this IContentQuery<T> query, int count) where T : IContent {
return query.Slice(0, count);
}
/* Aggregate item/part type casting extension methods */
public static bool Is<T>(this IContent content) {
return content == null ? false : content.ContentItem.Has(typeof(T));
}
public static T As<T>(this IContent content) where T : IContent {
return content == null ? default(T) : (T)content.ContentItem.Get(typeof(T));
}
public static bool Has<T>(this IContent content) {
return content == null ? false : content.ContentItem.Has(typeof(T));
}
public static T Get<T>(this IContent content) where T : IContent {
return content == null ? default(T) : (T)content.ContentItem.Get(typeof(T));
}
public static IEnumerable<T> AsPart<T>(this IEnumerable<ContentItem> items) where T : IContent {
return items == null ? null : items.Where(item => item.Is<T>()).Select(item => item.As<T>());
}
}
}

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard.ContentManagement.Records;
namespace Orchard.ContentManagement {
public class ContentItem : IContent {
public ContentItem() {
_parts = new List<ContentPart>();
}
private readonly IList<ContentPart> _parts;
ContentItem IContent.ContentItem { get { return this; } }
public int Id { get; set; }
public string ContentType { get; set; }
public ContentItemRecord Record { get; set; }
public IEnumerable<ContentPart> Parts { get { return _parts; } }
public IContentManager ContentManager { get; set; }
public bool Has(Type partType) {
return partType==typeof(ContentItem) || _parts.Any(part => partType.IsAssignableFrom(part.GetType()));
}
public IContent Get(Type partType) {
if (partType == typeof(ContentItem))
return this;
return _parts.FirstOrDefault(part => partType.IsAssignableFrom(part.GetType()));
}
public void Weld(ContentPart part) {
part.ContentItem = this;
_parts.Add(part);
}
}
}

View File

@@ -0,0 +1,13 @@
using System.Collections.Generic;
using System.Web.Routing;
namespace Orchard.ContentManagement {
public class ContentItemMetadata {
public string DisplayText { get; set; }
public RouteValueDictionary DisplayRouteValues { get; set; }
public RouteValueDictionary EditorRouteValues { get; set; }
public IEnumerable<string> DisplayGroups { get; set; }
public IEnumerable<string> EditorGroups { get; set; }
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autofac.Builder;
namespace Orchard.ContentManagement {
public class ContentModule : Module {
protected override void Load(ContainerBuilder builder) {
builder.Register<DefaultContentQuery>().As<IContentQuery>().FactoryScoped();
}
}
}

View File

@@ -0,0 +1,10 @@
namespace Orchard.ContentManagement {
public abstract class ContentPart : IContent {
public virtual ContentItem ContentItem { get; set; }
}
public class ContentPart<TRecord> : ContentPart {
public TRecord Record { get; set; }
}
}

View File

@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Orchard.ContentManagement {
public class ContentType {
public string Name { get; set; }
public string DisplayName { get; set; }
}
}

View File

@@ -0,0 +1,191 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Autofac;
using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.Records;
using Orchard.ContentManagement.ViewModels;
using Orchard.Data;
using Orchard.UI.Navigation;
namespace Orchard.ContentManagement {
public class DefaultContentManager : IContentManager {
private readonly IContext _context;
private readonly IRepository<ContentItemRecord> _contentItemRepository;
private readonly IRepository<ContentTypeRecord> _contentTypeRepository;
public DefaultContentManager(
IContext context,
IRepository<ContentItemRecord> contentItemRepository,
IRepository<ContentTypeRecord> contentTypeRepository) {
_context = context;
_contentItemRepository = contentItemRepository;
_contentTypeRepository = contentTypeRepository;
}
private IEnumerable<IContentHandler> _handlers;
public IEnumerable<IContentHandler> Handlers {
get {
if (_handlers == null)
_handlers = _context.Resolve<IEnumerable<IContentHandler>>();
return _handlers;
}
}
public IEnumerable<ContentType> GetContentTypes() {
return Handlers.Aggregate(
Enumerable.Empty<ContentType>(),
(types, handler) => types.Concat(handler.GetContentTypes()));
}
public virtual ContentItem New(string contentType) {
// create a new kernel for the model instance
var context = new ActivatingContentContext {
ContentType = contentType,
Builder = new ContentItemBuilder(contentType)
};
// invoke handlers to weld aspects onto kernel
foreach (var handler in Handlers) {
handler.Activating(context);
}
var context2 = new ActivatedContentContext {
ContentType = contentType,
ContentItem = context.Builder.Build()
};
// back-reference for convenience (e.g. getting metadata when in a view)
context2.ContentItem.ContentManager = this;
foreach (var handler in Handlers) {
handler.Activated(context2);
}
// composite result is returned
return context2.ContentItem;
}
public virtual ContentItem Get(int id) {
// obtain root record to determine the model type
var record = _contentItemRepository.Get(id);
// no record of that id means content item doesn't exist
if (record == null)
return null;
// allocate instance and set record property
var contentItem = New(record.ContentType.Name);
contentItem.Id = record.Id;
contentItem.Record = record;
// create a context with a new instance to load
var context = new LoadContentContext {
Id = contentItem.Id,
ContentType = contentItem.ContentType,
ContentItemRecord = record,
ContentItem = contentItem,
};
// invoke handlers to acquire state, or at least establish lazy loading callbacks
foreach (var handler in Handlers) {
handler.Loading(context);
}
foreach (var handler in Handlers) {
handler.Loaded(context);
}
return context.ContentItem;
}
public void Create(ContentItem contentItem) {
// produce root record to determine the model id
var modelRecord = new ContentItemRecord { ContentType = AcquireContentTypeRecord(contentItem.ContentType) };
_contentItemRepository.Create(modelRecord);
contentItem.Record = modelRecord;
// build a context with the initialized instance to create
var context = new CreateContentContext {
Id = modelRecord.Id,
ContentType = modelRecord.ContentType.Name,
ContentItemRecord = modelRecord,
ContentItem = contentItem
};
// set the id
context.ContentItem.Id = context.Id;
// invoke handlers to add information to persistent stores
foreach (var handler in Handlers) {
handler.Creating(context);
}
foreach (var handler in Handlers) {
handler.Created(context);
}
}
public ContentItemMetadata GetItemMetadata(IContent content) {
var context = new GetItemMetadataContext {
ContentItem = content.ContentItem,
Metadata = new ContentItemMetadata()
};
foreach (var handler in Handlers) {
handler.GetItemMetadata(context);
}
return context.Metadata;
}
public ItemDisplayModel<TContentPart> BuildDisplayModel<TContentPart>(TContentPart content, string displayType) where TContentPart : IContent {
var itemView = new ItemDisplayModel<TContentPart> {Item = content, Displays = Enumerable.Empty<TemplateViewModel>()};
var context = new BuildDisplayModelContext(itemView, displayType);
foreach (var handler in Handlers) {
handler.BuildDisplayModel(context);
}
context.DisplayModel.Displays = OrderTemplates(context.DisplayModel.Displays);
return itemView;
}
public ItemEditorModel<TContentPart> BuildEditorModel<TContentPart>(TContentPart content) where TContentPart : IContent {
var itemView = new ItemEditorModel<TContentPart> { Item = content, Editors = Enumerable.Empty<TemplateViewModel>() };
var context = new BuildEditorModelContext(itemView);
foreach (var handler in Handlers) {
handler.BuildEditorModel(context);
}
context.EditorModel.Editors = OrderTemplates(context.EditorModel.Editors);
return itemView;
}
public ItemEditorModel<TContentPart> UpdateEditorModel<TContentPart>(TContentPart content, IUpdateModel updater) where TContentPart : IContent {
var itemView = new ItemEditorModel<TContentPart> { Item = content, Editors = Enumerable.Empty<TemplateViewModel>() };
var context = new UpdateEditorModelContext(itemView, updater);
foreach (var handler in Handlers) {
handler.UpdateEditorModel(context);
}
context.EditorModel.Editors = OrderTemplates(context.EditorModel.Editors);
return itemView;
}
private static IEnumerable<TemplateViewModel> OrderTemplates(IEnumerable<TemplateViewModel> templates) {
var comparer = new PositionComparer();
//TODO: rethink this comparison because it adds a requirement on naming zones.
return templates.OrderBy(x => (x.ZoneName ?? "*") + "." + (x.Position ?? "5"), comparer);
}
public IContentQuery<ContentItem> Query() {
var query = _context.Resolve<IContentQuery>(TypedParameter.From<IContentManager>(this));
return query.ForPart<ContentItem>();
}
private ContentTypeRecord AcquireContentTypeRecord(string contentType) {
var contentTypeRecord = _contentTypeRepository.Get(x => x.Name == contentType);
if (contentTypeRecord == null) {
//TEMP: this is not safe... ContentItem types could be created concurrently?
contentTypeRecord = new ContentTypeRecord { Name = contentType };
_contentTypeRepository.Create(contentTypeRecord);
}
return contentTypeRecord;
}
}
}

View File

@@ -0,0 +1,209 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using NHibernate;
using NHibernate.Criterion;
using NHibernate.Impl;
using NHibernate.Linq;
using Orchard.ContentManagement.Records;
using Orchard.Data;
namespace Orchard.ContentManagement {
public class DefaultContentQuery : IContentQuery {
private readonly ISessionLocator _sessionLocator;
private ISession _session;
private ICriteria _itemCriteria;
public DefaultContentQuery(IContentManager contentManager, ISessionLocator sessionLocator) {
_sessionLocator = sessionLocator;
ContentManager = contentManager;
}
public IContentManager ContentManager { get; private set; }
ISession BindSession() {
if (_session == null)
_session = _sessionLocator.For(typeof(ContentItemRecord));
return _session;
}
ICriteria BindItemCriteria() {
if (_itemCriteria == null) {
_itemCriteria = BindSession().CreateCriteria<ContentItemRecord>();
}
return _itemCriteria;
}
ICriteria BindCriteriaByPath(string path) {
var itemCriteria = BindItemCriteria();
// special if the content item is ever used as where or order
if (path == typeof(ContentItemRecord).Name)
return itemCriteria;
return itemCriteria.GetCriteriaByPath(path) ?? itemCriteria.CreateCriteria(path);
}
private void ForType(params string[] contentTypeNames) {
BindCriteriaByPath("ContentType").Add(Restrictions.InG("Name", contentTypeNames));
return;
}
private void Where<TRecord>() {
// this simply demands an inner join
BindCriteriaByPath(typeof(TRecord).Name);
return;
}
private void Where<TRecord>(Expression<Func<TRecord, bool>> predicate) {
// build a linq to nhibernate expression
var options = new QueryOptions();
var queryProvider = new NHibernateQueryProvider(BindSession(), options);
var queryable = new Query<TRecord>(queryProvider, options).Where(predicate);
// translate it into the nhibernate ICriteria implementation
var criteria = (CriteriaImpl)queryProvider.TranslateExpression(queryable.Expression);
// attach the criterion from the predicate to this query's criteria for the record
var recordCriteria = BindCriteriaByPath(typeof(TRecord).Name);
foreach (var expressionEntry in criteria.IterateExpressionEntries()) {
recordCriteria.Add(expressionEntry.Criterion);
}
return;
}
private void OrderBy<TRecord, TKey>(Expression<Func<TRecord, TKey>> keySelector) {
// build a linq to nhibernate expression
var options = new QueryOptions();
var queryProvider = new NHibernateQueryProvider(BindSession(), options);
var queryable = new Query<TRecord>(queryProvider, options).OrderBy(keySelector);
// translate it into the nhibernate ordering
var criteria = (CriteriaImpl)queryProvider.TranslateExpression(queryable.Expression);
// attaching orderings to the query's criteria
var recordCriteria = BindCriteriaByPath(typeof(TRecord).Name);
foreach (var ordering in criteria.IterateOrderings()) {
recordCriteria.AddOrder(ordering.Order);
}
return;
}
private void OrderByDescending<TRecord, TKey>(Expression<Func<TRecord, TKey>> keySelector) {
// build a linq to nhibernate expression
var options = new QueryOptions();
var queryProvider = new NHibernateQueryProvider(BindSession(), options);
var queryable = new Query<TRecord>(queryProvider, options).OrderByDescending(keySelector);
// translate it into the nhibernate ICriteria implementation
var criteria = (CriteriaImpl)queryProvider.TranslateExpression(queryable.Expression);
// attaching orderings to the query's criteria
var recordCriteria = BindCriteriaByPath(typeof(TRecord).Name);
foreach (var ordering in criteria.IterateOrderings()) {
recordCriteria.AddOrder(ordering.Order);
}
return;
}
private IEnumerable<ContentItem> List() {
return BindItemCriteria()
.List<ContentItemRecord>()
.Select(x => ContentManager.Get(x.Id));
}
private IEnumerable<ContentItem> Slice(int skip, int count) {
var criteria = BindItemCriteria();
if (skip != 0)
criteria = criteria.SetFirstResult(skip);
if (count != 0)
criteria = criteria.SetMaxResults(count);
return criteria
.List<ContentItemRecord>()
.Select(x => ContentManager.Get(x.Id));
}
IContentQuery<TPart> IContentQuery.ForPart<TPart>() {
return new ContentQuery<TPart>(this);
}
class ContentQuery<T> : IContentQuery<T> where T : IContent {
protected readonly DefaultContentQuery _query;
public ContentQuery(DefaultContentQuery query) {
_query = query;
}
public IContentManager ContentManager {
get { return _query.ContentManager; }
}
public IContentQuery<TPart> ForPart<TPart>() where TPart : IContent {
return new ContentQuery<TPart>(_query);
}
public IContentQuery<T> ForType(params string[] contentTypes) {
_query.ForType(contentTypes);
return this;
}
public IEnumerable<T> List() {
return _query.List().AsPart<T>();
}
public IEnumerable<T> Slice(int skip, int count) {
return _query.Slice(skip, count).AsPart<T>();
}
public IContentQuery<T, TRecord> Join<TRecord>() where TRecord : ContentPartRecord {
_query.Where<TRecord>();
return new ContentQuery<T, TRecord>(_query);
}
public IContentQuery<T, TRecord> Where<TRecord>(Expression<Func<TRecord, bool>> predicate) where TRecord : ContentPartRecord {
_query.Where(predicate);
return new ContentQuery<T, TRecord>(_query);
}
public IContentQuery<T, TRecord> OrderBy<TRecord, TKey>(Expression<Func<TRecord, TKey>> keySelector) where TRecord : ContentPartRecord {
_query.OrderBy(keySelector);
return new ContentQuery<T, TRecord>(_query);
}
public IContentQuery<T, TRecord> OrderByDescending<TRecord, TKey>(Expression<Func<TRecord, TKey>> keySelector) where TRecord : ContentPartRecord {
_query.OrderByDescending(keySelector);
return new ContentQuery<T, TRecord>(_query);
}
}
class ContentQuery<T, TR> : ContentQuery<T>, IContentQuery<T, TR>
where T : IContent
where TR : ContentPartRecord {
public ContentQuery(DefaultContentQuery query)
: base(query) {
}
public IContentQuery<T, TR> Where(Expression<Func<TR, bool>> predicate) {
_query.Where(predicate);
return this;
}
public IContentQuery<T, TR> OrderBy<TKey>(Expression<Func<TR, TKey>> keySelector) {
_query.OrderBy(keySelector);
return this;
}
public IContentQuery<T, TR> OrderByDescending<TKey>(Expression<Func<TR, TKey>> keySelector) {
_query.OrderByDescending(keySelector);
return this;
}
}
}
}

View File

@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1" MembersFormat="FullSignature">
<Class Name="Orchard.Models.ContentItem">
<Position X="0.5" Y="1.25" Width="2.5" />
<Members>
<Property Name="IContent.ContentItem" Hidden="true" />
</Members>
<TypeIdentifier>
<HashCode>AAACAAAAAAACAAhAABAAAAAAAAAAQABAAAAQAAAEBAA=</HashCode>
<FileName>Models\ContentItem.cs</FileName>
</TypeIdentifier>
<ShowAsAssociation>
<Property Name="Record" />
</ShowAsAssociation>
<ShowAsCollectionAssociation>
<Property Name="Parts" />
</ShowAsCollectionAssociation>
<Lollipop Position="0.2" />
</Class>
<Class Name="Orchard.Models.ContentPart">
<Position X="5.75" Y="2.25" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAA=</HashCode>
<FileName>Models\ContentPart.cs</FileName>
</TypeIdentifier>
<ShowAsAssociation>
<Property Name="ContentItem" />
</ShowAsAssociation>
<Lollipop Position="0.2" />
</Class>
<Class Name="Orchard.Models.ContentPart&lt;TRecord&gt;">
<Position X="5.25" Y="4" Width="2.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAA=</HashCode>
<FileName>Models\ContentPart.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Orchard.Models.Records.ContentItemRecord">
<Position X="0.5" Y="4.75" Width="2.5" />
<TypeIdentifier>
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAA=</HashCode>
<FileName>Models\Records\ContentItemRecord.cs</FileName>
</TypeIdentifier>
<ShowAsAssociation>
<Property Name="ContentType" />
</ShowAsAssociation>
</Class>
<Class Name="Orchard.Models.Records.ContentTypeRecord">
<Position X="0.5" Y="6.5" Width="2.25" />
<TypeIdentifier>
<HashCode>AAACAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Models\Records\ContentTypeRecord.cs</FileName>
</TypeIdentifier>
</Class>
<Interface Name="Orchard.Models.IContent">
<Position X="5.5" Y="0.5" Width="2.25" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAA=</HashCode>
<FileName>Models\IContent.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="Orchard.Models.IContentManager">
<Position X="4" Y="5.75" Width="6" />
<TypeIdentifier>
<HashCode>AAAAEAAAAAAAACBBAIAAAAAAAAEAAEgAAACAAAAAAAA=</HashCode>
<FileName>Models\IContentManager.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="Orchard.Models.Driver.IContentHandler">
<Position X="4.5" Y="8.75" Width="4.75" />
<TypeIdentifier>
<HashCode>AAAAEAAAAAEAAABBAIAAAIAAACEAAAQAAACAAAAAAAg=</HashCode>
<FileName>Models\Driver\IContentHandler.cs</FileName>
</TypeIdentifier>
</Interface>
<Font Name="Segoe UI" Size="9" />
</ClassDiagram>

View File

@@ -0,0 +1,6 @@
namespace Orchard.ContentManagement.Handlers {
public class ActivatedContentContext {
public string ContentType { get; set; }
public ContentItem ContentItem { get; set; }
}
}

View File

@@ -0,0 +1,6 @@
namespace Orchard.ContentManagement.Handlers {
public class ActivatingContentContext {
public string ContentType { get; set; }
public ContentItemBuilder Builder { get; set; }
}
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Linq;
namespace Orchard.ContentManagement.Handlers {
public class ActivatingFilter<TPart> : IContentActivatingFilter where TPart : ContentPart, new() {
private readonly Func<string, bool> _predicate;
public ActivatingFilter(Func<string, bool> predicate) {
_predicate = predicate;
}
public ActivatingFilter(params string[] contentTypes)
: this(contentType => contentTypes.Contains(contentType)) {
}
public void Activating(ActivatingContentContext context) {
if (_predicate(context.ContentType))
context.Builder.Weld<TPart>();
}
}
}

View File

@@ -0,0 +1,20 @@
using System.Linq;
using Orchard.ContentManagement.ViewModels;
namespace Orchard.ContentManagement.Handlers {
public class BuildDisplayModelContext {
public BuildDisplayModelContext(ItemDisplayModel displayModel, string displayType) {
ContentItem = displayModel.Item;
DisplayType = displayType;
DisplayModel = displayModel;
}
public ContentItem ContentItem { get; private set; }
public string DisplayType { get; private set; }
public ItemDisplayModel DisplayModel { get; private set; }
public void AddDisplay(TemplateViewModel display) {
DisplayModel.Displays = DisplayModel.Displays.Concat(new[] { display });
}
}
}

View File

@@ -0,0 +1,18 @@
using System.Linq;
using Orchard.ContentManagement.ViewModels;
namespace Orchard.ContentManagement.Handlers {
public class BuildEditorModelContext {
public BuildEditorModelContext(ItemEditorModel editorModel) {
ContentItem = editorModel.Item;
EditorModel = editorModel;
}
public ContentItem ContentItem { get; set; }
public ItemEditorModel EditorModel { get; set; }
public void AddEditor(TemplateViewModel editor) {
EditorModel.Editors = EditorModel.Editors.Concat(new[] { editor });
}
}
}

View File

@@ -0,0 +1,169 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard.Logging;
namespace Orchard.ContentManagement.Handlers {
public abstract class ContentHandler : IContentHandler {
protected ContentHandler() {
Filters = new List<IContentFilter>();
Logger = NullLogger.Instance;
}
public List<IContentFilter> Filters { get; set; }
public ILogger Logger { get; set; }
protected void OnActivated<TPart>(Action<ActivatedContentContext, TPart> handler) where TPart : class, IContent {
Filters.Add(new InlineStorageFilter<TPart> { OnActivated = handler });
}
protected void OnCreating<TPart>(Action<CreateContentContext, TPart> handler) where TPart : class, IContent {
Filters.Add(new InlineStorageFilter<TPart> { OnCreating = handler });
}
protected void OnCreated<TPart>(Action<CreateContentContext, TPart> handler) where TPart : class, IContent {
Filters.Add(new InlineStorageFilter<TPart> { OnCreated = handler });
}
protected void OnLoading<TPart>(Action<LoadContentContext, TPart> handler) where TPart : class, IContent {
Filters.Add(new InlineStorageFilter<TPart> { OnLoading = handler });
}
protected void OnLoaded<TPart>(Action<LoadContentContext, TPart> handler) where TPart : class, IContent {
Filters.Add(new InlineStorageFilter<TPart> { OnLoaded = handler });
}
protected void OnGetItemMetadata<TPart>(Action<GetItemMetadataContext, TPart> handler) where TPart : class, IContent {
Filters.Add(new InlineTemplateFilter<TPart> { OnGetItemMetadata = handler });
}
protected void OnGetDisplayViewModel<TPart>(Action<BuildDisplayModelContext, TPart> handler) where TPart : class, IContent {
Filters.Add(new InlineTemplateFilter<TPart> { OnGetDisplayViewModel = handler });
}
protected void OnGetEditorViewModel<TPart>(Action<BuildEditorModelContext, TPart> handler) where TPart : class, IContent {
Filters.Add(new InlineTemplateFilter<TPart> { OnGetEditorViewModel = handler });
}
protected void OnUpdateEditorViewModel<TPart>(Action<UpdateEditorModelContext, TPart> handler) where TPart : class, IContent {
Filters.Add(new InlineTemplateFilter<TPart> { OnUpdateEditorViewModel = handler });
}
class InlineStorageFilter<TPart> : StorageFilterBase<TPart> where TPart : class, IContent {
public Action<ActivatedContentContext, TPart> OnActivated { get; set; }
public Action<CreateContentContext, TPart> OnCreating { get; set; }
public Action<CreateContentContext, TPart> OnCreated { get; set; }
public Action<LoadContentContext, TPart> OnLoading { get; set; }
public Action<LoadContentContext, TPart> OnLoaded { get; set; }
protected override void Activated(ActivatedContentContext context, TPart instance) {
if (OnActivated != null) OnActivated(context, instance);
}
protected override void Creating(CreateContentContext context, TPart instance) {
if (OnCreating != null) OnCreating(context, instance);
}
protected override void Created(CreateContentContext context, TPart instance) {
if (OnCreated != null) OnCreated(context, instance);
}
protected override void Loading(LoadContentContext context, TPart instance) {
if (OnLoading != null) OnLoading(context, instance);
}
protected override void Loaded(LoadContentContext context, TPart instance) {
if (OnLoaded != null) OnLoaded(context, instance);
}
}
class InlineTemplateFilter<TPart> : TemplateFilterBase<TPart> where TPart : class, IContent {
public Action<GetItemMetadataContext, TPart> OnGetItemMetadata { get; set; }
public Action<BuildDisplayModelContext, TPart> OnGetDisplayViewModel { get; set; }
public Action<BuildEditorModelContext, TPart> OnGetEditorViewModel { get; set; }
public Action<UpdateEditorModelContext, TPart> OnUpdateEditorViewModel { get; set; }
protected override void GetItemMetadata(GetItemMetadataContext context, TPart instance) {
if (OnGetItemMetadata != null) OnGetItemMetadata(context, instance);
}
protected override void BuildDisplayModel(BuildDisplayModelContext context, TPart instance) {
if (OnGetDisplayViewModel != null) OnGetDisplayViewModel(context, instance);
}
protected override void BuildEditorModel(BuildEditorModelContext context, TPart instance) {
if (OnGetEditorViewModel != null) OnGetEditorViewModel(context, instance);
}
protected override void UpdateEditorModel(UpdateEditorModelContext context, TPart instance) {
if (OnUpdateEditorViewModel != null) OnUpdateEditorViewModel(context, instance);
}
}
public virtual IEnumerable<ContentType> GetContentTypes() {
return Enumerable.Empty<ContentType>();
}
void IContentHandler.Activating(ActivatingContentContext context) {
foreach (var filter in Filters.OfType<IContentActivatingFilter>())
filter.Activating(context);
Activating(context);
}
void IContentHandler.Activated(ActivatedContentContext context) {
foreach (var filter in Filters.OfType<IContentStorageFilter>())
filter.Activated(context);
Activated(context);
}
void IContentHandler.Creating(CreateContentContext context) {
foreach (var filter in Filters.OfType<IContentStorageFilter>())
filter.Creating(context);
Creating(context);
}
void IContentHandler.Created(CreateContentContext context) {
foreach (var filter in Filters.OfType<IContentStorageFilter>())
filter.Created(context);
Created(context);
}
void IContentHandler.Loading(LoadContentContext context) {
foreach (var filter in Filters.OfType<IContentStorageFilter>())
filter.Loading(context);
Loading(context);
}
void IContentHandler.Loaded(LoadContentContext context) {
foreach (var filter in Filters.OfType<IContentStorageFilter>())
filter.Loaded(context);
Loaded(context);
}
void IContentHandler.GetItemMetadata(GetItemMetadataContext context) {
foreach (var filter in Filters.OfType<IContentTemplateFilter>())
filter.GetItemMetadata(context);
GetItemMetadata(context);
}
void IContentHandler.BuildDisplayModel(BuildDisplayModelContext context) {
foreach (var filter in Filters.OfType<IContentTemplateFilter>())
filter.BuildDisplayModel(context);
BuildDisplayModel(context);
}
void IContentHandler.BuildEditorModel(BuildEditorModelContext context) {
foreach (var filter in Filters.OfType<IContentTemplateFilter>())
filter.BuildEditorModel(context);
BuildEditorModel(context);
}
void IContentHandler.UpdateEditorModel(UpdateEditorModelContext context) {
foreach (var filter in Filters.OfType<IContentTemplateFilter>())
filter.UpdateEditorModel(context);
UpdateEditorModel(context);
}
protected virtual void Activating(ActivatingContentContext context) { }
protected virtual void Activated(ActivatedContentContext context) { }
protected virtual void Loading(LoadContentContext context) { }
protected virtual void Loaded(LoadContentContext context) { }
protected virtual void Creating(CreateContentContext context) { }
protected virtual void Created(CreateContentContext context) { }
protected virtual void GetItemMetadata(GetItemMetadataContext context) { }
protected virtual void BuildDisplayModel(BuildDisplayModelContext context) { }
protected virtual void BuildEditorModel(BuildEditorModelContext context) { }
protected virtual void UpdateEditorModel(UpdateEditorModelContext context) {}
}
}

View File

@@ -0,0 +1,21 @@
using System;
namespace Orchard.ContentManagement.Handlers {
public class ContentItemBuilder {
private readonly ContentItem _item;
public ContentItemBuilder(string contentType) {
_item = new ContentItem { ContentType = contentType };
}
public ContentItem Build() {
return _item;
}
public ContentItemBuilder Weld<TPart>() where TPart : ContentPart, new() {
var part = new TPart();
_item.Weld(part);
return this;
}
}
}

View File

@@ -0,0 +1,83 @@
using System;
using System.Linq;
using System.Web.Mvc;
using Orchard.ContentManagement.ViewModels;
namespace Orchard.ContentManagement.Handlers {
public class ContentItemTemplates<TContent> : TemplateFilterBase<TContent> where TContent : class, IContent {
private readonly string _templateName;
// todo: (heskew) use _prefix?
private readonly string _prefix;
private readonly string[] _displayTypes;
private Action<UpdateEditorModelContext, ItemEditorModel<TContent>> _updater;
public ContentItemTemplates(string templateName)
: this(templateName, "") {
}
public ContentItemTemplates(string templateName, string displayTypes) {
_templateName = templateName;
_displayTypes = (displayTypes ?? "").Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
_updater = (context, viewModel) => context.Updater.TryUpdateModel(viewModel, "", null, null);
}
protected override void BuildDisplayModel(BuildDisplayModelContext context, TContent instance) {
context.DisplayModel.TemplateName = _templateName;
var longestMatch = LongestMatch(context.DisplayType);
if (!string.IsNullOrEmpty(longestMatch))
context.DisplayModel.TemplateName += "." + longestMatch;
context.DisplayModel.Prefix = _prefix;
if (context.DisplayModel.GetType() != typeof(ItemDisplayModel<TContent>)) {
context.DisplayModel.Adaptor = (html, viewModel) => {
return new HtmlHelper<ItemDisplayModel<TContent>>(
html.ViewContext,
new ViewDataContainer { ViewData = new ViewDataDictionary(new ItemDisplayModel<TContent>(viewModel)) },
html.RouteCollection);
};
}
}
class ViewDataContainer : IViewDataContainer {
public ViewDataDictionary ViewData { get; set; }
}
private string LongestMatch(string displayType) {
if (string.IsNullOrEmpty(displayType))
return displayType;
return _displayTypes.Aggregate("", (best, x) => {
if (displayType.StartsWith(x) && x.Length > best.Length) return x;
return best;
});
}
protected override void BuildEditorModel(BuildEditorModelContext context, TContent instance) {
context.EditorModel.TemplateName = _templateName;
context.EditorModel.Prefix = _prefix;
if (context.EditorModel.GetType() != typeof(ItemEditorModel<TContent>)) {
context.EditorModel.Adaptor = (html, viewModel) => {
return new HtmlHelper<ItemEditorModel<TContent>>(
html.ViewContext,
new ViewDataContainer { ViewData = new ViewDataDictionary(new ItemEditorModel<TContent>(viewModel)) },
html.RouteCollection);
};
}
}
protected override void UpdateEditorModel(UpdateEditorModelContext context, TContent instance) {
if (context.EditorModel is ItemEditorModel<TContent>)
_updater(context, (ItemEditorModel<TContent>)context.EditorModel);
else
_updater(context, new ItemEditorModel<TContent>(context.EditorModel));
context.EditorModel.TemplateName = _templateName;
context.EditorModel.Prefix = _prefix;
}
public void Updater(Action<UpdateEditorModelContext, ItemEditorModel<TContent>> updater) {
_updater = updater;
}
}
}

View File

@@ -0,0 +1,10 @@
using Orchard.ContentManagement.Records;
namespace Orchard.ContentManagement.Handlers {
public class CreateContentContext {
public int Id { get; set; }
public string ContentType { get; set; }
public ContentItemRecord ContentItemRecord { get; set; }
public ContentItem ContentItem { get; set; }
}
}

View File

@@ -0,0 +1,6 @@
namespace Orchard.ContentManagement.Handlers {
public class GetItemMetadataContext {
public ContentItem ContentItem { get; set; }
public ContentItemMetadata Metadata { get; set; }
}
}

View File

@@ -0,0 +1,5 @@
namespace Orchard.ContentManagement.Handlers {
public interface IContentActivatingFilter : IContentFilter {
void Activating(ActivatingContentContext context);
}
}

View File

@@ -0,0 +1,4 @@
namespace Orchard.ContentManagement.Handlers {
public interface IContentFilter {
}
}

View File

@@ -0,0 +1,19 @@
using System.Collections.Generic;
namespace Orchard.ContentManagement.Handlers {
public interface IContentHandler : IEvents {
IEnumerable<ContentType> GetContentTypes();
void Activating(ActivatingContentContext context);
void Activated(ActivatedContentContext context);
void Creating(CreateContentContext context);
void Created(CreateContentContext context);
void Loading(LoadContentContext context);
void Loaded(LoadContentContext context);
void GetItemMetadata(GetItemMetadataContext context);
void BuildDisplayModel(BuildDisplayModelContext context);
void BuildEditorModel(BuildEditorModelContext context);
void UpdateEditorModel(UpdateEditorModelContext context);
}
}

View File

@@ -0,0 +1,9 @@
namespace Orchard.ContentManagement.Handlers {
public interface IContentStorageFilter : IContentFilter {
void Activated(ActivatedContentContext context);
void Creating(CreateContentContext context);
void Created(CreateContentContext context);
void Loading(LoadContentContext context);
void Loaded(LoadContentContext context);
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Orchard.ContentManagement.Handlers {
interface IContentTemplateFilter : IContentFilter {
void GetItemMetadata(GetItemMetadataContext context);
void BuildDisplayModel(BuildDisplayModelContext context);
void BuildEditorModel(BuildEditorModelContext context);
void UpdateEditorModel(UpdateEditorModelContext context);
}
}

View File

@@ -0,0 +1,8 @@
using Orchard.Localization;
namespace Orchard.ContentManagement.Handlers {
public interface IUpdateModel {
bool TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) where TModel : class;
void AddModelError(string key, LocalizedString errorMessage);
}
}

View File

@@ -0,0 +1,11 @@
using System;
using Orchard.ContentManagement.Records;
namespace Orchard.ContentManagement.Handlers {
public class LoadContentContext {
public int Id { get; set; }
public string ContentType { get; set; }
public ContentItemRecord ContentItemRecord { get; set; }
public ContentItem ContentItem { get; set; }
}
}

View File

@@ -0,0 +1,34 @@
using Orchard.ContentManagement.Records;
using Orchard.Data;
namespace Orchard.ContentManagement.Handlers {
public class StorageFilter<TRecord> : StorageFilterBase<ContentPart<TRecord>> where TRecord : ContentPartRecord,new() {
private readonly IRepository<TRecord> _repository;
public StorageFilter(IRepository<TRecord> repository) {
_repository = repository;
}
public bool AutomaticallyCreateMissingRecord { get; set; }
protected override void Activated(ActivatedContentContext context, ContentPart<TRecord> instance) {
instance.Record = new TRecord();
}
protected override void Creating(CreateContentContext context, ContentPart<TRecord> instance) {
instance.Record.ContentItemRecord = context.ContentItemRecord;
_repository.Create(instance.Record);
}
protected override void Loading(LoadContentContext context, ContentPart<TRecord> instance) {
var record = _repository.Get(instance.ContentItem.Id);
if (record != null) {
instance.Record = record;
}
else if (AutomaticallyCreateMissingRecord) {
instance.Record = new TRecord {ContentItemRecord = context.ContentItemRecord};
_repository.Create(instance.Record);
}
}
}
}

View File

@@ -0,0 +1,36 @@
namespace Orchard.ContentManagement.Handlers {
public abstract class StorageFilterBase<TPart> : IContentStorageFilter where TPart : class, IContent {
protected virtual void Activated(ActivatedContentContext context, TPart instance) { }
protected virtual void Creating(CreateContentContext context, TPart instance) { }
protected virtual void Created(CreateContentContext context, TPart instance) { }
protected virtual void Loading(LoadContentContext context, TPart instance) { }
protected virtual void Loaded(LoadContentContext context, TPart instance) { }
void IContentStorageFilter.Activated(ActivatedContentContext context) {
if (context.ContentItem.Is<TPart>())
Activated(context, context.ContentItem.As<TPart>());
}
void IContentStorageFilter.Creating(CreateContentContext context) {
if (context.ContentItem.Is<TPart>())
Creating(context, context.ContentItem.As<TPart>());
}
void IContentStorageFilter.Created(CreateContentContext context) {
if (context.ContentItem.Is<TPart>())
Created(context, context.ContentItem.As<TPart>());
}
void IContentStorageFilter.Loading(LoadContentContext context) {
if (context.ContentItem.Is<TPart>())
Loading(context, context.ContentItem.As<TPart>());
}
void IContentStorageFilter.Loaded(LoadContentContext context) {
if (context.ContentItem.Is<TPart>())
Loaded(context, context.ContentItem.As<TPart>());
}
}
}

View File

@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Orchard.ContentManagement.Handlers {
public abstract class TemplateFilterBase<TPart> : IContentTemplateFilter where TPart : class, IContent {
protected virtual void GetItemMetadata(GetItemMetadataContext context, TPart instance) { }
protected virtual void BuildDisplayModel(BuildDisplayModelContext context, TPart instance) { }
protected virtual void BuildEditorModel(BuildEditorModelContext context, TPart instance) { }
protected virtual void UpdateEditorModel(UpdateEditorModelContext context, TPart instance) { }
void IContentTemplateFilter.GetItemMetadata(GetItemMetadataContext context) {
if (context.ContentItem.Is<TPart>())
GetItemMetadata(context, context.ContentItem.As<TPart>());
}
void IContentTemplateFilter.BuildDisplayModel(BuildDisplayModelContext context) {
if (context.ContentItem.Is<TPart>())
BuildDisplayModel(context, context.ContentItem.As<TPart>());
}
void IContentTemplateFilter.BuildEditorModel(BuildEditorModelContext context) {
if (context.ContentItem.Is<TPart>())
BuildEditorModel(context, context.ContentItem.As<TPart>());
}
void IContentTemplateFilter.UpdateEditorModel(UpdateEditorModelContext context) {
if (context.ContentItem.Is<TPart>())
UpdateEditorModel(context, context.ContentItem.As<TPart>());
}
}
}

View File

@@ -0,0 +1,23 @@
using Orchard.ContentManagement.Records;
using Orchard.ContentManagement.ViewModels;
namespace Orchard.ContentManagement.Handlers {
public class TemplateFilterForRecord<TRecord> : TemplateFilterBase<ContentPart<TRecord>> where TRecord : ContentPartRecord, new() {
private readonly string _prefix;
private readonly string _templateName;
public TemplateFilterForRecord(string prefix, string templateName) {
_prefix = prefix;
_templateName = templateName;
}
protected override void BuildEditorModel(BuildEditorModelContext context, ContentPart<TRecord> part) {
context.AddEditor(new TemplateViewModel(part.Record, _prefix) { TemplateName = _templateName });
}
protected override void UpdateEditorModel(UpdateEditorModelContext context, ContentPart<TRecord> part) {
context.Updater.TryUpdateModel(part.Record, _prefix, null, null);
context.AddEditor(new TemplateViewModel(part.Record, _prefix) { TemplateName = _templateName });
}
}
}

View File

@@ -0,0 +1,12 @@
using Orchard.ContentManagement.ViewModels;
namespace Orchard.ContentManagement.Handlers {
public class UpdateEditorModelContext : BuildEditorModelContext {
public UpdateEditorModelContext(ItemEditorModel editorModel, IUpdateModel updater)
: base(editorModel) {
Updater = updater;
}
public IUpdateModel Updater { get; private set; }
}
}

View File

@@ -0,0 +1,21 @@
using Orchard.ContentManagement.Handlers;
namespace Orchard.ContentManagement.Drivers {
public abstract class AutomaticPartDriver<TPart> : PartDriver<TPart> where TPart : class, IContent {
protected override string Prefix {
get {
return (typeof (TPart).Name);
}
}
protected override DriverResult Display(TPart part, string displayType) {
return PartialView(part);
}
protected override DriverResult Editor(TPart part) {
return PartialView(part);
}
protected override DriverResult Editor(TPart part, IUpdateModel updater) {
updater.TryUpdateModel(part, Prefix, null, null);
return PartialView(part);
}
}
}

View File

@@ -0,0 +1,23 @@
using Orchard.ContentManagement.Handlers;
namespace Orchard.ContentManagement.Drivers {
public class CombinedResult : DriverResult {
private readonly DriverResult[] _results;
public CombinedResult(DriverResult[] results) {
_results = results;
}
public override void Apply(BuildDisplayModelContext context) {
foreach (var result in _results) {
result.Apply(context);
}
}
public override void Apply(BuildEditorModelContext context) {
foreach(var result in _results) {
result.Apply(context);
}
}
}
}

View File

@@ -0,0 +1,8 @@
using Orchard.ContentManagement.Handlers;
namespace Orchard.ContentManagement.Drivers {
public class DriverResult {
public virtual void Apply(BuildDisplayModelContext context) { }
public virtual void Apply(BuildEditorModelContext context) { }
}
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Routing;
using Orchard.ContentManagement.Handlers;
namespace Orchard.ContentManagement.Drivers {
public interface IItemDriver : IEvents {
void GetItemMetadata(GetItemMetadataContext context);
}
public abstract class ItemDriver<TItemPart> : PartDriver<TItemPart>, IItemDriver where TItemPart : class, IContent {
public void GetItemMetadata(GetItemMetadataContext context) {
var item = context.ContentItem.As<TItemPart>();
if (item != null) {
context.Metadata.DisplayText = GetDisplayText(item) ?? context.Metadata.DisplayText;
context.Metadata.DisplayRouteValues = GetDisplayRouteValues(item) ?? context.Metadata.DisplayRouteValues;
context.Metadata.EditorRouteValues = GetEditorRouteValues(item) ?? context.Metadata.EditorRouteValues;
}
}
protected virtual string GetDisplayText(TItemPart item) { return null; }
protected virtual RouteValueDictionary GetDisplayRouteValues(TItemPart item) { return null; }
protected virtual RouteValueDictionary GetEditorRouteValues(TItemPart item) { return null; }
}
}

View File

@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using JetBrains.Annotations;
using Orchard.ContentManagement.Handlers;
using Orchard.Logging;
namespace Orchard.ContentManagement.Drivers {
[UsedImplicitly]
public class ItemDriverHandler : IContentHandler {
private readonly IEnumerable<IItemDriver> _drivers;
public ItemDriverHandler(IEnumerable<IItemDriver> drivers) {
_drivers = drivers;
Logger = NullLogger.Instance;
}
public ILogger Logger { get; set; }
System.Collections.Generic.IEnumerable<ContentType> IContentHandler.GetContentTypes() {
return Enumerable.Empty<ContentType>();
}
void IContentHandler.Activating(ActivatingContentContext context) { }
void IContentHandler.Activated(ActivatedContentContext context) { }
void IContentHandler.Creating(CreateContentContext context) { }
void IContentHandler.Created(CreateContentContext context) { }
void IContentHandler.Loading(LoadContentContext context) { }
void IContentHandler.Loaded(LoadContentContext context) { }
void IContentHandler.GetItemMetadata(GetItemMetadataContext context) {
_drivers.Invoke(driver => {
driver.GetItemMetadata(context);
}, Logger);
}
void IContentHandler.BuildDisplayModel(BuildDisplayModelContext context) { }
void IContentHandler.BuildEditorModel(BuildEditorModelContext context) { }
void IContentHandler.UpdateEditorModel(UpdateEditorModelContext context) { }
}
}

View File

@@ -0,0 +1,49 @@
using System;
using Orchard.ContentManagement.Handlers;
namespace Orchard.ContentManagement.Drivers {
public interface IPartDriver : IEvents {
DriverResult BuildDisplayModel(BuildDisplayModelContext context);
DriverResult BuildEditorModel(BuildEditorModelContext context);
DriverResult UpdateEditorModel(UpdateEditorModelContext context);
}
public abstract class PartDriver<TPart> : IPartDriver where TPart : class, IContent {
protected virtual string Prefix { get { return ""; } }
protected virtual string Zone { get { return "body"; } }
DriverResult IPartDriver.BuildDisplayModel(BuildDisplayModelContext context) {
var part = context.ContentItem.As<TPart>();
return part == null ? null : Display(part, context.DisplayType);
}
DriverResult IPartDriver.BuildEditorModel(BuildEditorModelContext context) {
var part = context.ContentItem.As<TPart>();
return part == null ? null : Editor(part);
}
DriverResult IPartDriver.UpdateEditorModel(UpdateEditorModelContext context) {
var part = context.ContentItem.As<TPart>();
return part == null ? null : Editor(part, context.Updater);
}
protected virtual DriverResult Display(TPart part, string displayType) {return null;}
protected virtual DriverResult Editor(TPart part) {return null;}
protected virtual DriverResult Editor(TPart part, IUpdateModel updater) {return null;}
public TemplateResult PartialView(object model) {
return new TemplateResult(model, null, Prefix).Location(Zone);
}
public TemplateResult PartialView(object model, string template) {
return new TemplateResult(model, template, Prefix).Location(Zone);
}
public TemplateResult PartialView(object model, string template, string prefix) {
return new TemplateResult(model, template, prefix).Location(Zone);
}
public CombinedResult Combined(params DriverResult[] results) {
return new CombinedResult(results);
}
}
}

View File

@@ -0,0 +1,62 @@
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Orchard.ContentManagement.Handlers;
using Orchard.Logging;
namespace Orchard.ContentManagement.Drivers {
[UsedImplicitly]
public class PartDriverHandler : IContentHandler {
private readonly IEnumerable<IPartDriver> _drivers;
public PartDriverHandler(IEnumerable<IPartDriver> drivers) {
_drivers = drivers;
Logger = NullLogger.Instance;
}
public ILogger Logger { get; set; }
System.Collections.Generic.IEnumerable<ContentType> IContentHandler.GetContentTypes() {
return Enumerable.Empty<ContentType>();
}
void IContentHandler.Activating(ActivatingContentContext context) { }
void IContentHandler.Activated(ActivatedContentContext context) { }
void IContentHandler.Creating(CreateContentContext context) { }
void IContentHandler.Created(CreateContentContext context) { }
void IContentHandler.Loading(LoadContentContext context) { }
void IContentHandler.Loaded(LoadContentContext context) { }
void IContentHandler.GetItemMetadata(GetItemMetadataContext context) { }
void IContentHandler.BuildDisplayModel(BuildDisplayModelContext context) {
_drivers.Invoke(driver => {
var result = driver.BuildDisplayModel(context);
if (result != null)
result.Apply(context);
}, Logger);
}
void IContentHandler.BuildEditorModel(BuildEditorModelContext context) {
_drivers.Invoke(driver => {
var result = driver.BuildEditorModel(context);
if (result != null)
result.Apply(context);
}, Logger);
}
void IContentHandler.UpdateEditorModel(UpdateEditorModelContext context) {
_drivers.Invoke(driver => {
var result = driver.UpdateEditorModel(context);
if (result != null)
result.Apply(context);
}, Logger);
}
}
}

View File

@@ -0,0 +1,45 @@
using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.ViewModels;
namespace Orchard.ContentManagement.Drivers {
public class TemplateResult : DriverResult {
public object Model { get; set; }
public string TemplateName { get; set; }
public string Prefix { get; set; }
public string Zone { get; set; }
public string Position { get; set; }
public TemplateResult(object model, string templateName, string prefix) {
Model = model;
TemplateName = templateName;
Prefix = prefix;
}
public override void Apply(BuildDisplayModelContext context) {
context.AddDisplay(new TemplateViewModel(Model, Prefix) {
TemplateName = TemplateName,
ZoneName = Zone,
Position = Position
});
}
public override void Apply(BuildEditorModelContext context) {
context.AddEditor(new TemplateViewModel(Model, Prefix) {
TemplateName = TemplateName,
ZoneName = Zone,
Position = Position
});
}
public TemplateResult Location(string zone) {
Zone = zone;
return this;
}
public TemplateResult Location(string zone, string position) {
Zone = zone;
Position = position;
return this;
}
}
}

View File

@@ -0,0 +1,6 @@
namespace Orchard.ContentManagement.Handlers {
public class ActivatedContentContext {
public string ContentType { get; set; }
public ContentItem ContentItem { get; set; }
}
}

View File

@@ -0,0 +1,6 @@
namespace Orchard.ContentManagement.Handlers {
public class ActivatingContentContext {
public string ContentType { get; set; }
public ContentItemBuilder Builder { get; set; }
}
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Linq;
namespace Orchard.ContentManagement.Handlers {
public class ActivatingFilter<TPart> : IContentActivatingFilter where TPart : ContentPart, new() {
private readonly Func<string, bool> _predicate;
public ActivatingFilter(Func<string, bool> predicate) {
_predicate = predicate;
}
public ActivatingFilter(params string[] contentTypes)
: this(contentType => contentTypes.Contains(contentType)) {
}
public void Activating(ActivatingContentContext context) {
if (_predicate(context.ContentType))
context.Builder.Weld<TPart>();
}
}
}

View File

@@ -0,0 +1,20 @@
using System.Linq;
using Orchard.ContentManagement.ViewModels;
namespace Orchard.ContentManagement.Handlers {
public class BuildDisplayModelContext {
public BuildDisplayModelContext(ItemDisplayModel displayModel, string displayType) {
ContentItem = displayModel.Item;
DisplayType = displayType;
DisplayModel = displayModel;
}
public ContentItem ContentItem { get; private set; }
public string DisplayType { get; private set; }
public ItemDisplayModel DisplayModel { get; private set; }
public void AddDisplay(TemplateViewModel display) {
DisplayModel.Displays = DisplayModel.Displays.Concat(new[] { display });
}
}
}

View File

@@ -0,0 +1,18 @@
using System.Linq;
using Orchard.ContentManagement.ViewModels;
namespace Orchard.ContentManagement.Handlers {
public class BuildEditorModelContext {
public BuildEditorModelContext(ItemEditorModel editorModel) {
ContentItem = editorModel.Item;
EditorModel = editorModel;
}
public ContentItem ContentItem { get; set; }
public ItemEditorModel EditorModel { get; set; }
public void AddEditor(TemplateViewModel editor) {
EditorModel.Editors = EditorModel.Editors.Concat(new[] { editor });
}
}
}

View File

@@ -0,0 +1,169 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard.Logging;
namespace Orchard.ContentManagement.Handlers {
public abstract class ContentHandler : IContentHandler {
protected ContentHandler() {
Filters = new List<IContentFilter>();
Logger = NullLogger.Instance;
}
public List<IContentFilter> Filters { get; set; }
public ILogger Logger { get; set; }
protected void OnActivated<TPart>(Action<ActivatedContentContext, TPart> handler) where TPart : class, IContent {
Filters.Add(new InlineStorageFilter<TPart> { OnActivated = handler });
}
protected void OnCreating<TPart>(Action<CreateContentContext, TPart> handler) where TPart : class, IContent {
Filters.Add(new InlineStorageFilter<TPart> { OnCreating = handler });
}
protected void OnCreated<TPart>(Action<CreateContentContext, TPart> handler) where TPart : class, IContent {
Filters.Add(new InlineStorageFilter<TPart> { OnCreated = handler });
}
protected void OnLoading<TPart>(Action<LoadContentContext, TPart> handler) where TPart : class, IContent {
Filters.Add(new InlineStorageFilter<TPart> { OnLoading = handler });
}
protected void OnLoaded<TPart>(Action<LoadContentContext, TPart> handler) where TPart : class, IContent {
Filters.Add(new InlineStorageFilter<TPart> { OnLoaded = handler });
}
protected void OnGetItemMetadata<TPart>(Action<GetItemMetadataContext, TPart> handler) where TPart : class, IContent {
Filters.Add(new InlineTemplateFilter<TPart> { OnGetItemMetadata = handler });
}
protected void OnGetDisplayViewModel<TPart>(Action<BuildDisplayModelContext, TPart> handler) where TPart : class, IContent {
Filters.Add(new InlineTemplateFilter<TPart> { OnGetDisplayViewModel = handler });
}
protected void OnGetEditorViewModel<TPart>(Action<BuildEditorModelContext, TPart> handler) where TPart : class, IContent {
Filters.Add(new InlineTemplateFilter<TPart> { OnGetEditorViewModel = handler });
}
protected void OnUpdateEditorViewModel<TPart>(Action<UpdateEditorModelContext, TPart> handler) where TPart : class, IContent {
Filters.Add(new InlineTemplateFilter<TPart> { OnUpdateEditorViewModel = handler });
}
class InlineStorageFilter<TPart> : StorageFilterBase<TPart> where TPart : class, IContent {
public Action<ActivatedContentContext, TPart> OnActivated { get; set; }
public Action<CreateContentContext, TPart> OnCreating { get; set; }
public Action<CreateContentContext, TPart> OnCreated { get; set; }
public Action<LoadContentContext, TPart> OnLoading { get; set; }
public Action<LoadContentContext, TPart> OnLoaded { get; set; }
protected override void Activated(ActivatedContentContext context, TPart instance) {
if (OnActivated != null) OnActivated(context, instance);
}
protected override void Creating(CreateContentContext context, TPart instance) {
if (OnCreating != null) OnCreating(context, instance);
}
protected override void Created(CreateContentContext context, TPart instance) {
if (OnCreated != null) OnCreated(context, instance);
}
protected override void Loading(LoadContentContext context, TPart instance) {
if (OnLoading != null) OnLoading(context, instance);
}
protected override void Loaded(LoadContentContext context, TPart instance) {
if (OnLoaded != null) OnLoaded(context, instance);
}
}
class InlineTemplateFilter<TPart> : TemplateFilterBase<TPart> where TPart : class, IContent {
public Action<GetItemMetadataContext, TPart> OnGetItemMetadata { get; set; }
public Action<BuildDisplayModelContext, TPart> OnGetDisplayViewModel { get; set; }
public Action<BuildEditorModelContext, TPart> OnGetEditorViewModel { get; set; }
public Action<UpdateEditorModelContext, TPart> OnUpdateEditorViewModel { get; set; }
protected override void GetItemMetadata(GetItemMetadataContext context, TPart instance) {
if (OnGetItemMetadata != null) OnGetItemMetadata(context, instance);
}
protected override void BuildDisplayModel(BuildDisplayModelContext context, TPart instance) {
if (OnGetDisplayViewModel != null) OnGetDisplayViewModel(context, instance);
}
protected override void BuildEditorModel(BuildEditorModelContext context, TPart instance) {
if (OnGetEditorViewModel != null) OnGetEditorViewModel(context, instance);
}
protected override void UpdateEditorModel(UpdateEditorModelContext context, TPart instance) {
if (OnUpdateEditorViewModel != null) OnUpdateEditorViewModel(context, instance);
}
}
public virtual IEnumerable<ContentType> GetContentTypes() {
return Enumerable.Empty<ContentType>();
}
void IContentHandler.Activating(ActivatingContentContext context) {
foreach (var filter in Filters.OfType<IContentActivatingFilter>())
filter.Activating(context);
Activating(context);
}
void IContentHandler.Activated(ActivatedContentContext context) {
foreach (var filter in Filters.OfType<IContentStorageFilter>())
filter.Activated(context);
Activated(context);
}
void IContentHandler.Creating(CreateContentContext context) {
foreach (var filter in Filters.OfType<IContentStorageFilter>())
filter.Creating(context);
Creating(context);
}
void IContentHandler.Created(CreateContentContext context) {
foreach (var filter in Filters.OfType<IContentStorageFilter>())
filter.Created(context);
Created(context);
}
void IContentHandler.Loading(LoadContentContext context) {
foreach (var filter in Filters.OfType<IContentStorageFilter>())
filter.Loading(context);
Loading(context);
}
void IContentHandler.Loaded(LoadContentContext context) {
foreach (var filter in Filters.OfType<IContentStorageFilter>())
filter.Loaded(context);
Loaded(context);
}
void IContentHandler.GetItemMetadata(GetItemMetadataContext context) {
foreach (var filter in Filters.OfType<IContentTemplateFilter>())
filter.GetItemMetadata(context);
GetItemMetadata(context);
}
void IContentHandler.BuildDisplayModel(BuildDisplayModelContext context) {
foreach (var filter in Filters.OfType<IContentTemplateFilter>())
filter.BuildDisplayModel(context);
BuildDisplayModel(context);
}
void IContentHandler.BuildEditorModel(BuildEditorModelContext context) {
foreach (var filter in Filters.OfType<IContentTemplateFilter>())
filter.BuildEditorModel(context);
BuildEditorModel(context);
}
void IContentHandler.UpdateEditorModel(UpdateEditorModelContext context) {
foreach (var filter in Filters.OfType<IContentTemplateFilter>())
filter.UpdateEditorModel(context);
UpdateEditorModel(context);
}
protected virtual void Activating(ActivatingContentContext context) { }
protected virtual void Activated(ActivatedContentContext context) { }
protected virtual void Loading(LoadContentContext context) { }
protected virtual void Loaded(LoadContentContext context) { }
protected virtual void Creating(CreateContentContext context) { }
protected virtual void Created(CreateContentContext context) { }
protected virtual void GetItemMetadata(GetItemMetadataContext context) { }
protected virtual void BuildDisplayModel(BuildDisplayModelContext context) { }
protected virtual void BuildEditorModel(BuildEditorModelContext context) { }
protected virtual void UpdateEditorModel(UpdateEditorModelContext context) {}
}
}

View File

@@ -0,0 +1,21 @@
using System;
namespace Orchard.ContentManagement.Handlers {
public class ContentItemBuilder {
private readonly ContentItem _item;
public ContentItemBuilder(string contentType) {
_item = new ContentItem { ContentType = contentType };
}
public ContentItem Build() {
return _item;
}
public ContentItemBuilder Weld<TPart>() where TPart : ContentPart, new() {
var part = new TPart();
_item.Weld(part);
return this;
}
}
}

View File

@@ -0,0 +1,83 @@
using System;
using System.Linq;
using System.Web.Mvc;
using Orchard.ContentManagement.ViewModels;
namespace Orchard.ContentManagement.Handlers {
public class ContentItemTemplates<TContent> : TemplateFilterBase<TContent> where TContent : class, IContent {
private readonly string _templateName;
// todo: (heskew) use _prefix?
private readonly string _prefix;
private readonly string[] _displayTypes;
private Action<UpdateEditorModelContext, ItemEditorModel<TContent>> _updater;
public ContentItemTemplates(string templateName)
: this(templateName, "") {
}
public ContentItemTemplates(string templateName, string displayTypes) {
_templateName = templateName;
_displayTypes = (displayTypes ?? "").Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
_updater = (context, viewModel) => context.Updater.TryUpdateModel(viewModel, "", null, null);
}
protected override void BuildDisplayModel(BuildDisplayModelContext context, TContent instance) {
context.DisplayModel.TemplateName = _templateName;
var longestMatch = LongestMatch(context.DisplayType);
if (!string.IsNullOrEmpty(longestMatch))
context.DisplayModel.TemplateName += "." + longestMatch;
context.DisplayModel.Prefix = _prefix;
if (context.DisplayModel.GetType() != typeof(ItemDisplayModel<TContent>)) {
context.DisplayModel.Adaptor = (html, viewModel) => {
return new HtmlHelper<ItemDisplayModel<TContent>>(
html.ViewContext,
new ViewDataContainer { ViewData = new ViewDataDictionary(new ItemDisplayModel<TContent>(viewModel)) },
html.RouteCollection);
};
}
}
class ViewDataContainer : IViewDataContainer {
public ViewDataDictionary ViewData { get; set; }
}
private string LongestMatch(string displayType) {
if (string.IsNullOrEmpty(displayType))
return displayType;
return _displayTypes.Aggregate("", (best, x) => {
if (displayType.StartsWith(x) && x.Length > best.Length) return x;
return best;
});
}
protected override void BuildEditorModel(BuildEditorModelContext context, TContent instance) {
context.EditorModel.TemplateName = _templateName;
context.EditorModel.Prefix = _prefix;
if (context.EditorModel.GetType() != typeof(ItemEditorModel<TContent>)) {
context.EditorModel.Adaptor = (html, viewModel) => {
return new HtmlHelper<ItemEditorModel<TContent>>(
html.ViewContext,
new ViewDataContainer { ViewData = new ViewDataDictionary(new ItemEditorModel<TContent>(viewModel)) },
html.RouteCollection);
};
}
}
protected override void UpdateEditorModel(UpdateEditorModelContext context, TContent instance) {
if (context.EditorModel is ItemEditorModel<TContent>)
_updater(context, (ItemEditorModel<TContent>)context.EditorModel);
else
_updater(context, new ItemEditorModel<TContent>(context.EditorModel));
context.EditorModel.TemplateName = _templateName;
context.EditorModel.Prefix = _prefix;
}
public void Updater(Action<UpdateEditorModelContext, ItemEditorModel<TContent>> updater) {
_updater = updater;
}
}
}

View File

@@ -0,0 +1,10 @@
using Orchard.ContentManagement.Records;
namespace Orchard.ContentManagement.Handlers {
public class CreateContentContext {
public int Id { get; set; }
public string ContentType { get; set; }
public ContentItemRecord ContentItemRecord { get; set; }
public ContentItem ContentItem { get; set; }
}
}

View File

@@ -0,0 +1,6 @@
namespace Orchard.ContentManagement.Handlers {
public class GetItemMetadataContext {
public ContentItem ContentItem { get; set; }
public ContentItemMetadata Metadata { get; set; }
}
}

View File

@@ -0,0 +1,5 @@
namespace Orchard.ContentManagement.Handlers {
public interface IContentActivatingFilter : IContentFilter {
void Activating(ActivatingContentContext context);
}
}

View File

@@ -0,0 +1,4 @@
namespace Orchard.ContentManagement.Handlers {
public interface IContentFilter {
}
}

View File

@@ -0,0 +1,19 @@
using System.Collections.Generic;
namespace Orchard.ContentManagement.Handlers {
public interface IContentHandler : IEvents {
IEnumerable<ContentType> GetContentTypes();
void Activating(ActivatingContentContext context);
void Activated(ActivatedContentContext context);
void Creating(CreateContentContext context);
void Created(CreateContentContext context);
void Loading(LoadContentContext context);
void Loaded(LoadContentContext context);
void GetItemMetadata(GetItemMetadataContext context);
void BuildDisplayModel(BuildDisplayModelContext context);
void BuildEditorModel(BuildEditorModelContext context);
void UpdateEditorModel(UpdateEditorModelContext context);
}
}

View File

@@ -0,0 +1,9 @@
namespace Orchard.ContentManagement.Handlers {
public interface IContentStorageFilter : IContentFilter {
void Activated(ActivatedContentContext context);
void Creating(CreateContentContext context);
void Created(CreateContentContext context);
void Loading(LoadContentContext context);
void Loaded(LoadContentContext context);
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Orchard.ContentManagement.Handlers {
interface IContentTemplateFilter : IContentFilter {
void GetItemMetadata(GetItemMetadataContext context);
void BuildDisplayModel(BuildDisplayModelContext context);
void BuildEditorModel(BuildEditorModelContext context);
void UpdateEditorModel(UpdateEditorModelContext context);
}
}

View File

@@ -0,0 +1,8 @@
using Orchard.Localization;
namespace Orchard.ContentManagement.Handlers {
public interface IUpdateModel {
bool TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) where TModel : class;
void AddModelError(string key, LocalizedString errorMessage);
}
}

View File

@@ -0,0 +1,11 @@
using System;
using Orchard.ContentManagement.Records;
namespace Orchard.ContentManagement.Handlers {
public class LoadContentContext {
public int Id { get; set; }
public string ContentType { get; set; }
public ContentItemRecord ContentItemRecord { get; set; }
public ContentItem ContentItem { get; set; }
}
}

View File

@@ -0,0 +1,34 @@
using Orchard.ContentManagement.Records;
using Orchard.Data;
namespace Orchard.ContentManagement.Handlers {
public class StorageFilter<TRecord> : StorageFilterBase<ContentPart<TRecord>> where TRecord : ContentPartRecord,new() {
private readonly IRepository<TRecord> _repository;
public StorageFilter(IRepository<TRecord> repository) {
_repository = repository;
}
public bool AutomaticallyCreateMissingRecord { get; set; }
protected override void Activated(ActivatedContentContext context, ContentPart<TRecord> instance) {
instance.Record = new TRecord();
}
protected override void Creating(CreateContentContext context, ContentPart<TRecord> instance) {
instance.Record.ContentItemRecord = context.ContentItemRecord;
_repository.Create(instance.Record);
}
protected override void Loading(LoadContentContext context, ContentPart<TRecord> instance) {
var record = _repository.Get(instance.ContentItem.Id);
if (record != null) {
instance.Record = record;
}
else if (AutomaticallyCreateMissingRecord) {
instance.Record = new TRecord {ContentItemRecord = context.ContentItemRecord};
_repository.Create(instance.Record);
}
}
}
}

View File

@@ -0,0 +1,36 @@
namespace Orchard.ContentManagement.Handlers {
public abstract class StorageFilterBase<TPart> : IContentStorageFilter where TPart : class, IContent {
protected virtual void Activated(ActivatedContentContext context, TPart instance) { }
protected virtual void Creating(CreateContentContext context, TPart instance) { }
protected virtual void Created(CreateContentContext context, TPart instance) { }
protected virtual void Loading(LoadContentContext context, TPart instance) { }
protected virtual void Loaded(LoadContentContext context, TPart instance) { }
void IContentStorageFilter.Activated(ActivatedContentContext context) {
if (context.ContentItem.Is<TPart>())
Activated(context, context.ContentItem.As<TPart>());
}
void IContentStorageFilter.Creating(CreateContentContext context) {
if (context.ContentItem.Is<TPart>())
Creating(context, context.ContentItem.As<TPart>());
}
void IContentStorageFilter.Created(CreateContentContext context) {
if (context.ContentItem.Is<TPart>())
Created(context, context.ContentItem.As<TPart>());
}
void IContentStorageFilter.Loading(LoadContentContext context) {
if (context.ContentItem.Is<TPart>())
Loading(context, context.ContentItem.As<TPart>());
}
void IContentStorageFilter.Loaded(LoadContentContext context) {
if (context.ContentItem.Is<TPart>())
Loaded(context, context.ContentItem.As<TPart>());
}
}
}

View File

@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Orchard.ContentManagement.Handlers {
public abstract class TemplateFilterBase<TPart> : IContentTemplateFilter where TPart : class, IContent {
protected virtual void GetItemMetadata(GetItemMetadataContext context, TPart instance) { }
protected virtual void BuildDisplayModel(BuildDisplayModelContext context, TPart instance) { }
protected virtual void BuildEditorModel(BuildEditorModelContext context, TPart instance) { }
protected virtual void UpdateEditorModel(UpdateEditorModelContext context, TPart instance) { }
void IContentTemplateFilter.GetItemMetadata(GetItemMetadataContext context) {
if (context.ContentItem.Is<TPart>())
GetItemMetadata(context, context.ContentItem.As<TPart>());
}
void IContentTemplateFilter.BuildDisplayModel(BuildDisplayModelContext context) {
if (context.ContentItem.Is<TPart>())
BuildDisplayModel(context, context.ContentItem.As<TPart>());
}
void IContentTemplateFilter.BuildEditorModel(BuildEditorModelContext context) {
if (context.ContentItem.Is<TPart>())
BuildEditorModel(context, context.ContentItem.As<TPart>());
}
void IContentTemplateFilter.UpdateEditorModel(UpdateEditorModelContext context) {
if (context.ContentItem.Is<TPart>())
UpdateEditorModel(context, context.ContentItem.As<TPart>());
}
}
}

View File

@@ -0,0 +1,23 @@
using Orchard.ContentManagement.Records;
using Orchard.ContentManagement.ViewModels;
namespace Orchard.ContentManagement.Handlers {
public class TemplateFilterForRecord<TRecord> : TemplateFilterBase<ContentPart<TRecord>> where TRecord : ContentPartRecord, new() {
private readonly string _prefix;
private readonly string _templateName;
public TemplateFilterForRecord(string prefix, string templateName) {
_prefix = prefix;
_templateName = templateName;
}
protected override void BuildEditorModel(BuildEditorModelContext context, ContentPart<TRecord> part) {
context.AddEditor(new TemplateViewModel(part.Record, _prefix) { TemplateName = _templateName });
}
protected override void UpdateEditorModel(UpdateEditorModelContext context, ContentPart<TRecord> part) {
context.Updater.TryUpdateModel(part.Record, _prefix, null, null);
context.AddEditor(new TemplateViewModel(part.Record, _prefix) { TemplateName = _templateName });
}
}
}

View File

@@ -0,0 +1,12 @@
using Orchard.ContentManagement.ViewModels;
namespace Orchard.ContentManagement.Handlers {
public class UpdateEditorModelContext : BuildEditorModelContext {
public UpdateEditorModelContext(ItemEditorModel editorModel, IUpdateModel updater)
: base(editorModel) {
Updater = updater;
}
public IUpdateModel Updater { get; private set; }
}
}

View File

@@ -0,0 +1,5 @@
namespace Orchard.ContentManagement {
public interface IContent {
ContentItem ContentItem { get; }
}
}

View File

@@ -0,0 +1,9 @@
using System.Web.Routing;
namespace Orchard.ContentManagement {
//public interface IContentDisplayInfo : IContent {
// string DisplayText { get; }
// RouteValueDictionary DisplayRouteValues();
// RouteValueDictionary EditRouteValues();
//}
}

View File

@@ -0,0 +1,22 @@
using System.Collections.Generic;
using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.ViewModels;
namespace Orchard.ContentManagement {
public interface IContentManager : IDependency {
IEnumerable<ContentType> GetContentTypes();
ContentItem New(string contentType);
void Create(ContentItem contentItem);
ContentItem Get(int id);
IContentQuery<ContentItem> Query();
ContentItemMetadata GetItemMetadata(IContent contentItem);
ItemDisplayModel<TContent> BuildDisplayModel<TContent>(TContent content, string displayType) where TContent : IContent;
ItemEditorModel<TContent> BuildEditorModel<TContent>(TContent content) where TContent : IContent;
ItemEditorModel<TContent> UpdateEditorModel<TContent>(TContent content, IUpdateModel updater) where TContent : IContent;
}
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using Orchard.ContentManagement.Records;
namespace Orchard.ContentManagement {
public interface IContentQuery {
IContentManager ContentManager { get; }
IContentQuery<TPart> ForPart<TPart>() where TPart : IContent;
}
public interface IContentQuery<TPart> : IContentQuery where TPart : IContent {
IContentQuery<TPart> ForType(params string[] contentTypes);
IEnumerable<TPart> List();
IEnumerable<TPart> Slice(int skip, int count);
IContentQuery<TPart, TRecord> Join<TRecord>() where TRecord : ContentPartRecord;
IContentQuery<TPart, TRecord> Where<TRecord>(Expression<Func<TRecord, bool>> predicate) where TRecord : ContentPartRecord;
IContentQuery<TPart, TRecord> OrderBy<TRecord, TKey>(Expression<Func<TRecord, TKey>> keySelector) where TRecord : ContentPartRecord;
IContentQuery<TPart, TRecord> OrderByDescending<TRecord, TKey>(Expression<Func<TRecord, TKey>> keySelector) where TRecord : ContentPartRecord;
}
public interface IContentQuery<TPart, TRecord> : IContentQuery<TPart> where TPart : IContent where TRecord : ContentPartRecord {
IContentQuery<TPart, TRecord> Where(Expression<Func<TRecord, bool>> predicate);
IContentQuery<TPart, TRecord> OrderBy<TKey>(Expression<Func<TRecord, TKey>> keySelector);
IContentQuery<TPart, TRecord> OrderByDescending<TKey>(Expression<Func<TRecord, TKey>> keySelector);
}
}

View File

@@ -0,0 +1,8 @@
using Orchard.Localization;
namespace Orchard.ContentManagement {
public interface IUpdateModel {
bool TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) where TModel : class;
void AddModelError(string key, LocalizedString errorMessage);
}
}

View File

@@ -0,0 +1,177 @@
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.ViewModels;
using Orchard.Logging;
namespace Orchard.ContentManagement {
public interface IPartDriver : IEvents {
DriverResult BuildDisplayModel(BuildDisplayModelContext context);
DriverResult BuildEditorModel(BuildEditorModelContext context);
DriverResult UpdateEditorModel(UpdateEditorModelContext context);
}
public abstract class PartDriver<TPart> : IPartDriver where TPart : class, IContent {
DriverResult IPartDriver.BuildDisplayModel(BuildDisplayModelContext context) {
var part = context.ContentItem.As<TPart>();
return part == null ? null : Display(part, context.DisplayType);
}
DriverResult IPartDriver.BuildEditorModel(BuildEditorModelContext context) {
var part = context.ContentItem.As<TPart>();
return part == null ? null : Editor(part);
}
DriverResult IPartDriver.UpdateEditorModel(UpdateEditorModelContext context) {
var part = context.ContentItem.As<TPart>();
return part == null ? null : Editor(part, context.Updater);
}
protected virtual DriverResult Display(TPart part, string displayType) {
return null;
}
protected virtual DriverResult Editor(TPart part) {
return null;
}
protected virtual DriverResult Editor(TPart part, IUpdateModel updater) {
return null;
}
protected virtual string Prefix { get { return ""; } }
protected virtual string Zone { get { return "body"; } }
public TemplateResult PartialView(object model) {
return new TemplateResult(model, null, Prefix).Location(Zone);
}
public TemplateResult PartialView(object model, string template) {
return new TemplateResult(model, template, Prefix).Location(Zone);
}
public TemplateResult PartialView(object model, string template, string prefix) {
return new TemplateResult(model, template, prefix).Location(Zone);
}
}
public abstract class AutomaticPartDriver<TPart> : PartDriver<TPart> where TPart : class, IContent {
protected override string Prefix {
get {
return (typeof (TPart).Name);
}
}
protected override DriverResult Display(TPart part, string displayType) {
return PartialView(part);
}
protected override DriverResult Editor(TPart part) {
return PartialView(part);
}
protected override DriverResult Editor(TPart part, IUpdateModel updater) {
updater.TryUpdateModel(part, Prefix, null, null);
return PartialView(part);
}
}
public class DriverResult {
public virtual void Apply(BuildDisplayModelContext context) { }
public virtual void Apply(BuildEditorModelContext context) { }
}
public class TemplateResult : DriverResult {
public object Model { get; set; }
public string TemplateName { get; set; }
public string Prefix { get; set; }
public string Zone { get; set; }
public string Position { get; set; }
public TemplateResult(object model, string templateName, string prefix) {
Model = model;
TemplateName = templateName;
Prefix = prefix;
}
public override void Apply(BuildDisplayModelContext context) {
context.AddDisplay(new TemplateViewModel(Model, Prefix) {
TemplateName = TemplateName,
ZoneName = Zone,
Position = Position
});
}
public override void Apply(BuildEditorModelContext context) {
context.AddEditor(new TemplateViewModel(Model, Prefix) {
TemplateName = TemplateName,
ZoneName = Zone,
Position = Position
});
}
public TemplateResult Location(string zone) {
Zone = zone;
return this;
}
public TemplateResult Location(string zone, string position) {
Zone = zone;
Position = position;
return this;
}
}
[UsedImplicitly]
public class PartDriverHandler : IContentHandler {
private readonly IEnumerable<IPartDriver> _drivers;
public PartDriverHandler(IEnumerable<IPartDriver> drivers) {
_drivers = drivers;
Logger = NullLogger.Instance;
}
public ILogger Logger { get; set; }
System.Collections.Generic.IEnumerable<ContentType> IContentHandler.GetContentTypes() {
return Enumerable.Empty<ContentType>();
}
void IContentHandler.Activating(ActivatingContentContext context) { }
void IContentHandler.Activated(ActivatedContentContext context) { }
void IContentHandler.Creating(CreateContentContext context) { }
void IContentHandler.Created(CreateContentContext context) { }
void IContentHandler.Loading(LoadContentContext context) { }
void IContentHandler.Loaded(LoadContentContext context) { }
void IContentHandler.GetItemMetadata(GetItemMetadataContext context) { }
void IContentHandler.BuildDisplayModel(BuildDisplayModelContext context) {
_drivers.Invoke(driver => {
var result = driver.BuildDisplayModel(context);
if (result != null)
result.Apply(context);
}, Logger);
}
void IContentHandler.BuildEditorModel(BuildEditorModelContext context) {
_drivers.Invoke(driver => {
var result = driver.BuildEditorModel(context);
if (result != null)
result.Apply(context);
}, Logger);
}
void IContentHandler.UpdateEditorModel(UpdateEditorModelContext context) {
_drivers.Invoke(driver => {
var result = driver.UpdateEditorModel(context);
if (result != null)
result.Apply(context);
}, Logger);
}
}
}

View File

@@ -0,0 +1,6 @@
namespace Orchard.ContentManagement.Records {
public class ContentItemRecord {
public virtual int Id { get; set; }
public virtual ContentTypeRecord ContentType { get; set; }
}
}

View File

@@ -0,0 +1,127 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using FluentNHibernate.Automapping;
using FluentNHibernate.Automapping.Alterations;
namespace Orchard.ContentManagement.Records {
class ContentItemRecordAlteration : IAutoMappingAlteration {
private readonly IEnumerable<Type> _recordTypes;
public ContentItemRecordAlteration() {
_recordTypes = Enumerable.Empty<Type>();
}
public ContentItemRecordAlteration(IEnumerable<Type> recordTypes) {
_recordTypes = recordTypes;
}
public void Alter(AutoPersistenceModel model) {
model.Override<ContentItemRecord>(mapping => {
foreach (var recordType in _recordTypes.Where(x => x.IsSubclassOf(typeof(ContentPartRecord)))) {
var type = typeof(Alteration<>).MakeGenericType(recordType);
var alteration = (IAlteration)Activator.CreateInstance(type);
alteration.Override(mapping);
}
});
}
interface IAlteration {
void Override(AutoMapping<ContentItemRecord> mapping);
}
class Alteration<TPartRecord> : IAlteration where TPartRecord : ContentPartRecord {
public void Override(AutoMapping<ContentItemRecord> mapping) {
var name = typeof(TPartRecord).Name;
var syntheticMethod = new DynamicMethod(name, typeof(TPartRecord), null, typeof(ContentItemRecord));
var syntheticProperty = new FakePropertyInfo(syntheticMethod);
var parameter = Expression.Parameter(typeof(ContentItemRecord), "record");
var syntheticExpression = (Expression<Func<ContentItemRecord, TPartRecord>>)Expression.Lambda(
typeof(Func<ContentItemRecord, TPartRecord>),
Expression.Property(parameter, syntheticProperty),
parameter);
mapping.HasOne(syntheticExpression).Access.NoOp().Fetch.Select();
}
private class FakePropertyInfo : PropertyInfo {
private readonly DynamicMethod _getMethod;
public FakePropertyInfo(DynamicMethod dynamicMethod) {
_getMethod = dynamicMethod;
}
public override object[] GetCustomAttributes(bool inherit) {
throw new NotImplementedException();
}
public override bool IsDefined(Type attributeType, bool inherit) {
throw new NotImplementedException();
}
public override object GetValue(object obj, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture) {
throw new NotImplementedException();
}
public override void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture) {
throw new NotImplementedException();
}
public override MethodInfo[] GetAccessors(bool nonPublic) {
throw new NotImplementedException();
}
public override MethodInfo GetGetMethod(bool nonPublic) {
return _getMethod;
}
public override MethodInfo GetSetMethod(bool nonPublic) {
throw new NotImplementedException();
}
public override ParameterInfo[] GetIndexParameters() {
throw new NotImplementedException();
}
public override string Name {
get { return _getMethod.Name; }
}
public override Type DeclaringType {
get { throw new NotImplementedException(); }
}
public override Type ReflectedType {
get { throw new NotImplementedException(); }
}
public override Type PropertyType {
get { return _getMethod.ReturnType; }
}
public override PropertyAttributes Attributes {
get { throw new NotImplementedException(); }
}
public override bool CanRead {
get { return true; }
}
public override bool CanWrite {
get { throw new NotImplementedException(); }
}
public override object[] GetCustomAttributes(Type attributeType, bool inherit) {
throw new NotImplementedException();
}
}
}
}
}

View File

@@ -0,0 +1,6 @@
namespace Orchard.ContentManagement.Records {
public abstract class ContentPartRecord {
public virtual int Id { get; set; }
public virtual ContentItemRecord ContentItemRecord { get; set; }
}
}

View File

@@ -0,0 +1,35 @@
using System;
using System.Linq;
using FluentNHibernate.Automapping;
using FluentNHibernate.Automapping.Alterations;
namespace Orchard.ContentManagement.Records {
public class ContentPartRecordAlteration : IAutoMappingAlteration {
public void Alter(AutoPersistenceModel model) {
model.OverrideAll(mapping => {
var genericArguments = mapping.GetType().GetGenericArguments();
if (!genericArguments.Single().IsSubclassOf(typeof(ContentPartRecord))) {
return;
}
var type = typeof(Alteration<>).MakeGenericType(genericArguments);
var alteration = (IAlteration)Activator.CreateInstance(type);
alteration.Override(mapping);
});
}
interface IAlteration {
void Override(object mapping);
}
class Alteration<T> : IAlteration where T : ContentPartRecord {
public void Override(object mappingObj) {
var mapping = (AutoMapping<T>)mappingObj;
mapping.Id(x => x.Id).GeneratedBy.Foreign("ContentItemRecord");
mapping.HasOne(x => x.ContentItemRecord).Constrained();
}
}
}
}

View File

@@ -0,0 +1,6 @@
namespace Orchard.ContentManagement.Records {
public class ContentTypeRecord {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
}
}

View File

@@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
namespace Orchard.ContentManagement.ViewModels {
public class ItemDisplayModel {
private ContentItem _item;
protected ItemDisplayModel() {
}
protected ItemDisplayModel(ItemDisplayModel displayModel) {
TemplateName = displayModel.TemplateName;
Prefix = displayModel.Prefix;
Displays = displayModel.Displays.ToArray();
Item = displayModel.Item;
}
public ItemDisplayModel(ContentItem item) {
Item = item;
Displays = Enumerable.Empty<TemplateViewModel>();
}
public ContentItem Item {
get { return _item; }
set { SetItem(value); }
}
protected virtual void SetItem(ContentItem value) {
_item = value;
}
public Func<HtmlHelper, ItemDisplayModel, HtmlHelper> Adaptor { get; set; }
public string TemplateName { get; set; }
public string Prefix { get; set; }
public IEnumerable<TemplateViewModel> Displays { get; set; }
}
public class ItemDisplayModel<TPart> : ItemDisplayModel where TPart : IContent {
private TPart _item;
public ItemDisplayModel() {
}
public ItemDisplayModel(ItemDisplayModel displayModel)
: base(displayModel) {
}
public new TPart Item {
get { return _item; }
set { SetItem(value.ContentItem); }
}
protected override void SetItem(ContentItem value) {
_item = value.As<TPart>();
base.SetItem(value);
}
}
}

View File

@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
namespace Orchard.ContentManagement.ViewModels {
public class ItemEditorModel {
private ContentItem _item;
protected ItemEditorModel() {
}
protected ItemEditorModel(ItemEditorModel editorModel) {
TemplateName = editorModel.TemplateName;
Prefix = editorModel.Prefix;
Editors = editorModel.Editors.ToArray();
Item = editorModel.Item;
}
public ContentItem Item {
get { return _item; }
set { SetItem(value); }
}
protected virtual void SetItem(ContentItem value) {
_item = value;
}
public Func<HtmlHelper, ItemEditorModel, HtmlHelper> Adaptor { get; set; }
public string TemplateName { get; set; }
public string Prefix { get; set; }
public IEnumerable<TemplateViewModel> Editors { get; set; }
}
public class ItemEditorModel<TPart> : ItemEditorModel where TPart : IContent {
private TPart _item;
public ItemEditorModel() {
}
public ItemEditorModel(ItemEditorModel editorModel)
: base(editorModel) {
}
public new TPart Item {
get { return _item; }
set { SetItem(value.ContentItem); }
}
protected override void SetItem(ContentItem value) {
_item = value.As<TPart>();
base.SetItem(value);
}
}
}

View File

@@ -0,0 +1,20 @@
namespace Orchard.ContentManagement.ViewModels {
public class TemplateViewModel {
public TemplateViewModel(object model)
: this(model, string.Empty) {
}
public TemplateViewModel(object model, string prefix) {
Model = model;
Prefix = prefix;
}
public object Model { get; set; }
public string Prefix { get; set; }
public string TemplateName { get; set; }
public string ZoneName { get; set; }
public string Position { get; set; }
public bool WasUsed { get; set; }
}
}

View File

@@ -123,6 +123,56 @@
<Compile Include="Validation\Argument.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="ContentManagement\Aspects\ICommonAspect.cs" />
<Compile Include="ContentManagement\ContentExtensions.cs" />
<Compile Include="ContentManagement\ContentItem.cs" />
<Compile Include="ContentManagement\ContentItemMetadata.cs" />
<Compile Include="ContentManagement\ContentModule.cs" />
<Compile Include="ContentManagement\ContentPart.cs" />
<Compile Include="ContentManagement\ContentType.cs" />
<Compile Include="ContentManagement\DefaultContentManager.cs" />
<Compile Include="ContentManagement\DefaultContentQuery.cs" />
<Compile Include="ContentManagement\Drivers\AutomaticPartDriver.cs" />
<Compile Include="ContentManagement\Drivers\CombinedResult.cs" />
<Compile Include="ContentManagement\Drivers\DriverResult.cs" />
<Compile Include="ContentManagement\Drivers\ItemDriver.cs" />
<Compile Include="ContentManagement\Drivers\ItemDriverHandler.cs" />
<Compile Include="ContentManagement\Drivers\PartDriverHandler.cs" />
<Compile Include="ContentManagement\Drivers\TemplateResult.cs" />
<Compile Include="ContentManagement\Handlers\ActivatedContentContext.cs" />
<Compile Include="ContentManagement\Handlers\ActivatingContentContext.cs" />
<Compile Include="ContentManagement\Handlers\ActivatingFilter.cs" />
<Compile Include="ContentManagement\Handlers\BuildDisplayModelContext.cs" />
<Compile Include="ContentManagement\Handlers\BuildEditorModelContext.cs" />
<Compile Include="ContentManagement\Handlers\ContentHandler.cs" />
<Compile Include="ContentManagement\Handlers\ContentItemBuilder.cs" />
<Compile Include="ContentManagement\Handlers\ContentItemTemplates.cs" />
<Compile Include="ContentManagement\Handlers\CreateContentContext.cs" />
<Compile Include="ContentManagement\Handlers\GetItemMetadataContext.cs" />
<Compile Include="ContentManagement\Handlers\IContentActivatingFilter.cs" />
<Compile Include="ContentManagement\Handlers\IContentFilter.cs" />
<Compile Include="ContentManagement\Handlers\IContentHandler.cs" />
<Compile Include="ContentManagement\Handlers\IContentStorageFilter.cs" />
<Compile Include="ContentManagement\Handlers\IContentTemplateFilter.cs" />
<Compile Include="ContentManagement\Handlers\LoadContentContext.cs" />
<Compile Include="ContentManagement\Handlers\StorageFilter.cs" />
<Compile Include="ContentManagement\Handlers\StorageFilterBase.cs" />
<Compile Include="ContentManagement\Handlers\TemplateFilterBase.cs" />
<Compile Include="ContentManagement\Handlers\TemplateFilterForRecord.cs" />
<Compile Include="ContentManagement\Handlers\UpdateEditorModelContext.cs" />
<Compile Include="ContentManagement\IContent.cs" />
<Compile Include="ContentManagement\IContentManager.cs" />
<Compile Include="ContentManagement\IContentQuery.cs" />
<Compile Include="ContentManagement\Drivers\PartDriver.cs" />
<Compile Include="ContentManagement\IUpdateModel.cs" />
<Compile Include="ContentManagement\Records\ContentItemRecord.cs" />
<Compile Include="ContentManagement\Records\ContentItemRecordAlteration.cs" />
<Compile Include="ContentManagement\Records\ContentPartRecord.cs" />
<Compile Include="ContentManagement\Records\ContentPartRecordAlteration.cs" />
<Compile Include="ContentManagement\Records\ContentTypeRecord.cs" />
<Compile Include="ContentManagement\ViewModels\ItemDisplayModel.cs" />
<Compile Include="ContentManagement\ViewModels\ItemEditorModel.cs" />
<Compile Include="ContentManagement\ViewModels\TemplateViewModel.cs" />
<Compile Include="Controllers\AccountController.cs" />
<Compile Include="Controllers\HomeController.cs" />
<Compile Include="Data\Conventions\AttributeCollectionConvention.cs" />
@@ -154,22 +204,6 @@
<Compile Include="Localization\Localizer.cs" />
<Compile Include="Localization\LocalizedString.cs" />
<Compile Include="Localization\NullLocalizer.cs" />
<Compile Include="Models\Aspects\ICommonAspect.cs" />
<Compile Include="Models\ContentItem.cs" />
<Compile Include="Models\ContentItemMetadata.cs" />
<Compile Include="Models\ContentModule.cs" />
<Compile Include="Models\ContentType.cs" />
<Compile Include="Models\DefaultContentQuery.cs" />
<Compile Include="Models\Driver\ActivatedContentContext.cs" />
<Compile Include="Models\Driver\ActivatingFilter.cs" />
<Compile Include="Models\Driver\ContentItemTemplates.cs" />
<Compile Include="Models\Driver\BuildDisplayModelContext.cs" />
<Compile Include="Models\Driver\GetItemMetadataContext.cs" />
<Compile Include="Models\Driver\IContentActivatingFilter.cs" />
<Compile Include="Models\Driver\IContentFilter.cs" />
<Compile Include="Models\Driver\IContentStorageFilter.cs" />
<Compile Include="Models\Driver\IContentTemplateFilter.cs" />
<Compile Include="Models\Driver\IUpdateModel.cs" />
<Compile Include="Environment\ServiceLocator.cs" />
<Compile Include="Logging\CastleLogger.cs" />
<Compile Include="Logging\CastleLoggerFactory.cs" />
@@ -179,34 +213,6 @@
<Compile Include="Logging\LoggingModule.cs" />
<Compile Include="Logging\NullLogger.cs" />
<Compile Include="Logging\NullLoggerFactory.cs" />
<Compile Include="Models\DefaultContentManager.cs" />
<Compile Include="Models\Driver\CreateContentContext.cs" />
<Compile Include="Models\Driver\LoadContentContext.cs" />
<Compile Include="Models\Driver\ContentItemBuilder.cs" />
<Compile Include="Models\Driver\ContentHandler.cs" />
<Compile Include="Models\Driver\ActivatingContentContext.cs" />
<Compile Include="Models\Driver\BuildEditorModelContext.cs" />
<Compile Include="Models\Driver\StorageFilter.cs" />
<Compile Include="Models\Driver\StorageFilterBase.cs" />
<Compile Include="Models\Driver\TemplateFilterBase.cs" />
<Compile Include="Models\Driver\TemplateFilterForRecord.cs" />
<Compile Include="Models\IContentDisplayInfo.cs" />
<Compile Include="Models\IContentManager.cs" />
<Compile Include="Models\Driver\IContentHandler.cs" />
<Compile Include="Models\ContentExtensions.cs" />
<Compile Include="Models\ContentPart.cs" />
<Compile Include="Models\IContent.cs" />
<Compile Include="Models\IContentQuery.cs" />
<Compile Include="Models\PartDriver.cs" />
<Compile Include="Models\Records\ContentItemRecordAlteration.cs" />
<Compile Include="Models\Records\ContentPartRecord.cs" />
<Compile Include="Models\Records\ContentPartRecordAlteration.cs" />
<Compile Include="Models\Records\ContentTypeRecord.cs" />
<Compile Include="Models\Records\ContentItemRecord.cs" />
<Compile Include="Models\Driver\UpdateEditorModelContext.cs" />
<Compile Include="Models\ViewModels\TemplateViewModel.cs" />
<Compile Include="Models\ViewModels\ItemDisplayModel.cs" />
<Compile Include="Models\ViewModels\ItemEditorModel.cs" />
<Compile Include="Mvc\Filters\AntiForgeryAuthorizationFilter.cs" />
<Compile Include="Mvc\Html\ContainerExtensions.cs" />
<Compile Include="Mvc\Html\ContentItemExtensions.cs" />
@@ -295,7 +301,7 @@
<Compile Include="IMapper.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Models\Diagram.cd" />
<None Include="ContentManagement\Diagram.cd" />
</ItemGroup>
<ItemGroup>
<Folder Include="UI\Models\" />