mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 11:44:58 +08:00
Roughing in extensibility model for content type definition editor
IEventHandler method invocation will aggregate return values of type IEnumerable<T> Added IContentDefinitionEditorEvents and ContentDefinitionEditorEventsBase to framework assembly ContentTypes editor fires events to build and apply additional type and typepart TemplateViewModel classes As an example, added some content type settings to devtools "ShowDebugLinks" In content type definition builder moved DisplayedAs(name) into it's own method Added Html.RenderTemplates helper to execute renderpartial with prefix directly to bypass (for some cases) Html.EditorXxx, Html.DisplayXxx --HG-- branch : dev
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Autofac;
|
using Autofac;
|
||||||
@@ -28,9 +29,10 @@ namespace Orchard.Tests.Modules.Settings.Blueprint {
|
|||||||
public void Notify_Obsolete(string messageName, IDictionary<string, string> eventData) {
|
public void Notify_Obsolete(string messageName, IDictionary<string, string> eventData) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Notify(string messageName, Dictionary<string, object> eventData) {
|
public IEnumerable Notify(string messageName, Dictionary<string, object> eventData) {
|
||||||
LastMessageName = messageName;
|
LastMessageName = messageName;
|
||||||
LastEventData = eventData;
|
LastEventData = eventData;
|
||||||
|
return new object[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Autofac;
|
using Autofac;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using Orchard.Events;
|
using Orchard.Events;
|
||||||
@@ -13,10 +14,13 @@ namespace Orchard.Tests.Events {
|
|||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Init() {
|
public void Init() {
|
||||||
var builder = new ContainerBuilder();
|
|
||||||
_eventHandler = new StubEventHandler();
|
_eventHandler = new StubEventHandler();
|
||||||
builder.RegisterInstance(_eventHandler).As<IEventHandler>();
|
|
||||||
|
var builder = new ContainerBuilder();
|
||||||
builder.RegisterType<DefaultOrchardEventBus>().As<IEventBus>();
|
builder.RegisterType<DefaultOrchardEventBus>().As<IEventBus>();
|
||||||
|
builder.RegisterType<StubEventHandler2>().As<IEventHandler>();
|
||||||
|
builder.RegisterInstance(_eventHandler).As<IEventHandler>();
|
||||||
|
|
||||||
_container = builder.Build();
|
_container = builder.Build();
|
||||||
_eventBus = _container.Resolve<IEventBus>();
|
_eventBus = _container.Resolve<IEventBus>();
|
||||||
}
|
}
|
||||||
@@ -139,6 +143,25 @@ namespace Orchard.Tests.Events {
|
|||||||
Assert.Throws<ArgumentException>(() => _eventBus.Notify("StubEventHandlerIncrement", new Dictionary<string, object>()));
|
Assert.Throws<ArgumentException>(() => _eventBus.Notify("StubEventHandlerIncrement", new Dictionary<string, object>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void InterceptorCanCoerceResultingCollection() {
|
||||||
|
var data = new object[]{"5","18","2"};
|
||||||
|
var adjusted = EventsInterceptor.Adjust(data, typeof(IEnumerable<string>));
|
||||||
|
Assert.That(data, Is.InstanceOf<IEnumerable<object>>());
|
||||||
|
Assert.That(data, Is.Not.InstanceOf<IEnumerable<string>>());
|
||||||
|
Assert.That(adjusted, Is.InstanceOf<IEnumerable<string>>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void EnumerableResultsAreTreatedLikeSelectMany() {
|
||||||
|
var results = _eventBus.Notify("ITestEventHandler.Gather", new Dictionary<string, object> { { "a", 42 }, { "b", "alpha" } }).Cast<string>();
|
||||||
|
Assert.That(results.Count(), Is.EqualTo(3));
|
||||||
|
Assert.That(results, Has.Some.EqualTo("42"));
|
||||||
|
Assert.That(results, Has.Some.EqualTo("alpha"));
|
||||||
|
Assert.That(results, Has.Some.EqualTo("[42,alpha]"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public interface ITestEventHandler : IEventHandler {
|
public interface ITestEventHandler : IEventHandler {
|
||||||
void Increment();
|
void Increment();
|
||||||
void Sum(int a);
|
void Sum(int a);
|
||||||
@@ -146,6 +169,7 @@ namespace Orchard.Tests.Events {
|
|||||||
void Sum(int a, int b, int c);
|
void Sum(int a, int b, int c);
|
||||||
void Substract(int a, int b);
|
void Substract(int a, int b);
|
||||||
void Concat(string a, string b, string c);
|
void Concat(string a, string b, string c);
|
||||||
|
IEnumerable<string> Gather(int a, string b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class StubEventHandler : ITestEventHandler {
|
public class StubEventHandler : ITestEventHandler {
|
||||||
@@ -162,7 +186,7 @@ namespace Orchard.Tests.Events {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void Sum(int a, int b) {
|
public void Sum(int a, int b) {
|
||||||
Result = 2 * ( a + b );
|
Result = 2 * (a + b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Sum(int a, int b, int c) {
|
public void Sum(int a, int b, int c) {
|
||||||
@@ -176,7 +200,39 @@ namespace Orchard.Tests.Events {
|
|||||||
public void Concat(string a, string b, string c) {
|
public void Concat(string a, string b, string c) {
|
||||||
Summary = a + b + c;
|
Summary = a + b + c;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
public IEnumerable<string> Gather(int a, string b) {
|
||||||
|
yield return String.Format("[{0},{1}]", a, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class StubEventHandler2 : ITestEventHandler {
|
||||||
|
public void Increment() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Sum(int a) {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Sum(int a, int b) {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Sum(int a, int b, int c) {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Substract(int a, int b) {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Concat(string a, string b, string c) {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<string> Gather(int a, string b) {
|
||||||
|
return new[] { a.ToString(), b };
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +0,0 @@
|
|||||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<ContentTypeDefinition.Part>" %>
|
|
||||||
<%@ Import Namespace="Orchard.ContentManagement.MetaData.Models" %>
|
|
||||||
<fieldset>
|
|
||||||
<h3><%:Model.PartDefinition.Name %></h3>
|
|
||||||
<div class="manage add-to-type">
|
|
||||||
<%--// these inline forms can't be here. should probably have some JavaScript in here to build up the forms and add the "remove" link.
|
|
||||||
// get the antiforgery token from the edit type form and mark up the part in a semantic way so I can get some info from the DOM --%>
|
|
||||||
<% using (Html.BeginFormAntiForgeryPost(Url.Action("RemovePart", new { area = "Contents" }), FormMethod.Post, new {@class = "inline link"})) { %>
|
|
||||||
<%=Html.Hidden("name", Model.PartDefinition.Name, new { id = "" }) %>
|
|
||||||
<button type="submit" title="<%:T("Remove") %>"><%:T("Remove") %></button>
|
|
||||||
<% } %>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
@@ -1,7 +1,11 @@
|
|||||||
using System.Linq;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
using Orchard.ContentManagement;
|
using Orchard.ContentManagement;
|
||||||
|
using Orchard.ContentManagement.MetaData;
|
||||||
using Orchard.ContentManagement.MetaData.Models;
|
using Orchard.ContentManagement.MetaData.Models;
|
||||||
|
using Orchard.ContentManagement.ViewModels;
|
||||||
using Orchard.ContentTypes.Services;
|
using Orchard.ContentTypes.Services;
|
||||||
using Orchard.ContentTypes.ViewModels;
|
using Orchard.ContentTypes.ViewModels;
|
||||||
using Orchard.Data;
|
using Orchard.Data;
|
||||||
@@ -14,20 +18,26 @@ namespace Orchard.ContentTypes.Controllers {
|
|||||||
public class AdminController : Controller {
|
public class AdminController : Controller {
|
||||||
private readonly INotifier _notifier;
|
private readonly INotifier _notifier;
|
||||||
private readonly IContentDefinitionService _contentDefinitionService;
|
private readonly IContentDefinitionService _contentDefinitionService;
|
||||||
|
private readonly IContentDefinitionManager _contentDefinitionManager;
|
||||||
private readonly IContentManager _contentManager;
|
private readonly IContentManager _contentManager;
|
||||||
private readonly ITransactionManager _transactionManager;
|
private readonly ITransactionManager _transactionManager;
|
||||||
|
private readonly IContentDefinitionEditorEvents _extendViewModels;
|
||||||
|
|
||||||
public AdminController(
|
public AdminController(
|
||||||
IOrchardServices orchardServices,
|
IOrchardServices orchardServices,
|
||||||
INotifier notifier,
|
INotifier notifier,
|
||||||
IContentDefinitionService contentDefinitionService,
|
IContentDefinitionService contentDefinitionService,
|
||||||
|
IContentDefinitionManager contentDefinitionManager,
|
||||||
IContentManager contentManager,
|
IContentManager contentManager,
|
||||||
ITransactionManager transactionManager) {
|
ITransactionManager transactionManager,
|
||||||
|
IContentDefinitionEditorEvents extendViewModels) {
|
||||||
Services = orchardServices;
|
Services = orchardServices;
|
||||||
_notifier = notifier;
|
_notifier = notifier;
|
||||||
_contentDefinitionService = contentDefinitionService;
|
_contentDefinitionService = contentDefinitionService;
|
||||||
|
_contentDefinitionManager = contentDefinitionManager;
|
||||||
_contentManager = contentManager;
|
_contentManager = contentManager;
|
||||||
_transactionManager = transactionManager;
|
_transactionManager = transactionManager;
|
||||||
|
_extendViewModels = extendViewModels;
|
||||||
T = NullLocalizer.Instance;
|
T = NullLocalizer.Instance;
|
||||||
Logger = NullLogger.Instance;
|
Logger = NullLogger.Instance;
|
||||||
}
|
}
|
||||||
@@ -72,6 +82,19 @@ namespace Orchard.ContentTypes.Controllers {
|
|||||||
return RedirectToAction("Index");
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Updater : IUpdateModel {
|
||||||
|
public AdminController Thunk { get; set; }
|
||||||
|
public Func<string, string> _prefix = x => x;
|
||||||
|
|
||||||
|
public bool TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) where TModel : class {
|
||||||
|
return Thunk.TryUpdateModel(model, _prefix(prefix), includeProperties, excludeProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddModelError(string key, LocalizedString errorMessage) {
|
||||||
|
Thunk.ModelState.AddModelError(_prefix(key), errorMessage.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ActionResult Edit(string id) {
|
public ActionResult Edit(string id) {
|
||||||
if (!Services.Authorizer.Authorize(Permissions.CreateContentTypes, T("Not allowed to edit a content type.")))
|
if (!Services.Authorizer.Authorize(Permissions.CreateContentTypes, T("Not allowed to edit a content type.")))
|
||||||
return new HttpUnauthorizedResult();
|
return new HttpUnauthorizedResult();
|
||||||
@@ -81,7 +104,19 @@ namespace Orchard.ContentTypes.Controllers {
|
|||||||
if (contentTypeDefinition == null)
|
if (contentTypeDefinition == null)
|
||||||
return new NotFoundResult();
|
return new NotFoundResult();
|
||||||
|
|
||||||
return View(new EditTypeViewModel(contentTypeDefinition));
|
var viewModel = new EditTypeViewModel(contentTypeDefinition);
|
||||||
|
viewModel.Parts = viewModel.Parts.ToArray();
|
||||||
|
|
||||||
|
viewModel.Templates = _extendViewModels.TypeEditor(contentTypeDefinition);
|
||||||
|
var entries = viewModel.Parts.Join(contentTypeDefinition.Parts,
|
||||||
|
m => m.PartDefinition.Name,
|
||||||
|
d => d.PartDefinition.Name,
|
||||||
|
(model, definition) => new { model, definition });
|
||||||
|
foreach (var entry in entries) {
|
||||||
|
entry.model.Templates = _extendViewModels.TypePartEditor(entry.definition);
|
||||||
|
}
|
||||||
|
|
||||||
|
return View(viewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost, ActionName("Edit")]
|
[HttpPost, ActionName("Edit")]
|
||||||
@@ -94,26 +129,53 @@ namespace Orchard.ContentTypes.Controllers {
|
|||||||
if (contentTypeDefinition == null)
|
if (contentTypeDefinition == null)
|
||||||
return new NotFoundResult();
|
return new NotFoundResult();
|
||||||
|
|
||||||
|
var updater = new Updater { Thunk = this };
|
||||||
|
|
||||||
var viewModel = new EditTypeViewModel();
|
var viewModel = new EditTypeViewModel();
|
||||||
TryUpdateModel(viewModel);
|
TryUpdateModel(viewModel);
|
||||||
|
|
||||||
if (!ModelState.IsValid)
|
|
||||||
return Edit(id);
|
|
||||||
|
|
||||||
var contentTypeDefinitionParts = viewModel.Parts.Select(GenerateTypePart).ToList();
|
_contentDefinitionManager.AlterTypeDefinition(id, typeBuilder => {
|
||||||
if (viewModel.Fields.Any())
|
|
||||||
contentTypeDefinitionParts.Add(GenerateTypePart(viewModel));
|
|
||||||
|
|
||||||
//todo: apply the changes along the lines of but definately not resembling
|
typeBuilder.DisplayedAs(viewModel.DisplayName);
|
||||||
// for now this _might_ just get a little messy ->
|
|
||||||
_contentDefinitionService.AlterTypeDefinition(
|
// allow extensions to alter type configuration
|
||||||
new ContentTypeDefinition(
|
viewModel.Templates = _extendViewModels.TypeEditorUpdate(typeBuilder, updater);
|
||||||
viewModel.Name,
|
|
||||||
viewModel.DisplayName,
|
foreach (var entry in viewModel.Parts.Select((part, index) => new { part, index })) {
|
||||||
contentTypeDefinitionParts,
|
var partViewModel = entry.part;
|
||||||
viewModel.Settings
|
|
||||||
)
|
// enable updater to be aware of changing part prefix
|
||||||
);
|
var firstHalf = "Parts[" + entry.index + "].";
|
||||||
|
updater._prefix = secondHalf => firstHalf + secondHalf;
|
||||||
|
|
||||||
|
// allow extensions to alter typePart configuration
|
||||||
|
typeBuilder.WithPart(entry.part.PartDefinition.Name, typePartBuilder => {
|
||||||
|
partViewModel.Templates = _extendViewModels.TypePartEditorUpdate(typePartBuilder, updater);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if (!ModelState.IsValid) {
|
||||||
|
_transactionManager.Cancel();
|
||||||
|
return View(viewModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
//var contentTypeDefinitionParts = viewModel.Parts.Select(GenerateTypePart).ToList();
|
||||||
|
//if (viewModel.Fields.Any())
|
||||||
|
// contentTypeDefinitionParts.Add(GenerateTypePart(viewModel));
|
||||||
|
|
||||||
|
////todo: apply the changes along the lines of but definately not resembling
|
||||||
|
//// for now this _might_ just get a little messy ->
|
||||||
|
//_contentDefinitionService.AlterTypeDefinition(
|
||||||
|
// new ContentTypeDefinition(
|
||||||
|
// viewModel.Name,
|
||||||
|
// viewModel.DisplayName,
|
||||||
|
// contentTypeDefinitionParts,
|
||||||
|
// viewModel.Settings
|
||||||
|
// )
|
||||||
|
// );
|
||||||
|
|
||||||
return RedirectToAction("Index");
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
|
@@ -108,6 +108,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="App_Data\" />
|
<Folder Include="App_Data\" />
|
||||||
|
<Folder Include="Helpers\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\..\Orchard\Orchard.Framework.csproj">
|
<ProjectReference Include="..\..\..\Orchard\Orchard.Framework.csproj">
|
||||||
|
@@ -1,12 +1,14 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Orchard.ContentManagement.MetaData.Models;
|
using Orchard.ContentManagement.MetaData.Models;
|
||||||
|
using Orchard.ContentManagement.ViewModels;
|
||||||
using Orchard.Mvc.ViewModels;
|
using Orchard.Mvc.ViewModels;
|
||||||
|
|
||||||
namespace Orchard.ContentTypes.ViewModels {
|
namespace Orchard.ContentTypes.ViewModels {
|
||||||
public class EditTypeViewModel : BaseViewModel {
|
public class EditTypeViewModel : BaseViewModel {
|
||||||
public EditTypeViewModel() {
|
public EditTypeViewModel() {
|
||||||
Settings = new SettingsDictionary();
|
Settings = new SettingsDictionary();
|
||||||
|
Fields = new List<EditPartFieldViewModel>();
|
||||||
Parts = new List<EditTypePartViewModel>();
|
Parts = new List<EditTypePartViewModel>();
|
||||||
}
|
}
|
||||||
public EditTypeViewModel(ContentTypeDefinition contentTypeDefinition) {
|
public EditTypeViewModel(ContentTypeDefinition contentTypeDefinition) {
|
||||||
@@ -19,6 +21,8 @@ namespace Orchard.ContentTypes.ViewModels {
|
|||||||
|
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string DisplayName { get; set; }
|
public string DisplayName { get; set; }
|
||||||
|
public IEnumerable<TemplateViewModel> Templates { get; set; }
|
||||||
|
|
||||||
public SettingsDictionary Settings { get; set; }
|
public SettingsDictionary Settings { get; set; }
|
||||||
public IEnumerable<EditPartFieldViewModel> Fields { get; set; }
|
public IEnumerable<EditPartFieldViewModel> Fields { get; set; }
|
||||||
public IEnumerable<EditTypePartViewModel> Parts { get; set; }
|
public IEnumerable<EditTypePartViewModel> Parts { get; set; }
|
||||||
@@ -47,6 +51,7 @@ namespace Orchard.ContentTypes.ViewModels {
|
|||||||
|
|
||||||
public EditPartViewModel PartDefinition { get; set; }
|
public EditPartViewModel PartDefinition { get; set; }
|
||||||
public SettingsDictionary Settings { get; set; }
|
public SettingsDictionary Settings { get; set; }
|
||||||
|
public IEnumerable<TemplateViewModel> Templates { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class EditPartViewModel : BaseViewModel {
|
public class EditPartViewModel : BaseViewModel {
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.ContentTypes.ViewModels.EditTypeViewModel>" %>
|
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.ContentTypes.ViewModels.EditTypeViewModel>" %>
|
||||||
<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %><%
|
<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %>
|
||||||
|
<%@ Import Namespace="Orchard.ContentTypes.ViewModels" %><%
|
||||||
Html.RegisterStyle("admin.css"); %>
|
Html.RegisterStyle("admin.css"); %>
|
||||||
<h1><%:Html.TitleForPage(T("Edit Content Type").ToString())%></h1>
|
<h1><%:Html.TitleForPage(T("Edit Content Type").ToString())%></h1>
|
||||||
<p class="breadcrumb"><%:Html.ActionLink(T("Content Types").Text, "index") %><%:T(" > ") %><%:T("Edit Content Type") %></p><%
|
<p class="breadcrumb"><%:Html.ActionLink(T("Content Types").Text, "index") %><%:T(" > ") %><%:T("Edit Content Type") %></p><%
|
||||||
@@ -13,7 +14,7 @@ using (Html.BeginFormAntiForgeryPost()) { %>
|
|||||||
<%:Html.TextBoxFor(m => m.Name, new {@class = "textMedium", disabled = "disabled"}) %>
|
<%:Html.TextBoxFor(m => m.Name, new {@class = "textMedium", disabled = "disabled"}) %>
|
||||||
<%:Html.HiddenFor(m => m.Name) %>
|
<%:Html.HiddenFor(m => m.Name) %>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<%:Html.EditorFor(m => m.Settings) %>
|
<% Html.RenderTemplate(Model.Templates); %>
|
||||||
<h2><%:T("Parts") %></h2>
|
<h2><%:T("Parts") %></h2>
|
||||||
<div class="manage add-to-type"><%: Html.ActionLink(T("Add").Text, "AddPart", new { }, new { @class = "button" }) %></div>
|
<div class="manage add-to-type"><%: Html.ActionLink(T("Add").Text, "AddPart", new { }, new { @class = "button" }) %></div>
|
||||||
<%:Html.EditorFor(m => m.Parts, "Parts", "") %>
|
<%:Html.EditorFor(m => m.Parts, "Parts", "") %>
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.ContentTypes.ViewModels.EditTypePartViewModel>" %>
|
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.ContentTypes.ViewModels.EditTypePartViewModel>" %>
|
||||||
<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %>
|
<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %>
|
||||||
|
<%@ Import Namespace="Orchard.ContentTypes.ViewModels" %>
|
||||||
<fieldset class="manage-part">
|
<fieldset class="manage-part">
|
||||||
<h3><%:Model.PartDefinition.Name %></h3>
|
<h3><%:Model.PartDefinition.Name %></h3>
|
||||||
<div class="manage">
|
<div class="manage">
|
||||||
@@ -11,7 +12,8 @@
|
|||||||
<button type="submit" title="<%:T("Remove") %>"><%:T("Remove") %></button>
|
<button type="submit" title="<%:T("Remove") %>"><%:T("Remove") %></button>
|
||||||
<% } %> --%>
|
<% } %> --%>
|
||||||
</div>
|
</div>
|
||||||
<%:Html.EditorFor(m => m.Settings, "Settings", "") %>
|
<% Html.RenderTemplate(Model.Templates); %>
|
||||||
|
|
||||||
<h4><%:T("Global configuration") %></h4>
|
<h4><%:T("Global configuration") %></h4>
|
||||||
<div class="manage minor"><%:Html.ActionLink(T("Edit").Text, "EditPart", new { area = "Orchard.ContentTypes", id = Model.PartDefinition.Name }) %></div>
|
<div class="manage minor"><%:Html.ActionLink(T("Edit").Text, "EditPart", new { area = "Orchard.ContentTypes", id = Model.PartDefinition.Name }) %></div>
|
||||||
<%:Html.DisplayFor(m => m.PartDefinition.Settings, "Settings", "PartDefinition") %>
|
<%:Html.DisplayFor(m => m.PartDefinition.Settings, "Settings", "PartDefinition") %>
|
||||||
|
@@ -7,10 +7,14 @@ namespace Orchard.DevTools.Handlers {
|
|||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
public class DebugLinkHandler : ContentHandler {
|
public class DebugLinkHandler : ContentHandler {
|
||||||
protected override void BuildDisplayModel(BuildDisplayModelContext context) {
|
protected override void BuildDisplayModel(BuildDisplayModelContext context) {
|
||||||
context.AddDisplay(new TemplateViewModel(new ShowDebugLink { ContentItem = context.ContentItem }) { TemplateName="Parts/DevTools.ShowDebugLink", ZoneName = "recap", Position = "9999" });
|
var devToolsSettings = context.ContentItem.TypeDefinition.Settings.GetModel<Settings.DevToolsSettings>();
|
||||||
|
if (devToolsSettings.ShowDebugLinks)
|
||||||
|
context.AddDisplay(new TemplateViewModel(new ShowDebugLink { ContentItem = context.ContentItem }) { TemplateName = "Parts/DevTools.ShowDebugLink", ZoneName = "recap", Position = "9999" });
|
||||||
}
|
}
|
||||||
protected override void BuildEditorModel(BuildEditorModelContext context) {
|
protected override void BuildEditorModel(BuildEditorModelContext context) {
|
||||||
context.AddEditor(new TemplateViewModel(new ShowDebugLink { ContentItem = context.ContentItem }) { TemplateName = "Parts/DevTools.ShowDebugLink", ZoneName = "recap", Position = "9999" });
|
var devToolsSettings = context.ContentItem.TypeDefinition.Settings.GetModel<Settings.DevToolsSettings>();
|
||||||
|
if (devToolsSettings.ShowDebugLinks)
|
||||||
|
context.AddEditor(new TemplateViewModel(new ShowDebugLink { ContentItem = context.ContentItem }) { TemplateName = "Parts/DevTools.ShowDebugLink", ZoneName = "recap", Position = "9999" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -80,6 +80,7 @@
|
|||||||
<Compile Include="Models\Simple.cs" />
|
<Compile Include="Models\Simple.cs" />
|
||||||
<Compile Include="Permissions.cs" />
|
<Compile Include="Permissions.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Settings\DevToolsSettings.cs" />
|
||||||
<Compile Include="ViewModels\ContentIndexViewModel.cs" />
|
<Compile Include="ViewModels\ContentIndexViewModel.cs" />
|
||||||
<Compile Include="ViewModels\ContentDetailsViewModel.cs" />
|
<Compile Include="ViewModels\ContentDetailsViewModel.cs" />
|
||||||
<Compile Include="ViewModels\MetadataIndexViewModel.cs" />
|
<Compile Include="ViewModels\MetadataIndexViewModel.cs" />
|
||||||
@@ -91,6 +92,7 @@
|
|||||||
<Content Include="ScaffoldingTemplates\ModuleCsProj.txt" />
|
<Content Include="ScaffoldingTemplates\ModuleCsProj.txt" />
|
||||||
<Content Include="ScaffoldingTemplates\ModuleManifest.txt" />
|
<Content Include="ScaffoldingTemplates\ModuleManifest.txt" />
|
||||||
<Content Include="ScaffoldingTemplates\ModuleWebConfig.txt" />
|
<Content Include="ScaffoldingTemplates\ModuleWebConfig.txt" />
|
||||||
|
<Content Include="Views\DefinitionTemplates\DevToolsSettings.ascx" />
|
||||||
<Content Include="Views\Home\_RenderableAction.ascx" />
|
<Content Include="Views\Home\_RenderableAction.ascx" />
|
||||||
<Content Include="Views\Home\Simple.aspx" />
|
<Content Include="Views\Home\Simple.aspx" />
|
||||||
<Content Include="Views\Content\Details.aspx" />
|
<Content Include="Views\Content\Details.aspx" />
|
||||||
|
@@ -0,0 +1,30 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Orchard.ContentManagement;
|
||||||
|
using Orchard.ContentManagement.MetaData;
|
||||||
|
using Orchard.ContentManagement.MetaData.Builders;
|
||||||
|
using Orchard.ContentManagement.MetaData.Models;
|
||||||
|
using Orchard.ContentManagement.ViewModels;
|
||||||
|
|
||||||
|
namespace Orchard.DevTools.Settings {
|
||||||
|
|
||||||
|
|
||||||
|
public class DevToolsSettings {
|
||||||
|
public bool ShowDebugLinks { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DevToolsSettingsHooks : ContentDefinitionEditorEventsBase {
|
||||||
|
public override IEnumerable<TemplateViewModel> TypeEditor(ContentTypeDefinition definition) {
|
||||||
|
var model = definition.Settings.GetModel<DevToolsSettings>();
|
||||||
|
yield return DefinitionTemplate(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<TemplateViewModel> TypeEditorUpdate(ContentTypeDefinitionBuilder builder, IUpdateModel updateModel) {
|
||||||
|
var model = new DevToolsSettings();
|
||||||
|
updateModel.TryUpdateModel(model, "DevToolsSettings", null, null);
|
||||||
|
builder
|
||||||
|
.WithSetting("DevToolsSettings.ShowDebugLinks", model.ShowDebugLinks ? true.ToString() : null);
|
||||||
|
|
||||||
|
yield return DefinitionTemplate(model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,6 @@
|
|||||||
|
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Orchard.DevTools.Settings.DevToolsSettings>" %>
|
||||||
|
<fieldset>
|
||||||
|
<%:Html.LabelFor(m=>m.ShowDebugLinks) %>
|
||||||
|
<%:Html.EditorFor(m=>m.ShowDebugLinks) %>
|
||||||
|
<%:Html.ValidationMessageFor(m=>m.ShowDebugLinks) %>
|
||||||
|
</fieldset>
|
@@ -100,7 +100,9 @@
|
|||||||
<Content Include="Default.aspx" />
|
<Content Include="Default.aspx" />
|
||||||
<Content Include="Global.asax" />
|
<Content Include="Global.asax" />
|
||||||
<Content Include="Themes\TheAdmin\Styles\ie.css" />
|
<Content Include="Themes\TheAdmin\Styles\ie.css" />
|
||||||
<Content Include="Web.config" />
|
<Content Include="Web.config">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Orchard\Orchard.Framework.csproj">
|
<ProjectReference Include="..\Orchard\Orchard.Framework.csproj">
|
||||||
|
@@ -40,7 +40,7 @@ namespace Orchard.ContentManagement.MetaData.Builders {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContentTypeDefinitionBuilder DisplayedAs(string displayName ) {
|
public ContentTypeDefinitionBuilder DisplayedAs(string displayName) {
|
||||||
_displayName = displayName;
|
_displayName = displayName;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -84,9 +84,12 @@ namespace Orchard.ContentManagement.MetaData.Builders {
|
|||||||
protected readonly SettingsDictionary _settings;
|
protected readonly SettingsDictionary _settings;
|
||||||
|
|
||||||
protected PartConfigurer(ContentTypeDefinition.Part part) {
|
protected PartConfigurer(ContentTypeDefinition.Part part) {
|
||||||
|
Name = part.PartDefinition.Name;
|
||||||
_settings = new SettingsDictionary(part.Settings.ToDictionary(kv => kv.Key, kv => kv.Value));
|
_settings = new SettingsDictionary(part.Settings.ToDictionary(kv => kv.Key, kv => kv.Value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string Name { get; private set; }
|
||||||
|
|
||||||
public PartConfigurer WithSetting(string name, string value) {
|
public PartConfigurer WithSetting(string name, string value) {
|
||||||
_settings[name] = value;
|
_settings[name] = value;
|
||||||
return this;
|
return this;
|
||||||
|
@@ -0,0 +1,40 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Orchard.ContentManagement.MetaData.Builders;
|
||||||
|
using Orchard.ContentManagement.MetaData.Models;
|
||||||
|
using Orchard.ContentManagement.ViewModels;
|
||||||
|
using Orchard.Events;
|
||||||
|
|
||||||
|
namespace Orchard.ContentManagement.MetaData {
|
||||||
|
public interface IContentDefinitionEditorEvents : IEventHandler {
|
||||||
|
IEnumerable<TemplateViewModel> TypeEditor(ContentTypeDefinition definition);
|
||||||
|
IEnumerable<TemplateViewModel> TypePartEditor(ContentTypeDefinition.Part definition);
|
||||||
|
|
||||||
|
IEnumerable<TemplateViewModel> TypeEditorUpdate(ContentTypeDefinitionBuilder builder, IUpdateModel updateModel);
|
||||||
|
IEnumerable<TemplateViewModel> TypePartEditorUpdate(ContentTypeDefinitionBuilder.PartConfigurer builder, IUpdateModel updateModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class ContentDefinitionEditorEventsBase : IContentDefinitionEditorEvents {
|
||||||
|
public virtual IEnumerable<TemplateViewModel> TypeEditor(ContentTypeDefinition definition) {
|
||||||
|
return Enumerable.Empty<TemplateViewModel>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual IEnumerable<TemplateViewModel> TypePartEditor(ContentTypeDefinition.Part definition) {
|
||||||
|
return Enumerable.Empty<TemplateViewModel>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual IEnumerable<TemplateViewModel> TypeEditorUpdate(ContentTypeDefinitionBuilder builder, IUpdateModel updateModel) {
|
||||||
|
return Enumerable.Empty<TemplateViewModel>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual IEnumerable<TemplateViewModel> TypePartEditorUpdate(ContentTypeDefinitionBuilder.PartConfigurer builder, IUpdateModel updateModel) {
|
||||||
|
return Enumerable.Empty<TemplateViewModel>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static TemplateViewModel DefinitionTemplate<TModel>(TModel model) {
|
||||||
|
return new TemplateViewModel(model, typeof(TModel).Name) {
|
||||||
|
TemplateName = "DefinitionTemplates/" + typeof(TModel).Name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -3,22 +3,22 @@ using System.Web.Mvc;
|
|||||||
|
|
||||||
namespace Orchard.ContentManagement.MetaData.Models {
|
namespace Orchard.ContentManagement.MetaData.Models {
|
||||||
public class SettingsDictionary : Dictionary<string, string> {
|
public class SettingsDictionary : Dictionary<string, string> {
|
||||||
public SettingsDictionary() {}
|
public SettingsDictionary() { }
|
||||||
public SettingsDictionary(IDictionary<string, string> dictionary) : base(dictionary) {}
|
public SettingsDictionary(IDictionary<string, string> dictionary) : base(dictionary) { }
|
||||||
|
|
||||||
public T GetModel<T>() {
|
public T GetModel<T>() where T : class, new() {
|
||||||
return GetModel<T>(null);
|
return GetModel<T>(typeof(T).Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public T GetModel<T>(string key) {
|
public T GetModel<T>(string key) where T : class, new() {
|
||||||
var binder = new DefaultModelBinder();
|
var binder = new DefaultModelBinder();
|
||||||
var controllerContext = new ControllerContext();
|
var controllerContext = new ControllerContext();
|
||||||
var context = new ModelBindingContext {
|
var context = new ModelBindingContext {
|
||||||
ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, typeof (T)),
|
ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, typeof(T)),
|
||||||
ModelName = key,
|
ModelName = key,
|
||||||
ValueProvider = new DictionaryValueProvider<string>(this, null)
|
ValueProvider = new DictionaryValueProvider<string>(this, null)
|
||||||
};
|
};
|
||||||
return (T) binder.BindModel(controllerContext, context);
|
return (T)binder.BindModel(controllerContext, context) ?? new T();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -19,7 +19,7 @@ namespace Orchard.ContentManagement.MetaData.Services {
|
|||||||
if (source == null)
|
if (source == null)
|
||||||
return new XElement("settings");
|
return new XElement("settings");
|
||||||
|
|
||||||
return new XElement("settings", source.Select(kv => new XAttribute(XmlConvert.EncodeLocalName(kv.Key), kv.Value)));
|
return new XElement("settings", source.Where(kv => kv.Value != null).Select(kv => new XAttribute(XmlConvert.EncodeLocalName(kv.Key), kv.Value)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
@@ -18,9 +19,13 @@ namespace Orchard.Events {
|
|||||||
public ILogger Logger { get; set; }
|
public ILogger Logger { get; set; }
|
||||||
public Localizer T { get; set; }
|
public Localizer T { get; set; }
|
||||||
|
|
||||||
#region Implementation of IEventBus
|
|
||||||
|
|
||||||
public void Notify(string messageName, Dictionary<string, object> eventData) {
|
public IEnumerable Notify(string messageName, Dictionary<string, object> eventData) {
|
||||||
|
// call ToArray to ensure evaluation has taken place
|
||||||
|
return NotifyHandlers(messageName, eventData).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<object> NotifyHandlers(string messageName, Dictionary<string, object> eventData) {
|
||||||
string[] parameters = messageName.Split('.');
|
string[] parameters = messageName.Split('.');
|
||||||
if (parameters.Length != 2) {
|
if (parameters.Length != 2) {
|
||||||
throw new ArgumentException(messageName + T(" is not formatted correctly"));
|
throw new ArgumentException(messageName + T(" is not formatted correctly"));
|
||||||
@@ -30,37 +35,58 @@ namespace Orchard.Events {
|
|||||||
|
|
||||||
var eventHandlers = _eventHandlers();
|
var eventHandlers = _eventHandlers();
|
||||||
foreach (var eventHandler in eventHandlers) {
|
foreach (var eventHandler in eventHandlers) {
|
||||||
try {
|
IEnumerable returnValue;
|
||||||
TryInvoke(eventHandler, interfaceName, methodName, eventData);
|
if (TryNotifyHandler(eventHandler, messageName, interfaceName, methodName, eventData, out returnValue)) {
|
||||||
}
|
if (returnValue != null) {
|
||||||
catch(Exception ex) {
|
foreach (var value in returnValue) {
|
||||||
Logger.Error(ex, "{2} thrown from {0} by {1}",
|
yield return value;
|
||||||
messageName,
|
}
|
||||||
eventHandler.GetType().FullName,
|
}
|
||||||
ex.GetType().Name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void TryInvoke(IEventHandler eventHandler, string interfaceName, string methodName, IDictionary<string, object> arguments) {
|
private bool TryNotifyHandler(IEventHandler eventHandler, string messageName, string interfaceName, string methodName, Dictionary<string, object> eventData, out IEnumerable returnValue) {
|
||||||
|
try {
|
||||||
|
return TryInvoke(eventHandler, interfaceName, methodName, eventData, out returnValue);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
Logger.Error(ex, "{2} thrown from {0} by {1}",
|
||||||
|
messageName,
|
||||||
|
eventHandler.GetType().FullName,
|
||||||
|
ex.GetType().Name);
|
||||||
|
|
||||||
|
returnValue = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TryInvoke(IEventHandler eventHandler, string interfaceName, string methodName, IDictionary<string, object> arguments, out IEnumerable returnValue) {
|
||||||
Type type = eventHandler.GetType();
|
Type type = eventHandler.GetType();
|
||||||
foreach (var interfaceType in type.GetInterfaces()) {
|
foreach (var interfaceType in type.GetInterfaces()) {
|
||||||
if (String.Equals(interfaceType.Name, interfaceName, StringComparison.OrdinalIgnoreCase)) {
|
if (String.Equals(interfaceType.Name, interfaceName, StringComparison.OrdinalIgnoreCase)) {
|
||||||
TryInvokeMethod(eventHandler, interfaceType, methodName, arguments);
|
return TryInvokeMethod(eventHandler, interfaceType, methodName, arguments, out returnValue);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
returnValue = null;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void TryInvokeMethod(IEventHandler eventHandler, Type interfaceType, string methodName, IDictionary<string, object> arguments) {
|
private static bool TryInvokeMethod(IEventHandler eventHandler, Type interfaceType, string methodName, IDictionary<string, object> arguments, out IEnumerable returnValue) {
|
||||||
MethodInfo method = GetMatchingMethod(eventHandler, interfaceType, methodName, arguments);
|
MethodInfo method = GetMatchingMethod(eventHandler, interfaceType, methodName, arguments);
|
||||||
if (method != null) {
|
if (method != null) {
|
||||||
List<object> parameters = new List<object>();
|
List<object> parameters = new List<object>();
|
||||||
foreach (var methodParameter in method.GetParameters()) {
|
foreach (var methodParameter in method.GetParameters()) {
|
||||||
parameters.Add(arguments[methodParameter.Name]);
|
parameters.Add(arguments[methodParameter.Name]);
|
||||||
}
|
}
|
||||||
method.Invoke(eventHandler, parameters.ToArray());
|
var result = method.Invoke(eventHandler, parameters.ToArray());
|
||||||
|
returnValue = result as IEnumerable;
|
||||||
|
if (returnValue == null && result != null)
|
||||||
|
returnValue = new[] { result };
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
returnValue = null;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MethodInfo GetMatchingMethod(IEventHandler eventHandler, Type interfaceType, string methodName, IDictionary<string, object> arguments) {
|
private static MethodInfo GetMatchingMethod(IEventHandler eventHandler, Type interfaceType, string methodName, IDictionary<string, object> arguments) {
|
||||||
@@ -89,6 +115,5 @@ namespace Orchard.Events {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,8 @@
|
|||||||
using System.Linq;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using Castle.Core.Interceptor;
|
using Castle.Core.Interceptor;
|
||||||
|
|
||||||
namespace Orchard.Events {
|
namespace Orchard.Events {
|
||||||
@@ -17,7 +21,36 @@ namespace Orchard.Events {
|
|||||||
.Select((parameter, index) => new { parameter.Name, Value = invocation.Arguments[index] })
|
.Select((parameter, index) => new { parameter.Name, Value = invocation.Arguments[index] })
|
||||||
.ToDictionary(kv => kv.Name, kv => kv.Value);
|
.ToDictionary(kv => kv.Name, kv => kv.Value);
|
||||||
|
|
||||||
_eventBus.Notify(interfaceName + "." + methodName, data);
|
var results = _eventBus.Notify(interfaceName + "." + methodName, data);
|
||||||
|
|
||||||
|
invocation.ReturnValue = Adjust(results, invocation.Method.ReturnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static object Adjust(IEnumerable results, Type returnType) {
|
||||||
|
if (returnType == typeof(void) ||
|
||||||
|
results == null ||
|
||||||
|
results.GetType() == returnType) {
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
// acquire method:
|
||||||
|
// static IEnumerable<T> IEnumerable.OfType<T>(this IEnumerable source)
|
||||||
|
// where T is from returnType's IEnumerable<T>
|
||||||
|
var enumerableOfTypeT = typeof(Enumerable).GetGenericMethod("OfType", returnType.GetGenericArguments(), new[] { typeof(IEnumerable) }, typeof(IEnumerable<>));
|
||||||
|
return enumerableOfTypeT.Invoke(null, new[] { results });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Extensions {
|
||||||
|
public static MethodInfo GetGenericMethod(this Type t, string name, Type[] genericArgTypes, Type[] argTypes, Type returnType) {
|
||||||
|
return (from m in t.GetMethods(BindingFlags.Public | BindingFlags.Static)
|
||||||
|
where m.Name == name &&
|
||||||
|
m.GetGenericArguments().Length == genericArgTypes.Length &&
|
||||||
|
m.GetParameters().Select(pi => pi.ParameterType).SequenceEqual(argTypes) &&
|
||||||
|
(m.ReturnType.IsGenericType && !m.ReturnType.IsGenericTypeDefinition ? returnType.GetGenericTypeDefinition() : m.ReturnType) == returnType
|
||||||
|
select m).Single().MakeGenericMethod(genericArgTypes);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Orchard.Events {
|
namespace Orchard.Events {
|
||||||
public interface IEventBus : IDependency {
|
public interface IEventBus : IDependency {
|
||||||
void Notify(string messageName, Dictionary<string, object> eventData);
|
IEnumerable Notify(string messageName, Dictionary<string, object> eventData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
34
src/Orchard/Mvc/Html/TemplateViewModelExtensions.cs
Normal file
34
src/Orchard/Mvc/Html/TemplateViewModelExtensions.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Web.Mvc;
|
||||||
|
using System.Web.Mvc.Html;
|
||||||
|
using Orchard.ContentManagement.ViewModels;
|
||||||
|
|
||||||
|
namespace Orchard.Mvc.Html {
|
||||||
|
public static class TemplateViewModelExtensions {
|
||||||
|
public static void RenderTemplates(this HtmlHelper html, IEnumerable<TemplateViewModel> templates) {
|
||||||
|
if (templates == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var template in templates) {
|
||||||
|
html.RenderTemplates(template);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RenderTemplates(this HtmlHelper html, TemplateViewModel template) {
|
||||||
|
if (template.WasUsed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
template.WasUsed = true;
|
||||||
|
|
||||||
|
var templateInfo = html.ViewContext.ViewData.TemplateInfo;
|
||||||
|
var htmlFieldPrefix = templateInfo.HtmlFieldPrefix;
|
||||||
|
try {
|
||||||
|
templateInfo.HtmlFieldPrefix = templateInfo.GetFullHtmlFieldName(template.Prefix);
|
||||||
|
html.RenderPartial(template.TemplateName, template.Model);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
templateInfo.HtmlFieldPrefix = htmlFieldPrefix;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -310,6 +310,7 @@
|
|||||||
<Compile Include="ContentManagement\MetaData\ContentPartInfo.cs">
|
<Compile Include="ContentManagement\MetaData\ContentPartInfo.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="ContentManagement\MetaData\IContentDefinitionEditorEvents.cs" />
|
||||||
<Compile Include="ContentManagement\MetaData\Models\SettingsDictionary.cs" />
|
<Compile Include="ContentManagement\MetaData\Models\SettingsDictionary.cs" />
|
||||||
<Compile Include="ContentManagement\MetaData\Services\ContentDefinitionWriter.cs" />
|
<Compile Include="ContentManagement\MetaData\Services\ContentDefinitionWriter.cs" />
|
||||||
<Compile Include="ContentManagement\MetaData\IContentDefinitionManager.cs" />
|
<Compile Include="ContentManagement\MetaData\IContentDefinitionManager.cs" />
|
||||||
@@ -445,6 +446,7 @@
|
|||||||
<Compile Include="Localization\Services\IResourceManager.cs" />
|
<Compile Include="Localization\Services\IResourceManager.cs" />
|
||||||
<Compile Include="Localization\Records\CultureRecord.cs" />
|
<Compile Include="Localization\Records\CultureRecord.cs" />
|
||||||
<Compile Include="Localization\Services\SiteCultureSelector.cs" />
|
<Compile Include="Localization\Services\SiteCultureSelector.cs" />
|
||||||
|
<Compile Include="Mvc\Html\TemplateViewModelExtensions.cs" />
|
||||||
<Compile Include="Mvc\Html\ThemeExtensions.cs" />
|
<Compile Include="Mvc\Html\ThemeExtensions.cs" />
|
||||||
<Compile Include="Mvc\Routes\IRoutePublisher.cs" />
|
<Compile Include="Mvc\Routes\IRoutePublisher.cs" />
|
||||||
<Compile Include="Mvc\Routes\IRouteProvider.cs" />
|
<Compile Include="Mvc\Routes\IRouteProvider.cs" />
|
||||||
|
Reference in New Issue
Block a user