diff --git a/src/Orchard.Web/Modules/Orchard.Templates/Drivers/ShapePartDriver.cs b/src/Orchard.Web/Modules/Orchard.Templates/Drivers/ShapePartDriver.cs index 4504ef767..ff9f5d331 100644 --- a/src/Orchard.Web/Modules/Orchard.Templates/Drivers/ShapePartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Templates/Drivers/ShapePartDriver.cs @@ -11,35 +11,45 @@ using Orchard.Templates.Models; using Orchard.Templates.Services; using Orchard.Templates.ViewModels; using Orchard.Utility.Extensions; +using Orchard.Core.Title.Models; namespace Orchard.Templates.Drivers { public class ShapePartDriver : ContentPartDriver { private readonly IEnumerable _processors; private readonly ITransactionManager _transactions; + private readonly IContentManager _contentManager; public ShapePartDriver( IEnumerable processors, - ITransactionManager transactions) { + ITransactionManager transactions, + IContentManager contentManager) { _processors = processors; _transactions = transactions; + _contentManager = contentManager; T = NullLocalizer.Instance; } Localizer T { get; set; } + protected override DriverResult Display(ShapePart part, string displayType, dynamic shapeHelper) { + return ContentShape("Parts_Shape_SummaryAdmin", () => shapeHelper.Parts_Shape_SummaryAdmin()); + } + protected override DriverResult Editor(ShapePart part, dynamic shapeHelper) { return Editor(part, null, shapeHelper); } protected override DriverResult Editor(ShapePart part, IUpdateModel updater, dynamic shapeHelper) { var viewModel = new ShapePartViewModel { - Template = part.Template + Template = part.Template, + RenderingMode = part.RenderingMode }; if (updater != null && updater.TryUpdateModel(viewModel, Prefix, null, new[] { "AvailableLanguages" }) && ValidateShapeName(part, updater)) { part.Template = viewModel.Template; + part.RenderingMode = viewModel.RenderingMode; try { var processor = _processors.FirstOrDefault(x => String.Equals(x.Type, part.ProcessorName, StringComparison.OrdinalIgnoreCase)) ?? _processors.First(); @@ -49,6 +59,24 @@ namespace Orchard.Templates.Drivers { updater.AddModelError("", T("Template processing error: {0}", ex.Message)); _transactions.Cancel(); } + + // We need to query for the content type names because querying for content parts has no effect on the database side. + var contentTypesWithShapePart = _contentManager + .GetContentTypeDefinitions() + .Where(typeDefinition => typeDefinition.Parts.Any(partDefinition => partDefinition.PartDefinition.Name == "ShapePart")) + .Select(typeDefinition => typeDefinition.Name); + + // If ShapePart is only dynamically added to this content type or even this content item then we won't find + // a corresponding content type definition, so using the current content type too. + contentTypesWithShapePart = contentTypesWithShapePart.Union(new[] { part.ContentItem.ContentType }); + + var existingShapes = _contentManager + .Query(VersionOptions.Latest, contentTypesWithShapePart.ToArray()) + .Where(record => record.Title == part.As< TitlePart>().Title && record.ContentItemRecord.Id != part.ContentItem.Id); + + if (existingShapes.List().Any(x => x.As().RenderingMode == part.RenderingMode)) { + updater.AddModelError("ShapeNameAlreadyExists", T("A template with the given name and rendering mode already exists.")); + } } return ContentShape("Parts_Shape_Edit", () => shapeHelper.EditorTemplate(TemplateName: "Parts.Shape", Model: viewModel, Prefix: Prefix)); } diff --git a/src/Orchard.Web/Modules/Orchard.Templates/Drivers/TitlePartDriver.cs b/src/Orchard.Web/Modules/Orchard.Templates/Drivers/TitlePartDriver.cs deleted file mode 100644 index 2a7b6c37c..000000000 --- a/src/Orchard.Web/Modules/Orchard.Templates/Drivers/TitlePartDriver.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Orchard.ContentManagement; -using Orchard.ContentManagement.Drivers; -using Orchard.Core.Title.Models; -using Orchard.Localization; -using Orchard.Templates.Models; -using System.Linq; - -namespace Orchard.Templates.Drivers { - public class TitlePartDriver : ContentPartDriver { - private readonly IContentManager _contentManager; - - public Localizer T { get; set; } - - public TitlePartDriver(IContentManager contentManager) { - _contentManager = contentManager; - - T = NullLocalizer.Instance; - } - - protected override DriverResult Editor(TitlePart part, IUpdateModel updater, dynamic shapeHelper) { - if (!part.ContentItem.Has()) { - return null; - } - - updater.TryUpdateModel(part, Prefix, null, null); - - // We need to query for the content type names because querying for content parts has no effect on the database side. - var contentTypesWithShapePart = _contentManager - .GetContentTypeDefinitions() - .Where(typeDefinition => typeDefinition.Parts.Any(partDefinition => partDefinition.PartDefinition.Name == "ShapePart")) - .Select(typeDefinition => typeDefinition.Name); - - // If ShapePart is only dynamically added to this content type or even this content item then we won't find - // a corresponding content type definition, so using the current content type too. - contentTypesWithShapePart = contentTypesWithShapePart.Union(new[] { part.ContentItem.ContentType }); - - var existingShapeCount = _contentManager - .Query(VersionOptions.Latest, contentTypesWithShapePart.ToArray()) - .Where(record => record.Title == part.Title && record.ContentItemRecord.Id != part.ContentItem.Id) - .Count(); - - if (existingShapeCount > 0) { - updater.AddModelError("ShapeNameAlreadyExists", T("A template with the given name already exists.")); - } - - return null; - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Templates/Models/ShapePart.cs b/src/Orchard.Web/Modules/Orchard.Templates/Models/ShapePart.cs index 668b86878..1680223ad 100644 --- a/src/Orchard.Web/Modules/Orchard.Templates/Models/ShapePart.cs +++ b/src/Orchard.Web/Modules/Orchard.Templates/Models/ShapePart.cs @@ -16,5 +16,16 @@ namespace Orchard.Templates.Models { get { return this.Retrieve(x => x.Template); } set { this.Store(x => x.Template, value); } } + + public RenderingMode RenderingMode { + get { return this.Retrieve(x => x.RenderingMode); } + set { this.Store(x => x.RenderingMode, value); } + } + } + + public enum RenderingMode { + FrontEndAndAdmin, + FrontEnd, + Admin } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Templates/Orchard.Templates.csproj b/src/Orchard.Web/Modules/Orchard.Templates/Orchard.Templates.csproj index 6b0f6eae8..6d627d3dc 100644 --- a/src/Orchard.Web/Modules/Orchard.Templates/Orchard.Templates.csproj +++ b/src/Orchard.Web/Modules/Orchard.Templates/Orchard.Templates.csproj @@ -180,7 +180,6 @@ - @@ -227,6 +226,9 @@ + + + 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) diff --git a/src/Orchard.Web/Modules/Orchard.Templates/Placement.info b/src/Orchard.Web/Modules/Orchard.Templates/Placement.info index 9e4408cd0..22a0e50b8 100644 --- a/src/Orchard.Web/Modules/Orchard.Templates/Placement.info +++ b/src/Orchard.Web/Modules/Orchard.Templates/Placement.info @@ -1,3 +1,7 @@  - + + + + + \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Templates/Services/TemplateShapeBindingResolver.cs b/src/Orchard.Web/Modules/Orchard.Templates/Services/TemplateShapeBindingResolver.cs index 4fc5eb6a1..d6e851b3e 100644 --- a/src/Orchard.Web/Modules/Orchard.Templates/Services/TemplateShapeBindingResolver.cs +++ b/src/Orchard.Web/Modules/Orchard.Templates/Services/TemplateShapeBindingResolver.cs @@ -10,6 +10,8 @@ using System.Web; using System.Web.Mvc; using Orchard.DisplayManagement; using Orchard.DisplayManagement.Descriptors; +using System.Web.Routing; +using Orchard.UI.Admin; namespace Orchard.Templates.Services { public class TemplateShapeBindingResolver : IShapeBindingResolver { @@ -18,30 +20,50 @@ namespace Orchard.Templates.Services { private IContentManager _contentManager; private IContentDefinitionManager _contentDefinitionManager; private ITemplateService _templateService; + private readonly RequestContext _requestContext; public TemplateShapeBindingResolver( ICacheManager cacheManager, ISignals signals, IContentManager contentManager, IContentDefinitionManager contentDefinitionManager, - ITemplateService templateService - ) { + ITemplateService templateService, + RequestContext requestContext) { _cacheManager = cacheManager; _signals = signals; _contentManager = contentManager; _contentDefinitionManager = contentDefinitionManager; _templateService = templateService; + _requestContext = requestContext; } public bool TryGetDescriptorBinding(string shapeType, out ShapeBinding shapeBinding) { var processors = BuildShapeProcessors(); + var acceptableRenderingModes = new List() { RenderingMode.FrontEndAndAdmin }; + if (AdminFilter.IsApplied(_requestContext)) { + acceptableRenderingModes.Add(RenderingMode.Admin); + } + else { + acceptableRenderingModes.Add(RenderingMode.FrontEnd); + } + + var templateResults = processors[shapeType].Where(template => acceptableRenderingModes.Contains(template.RenderingMode)); TemplateResult templateResult = null; - if (processors.TryGetValue(shapeType, out templateResult)) { + var templateResultsCount = templateResults.Count(); + if (templateResultsCount == 1) { + templateResult = templateResults.FirstOrDefault(); + } + else if (templateResultsCount > 1) { + // Templates with the same name but specified rendering mode are prioritized. + templateResult = templateResults.FirstOrDefault(template => template.RenderingMode != RenderingMode.FrontEndAndAdmin); + } + + if (templateResult != null) { shapeBinding = new ShapeBinding { BindingName = "Templates", Binding = ctx => CoerceHtmlString(_templateService.Execute( - templateResult.Template, + templateResult.Template, templateResult.Name, templateResult.Processor, ctx.Value)), ShapeDescriptor = new ShapeDescriptor { ShapeType = shapeType } @@ -54,7 +76,7 @@ namespace Orchard.Templates.Services { return false; } - private IDictionary BuildShapeProcessors() { + private ILookup BuildShapeProcessors() { return _cacheManager.Get("Template.ShapeProcessors", true, ctx => { ctx.Monitor(_signals.When(DefaultTemplateService.TemplatesSignal)); @@ -67,11 +89,12 @@ namespace Orchard.Templates.Services { var allTemplates = _contentManager.Query(typesWithShapePart).List(); - return allTemplates.Select(x => new TemplateResult { - Name = x.Name, - Template = x.Template, - Processor = x.ProcessorName - }).ToDictionary(x => x.Name, x => x); + return allTemplates.Select(shapePart => new TemplateResult { + Name = shapePart.Name, + Template = shapePart.Template, + Processor = shapePart.ProcessorName, + RenderingMode = shapePart.RenderingMode + }).ToLookup(template => template.Name); }); } @@ -83,6 +106,7 @@ namespace Orchard.Templates.Services { public string Name { get; set; } public string Processor { get; set; } public string Template { get; set; } + public RenderingMode RenderingMode { get; set; } } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Templates/ViewModels/ShapePartViewModel.cs b/src/Orchard.Web/Modules/Orchard.Templates/ViewModels/ShapePartViewModel.cs index 44b2b22fa..5941eb4ab 100644 --- a/src/Orchard.Web/Modules/Orchard.Templates/ViewModels/ShapePartViewModel.cs +++ b/src/Orchard.Web/Modules/Orchard.Templates/ViewModels/ShapePartViewModel.cs @@ -1,5 +1,9 @@ -namespace Orchard.Templates.ViewModels { +using Orchard.Templates.Models; + +namespace Orchard.Templates.ViewModels { public class ShapePartViewModel { public string Template { get; set; } + + public RenderingMode RenderingMode { get; set; } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Templates/Views/EditorTemplates/Parts.Shape.cshtml b/src/Orchard.Web/Modules/Orchard.Templates/Views/EditorTemplates/Parts.Shape.cshtml index c012491a7..b99be3507 100644 --- a/src/Orchard.Web/Modules/Orchard.Templates/Views/EditorTemplates/Parts.Shape.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Templates/Views/EditorTemplates/Parts.Shape.cshtml @@ -1,4 +1,5 @@ -@model Orchard.Templates.ViewModels.ShapePartViewModel +@using Orchard.Templates.Models +@model Orchard.Templates.ViewModels.ShapePartViewModel @{ Style.Include("~/modules/orchard.templates/scripts/codemirror/lib/codemirror.css"); Style.Include("template-editor.css"); @@ -15,4 +16,8 @@
@Html.TextAreaFor(m => m.Template, new { @class = "text large code-editor" })
+
+ @Html.LabelFor(m => m.RenderingMode, T("Rendering Mode")) + @Html.DropDownListFor(m => m.RenderingMode, Enum.GetValues(typeof(RenderingMode)).Cast().Select(renderingMode => new SelectListItem { Text = renderingMode.ToString(), Value = renderingMode.ToString() })) +
\ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Templates/Views/Parts.Shape.SummaryAdmin.cshtml b/src/Orchard.Web/Modules/Orchard.Templates/Views/Parts.Shape.SummaryAdmin.cshtml new file mode 100644 index 000000000..ad93f7078 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Templates/Views/Parts.Shape.SummaryAdmin.cshtml @@ -0,0 +1 @@ +@T("Rendering mode: {0}", Model.ContentPart.RenderingMode) \ No newline at end of file