mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Added unique zone name validation.
This commit is contained in:
@@ -4,6 +4,7 @@ using Orchard.Layouts.Framework.Drivers;
|
||||
|
||||
namespace Orchard.Layouts.Drivers {
|
||||
public class ColumnElementDriver : ElementDriver<Column> {
|
||||
|
||||
protected override void OnDisplaying(Column element, ElementDisplayingContext context) {
|
||||
context.ElementShape.Width = element.Width;
|
||||
context.ElementShape.Offset = element.Offset;
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Orchard.Layouts.Models {
|
||||
public interface ILayoutAspect : IContent {
|
||||
int? TemplateId { get; set; }
|
||||
string LayoutData { get; set; }
|
||||
}
|
||||
}
|
@@ -60,5 +60,10 @@ namespace Orchard.Layouts.Services {
|
||||
/// Collects all zones as defined in all layouts in the system.
|
||||
/// </summary>
|
||||
IEnumerable<string> GetZones();
|
||||
|
||||
/// <summary>
|
||||
/// Recursively collects all zones of the specified layout and of its selected template, if any.
|
||||
/// </summary>
|
||||
IEnumerable<string> GetZones(ILayoutAspect layout);
|
||||
}
|
||||
}
|
@@ -10,6 +10,7 @@ using Orchard.Layouts.Framework.Elements;
|
||||
using Orchard.Layouts.Helpers;
|
||||
using Orchard.Layouts.Models;
|
||||
using Orchard.Layouts.Settings;
|
||||
using Orchard.Validation;
|
||||
|
||||
namespace Orchard.Layouts.Services {
|
||||
public class LayoutManager : ILayoutManager {
|
||||
@@ -84,19 +85,32 @@ namespace Orchard.Layouts.Services {
|
||||
|
||||
public IEnumerable<string> GetZones() {
|
||||
return _cacheManager.Get("LayoutZones", context => {
|
||||
var layouts = GetLayouts().ToList();
|
||||
var zoneNames = new HashSet<string>();
|
||||
context.Monitor(_signals.When(Signals.LayoutZones));
|
||||
return GetZones(GetLayouts());
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var layoutPart in layouts) {
|
||||
var elements = LoadElements(layoutPart).Flatten();
|
||||
var columns = elements.Where(x => x is Column).Cast<Column>().Where(x => !String.IsNullOrWhiteSpace(x.ZoneName)).ToList();
|
||||
public IEnumerable<string> GetZones(ILayoutAspect layout) {
|
||||
Argument.ThrowIfNull(layout, "layout");
|
||||
|
||||
foreach (var column in columns)
|
||||
zoneNames.Add(column.ZoneName);
|
||||
var key = String.Format("LayoutZones-{0}", layout.Id);
|
||||
return _cacheManager.Get(key, context => {
|
||||
context.Monitor(_signals.When(Signals.LayoutZones));
|
||||
|
||||
var layouts = new List<ILayoutAspect>();
|
||||
var currentTemplate = layout.TemplateId != null ? GetLayout(layout.TemplateId.Value) : default(LayoutPart);
|
||||
|
||||
// Add the layout itself to the chain of layouts to harvest zones from.
|
||||
layouts.Add(layout);
|
||||
|
||||
// Walk up the chain of templates and collect each one for zone harvesting.
|
||||
while (currentTemplate != null) {
|
||||
layouts.Add(currentTemplate);
|
||||
currentTemplate = currentTemplate.TemplateId != null ? GetLayout(currentTemplate.TemplateId.Value) : default(LayoutPart);
|
||||
}
|
||||
|
||||
context.Monitor(_signals.When(Signals.LayoutZones));
|
||||
return zoneNames;
|
||||
// Harvest the zones from the chain of layouts.
|
||||
return GetZones(layouts);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -199,5 +213,19 @@ namespace Orchard.Layouts.Services {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<string> GetZones(IEnumerable<ILayoutAspect> layouts) {
|
||||
var zoneNames = new HashSet<string>();
|
||||
|
||||
foreach (var layoutPart in layouts) {
|
||||
var elements = LoadElements(layoutPart).Flatten();
|
||||
var columns = elements.Where(x => x is Column).Cast<Column>().Where(x => !String.IsNullOrWhiteSpace(x.ZoneName)).ToList();
|
||||
|
||||
foreach (var column in columns)
|
||||
zoneNames.Add(column.ZoneName);
|
||||
}
|
||||
|
||||
return zoneNames.OrderBy(x => x);
|
||||
}
|
||||
}
|
||||
}
|
@@ -4,10 +4,11 @@ using System.Linq;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Aspects;
|
||||
using Orchard.Core.Settings.Models;
|
||||
using Orchard.Core.Shapes;
|
||||
using Orchard.Layouts.Elements;
|
||||
using Orchard.Layouts.Framework.Display;
|
||||
using Orchard.Layouts.Framework.Drivers;
|
||||
using Orchard.Layouts.Framework.Elements;
|
||||
using Orchard.Layouts.Helpers;
|
||||
using Orchard.Logging;
|
||||
using Orchard.Widgets.Models;
|
||||
using Orchard.Widgets.Services;
|
||||
@@ -24,10 +25,37 @@ namespace Orchard.Widgets.Drivers {
|
||||
_widgetsService = widgetsService;
|
||||
}
|
||||
|
||||
protected override void OnLayoutSaving(Column element, ElementSavingContext context) {
|
||||
ValidateZoneName(element, context);
|
||||
}
|
||||
|
||||
protected override void OnDisplaying(Column element, ElementDisplayingContext context) {
|
||||
RenderWidgets(element, context);
|
||||
}
|
||||
|
||||
private void ValidateZoneName(Column element, ElementSavingContext context) {
|
||||
if (String.IsNullOrWhiteSpace(element.ZoneName))
|
||||
return; // Nothing to validate.
|
||||
|
||||
if (element.IsTemplated)
|
||||
return; // No need to validate templated columns.
|
||||
|
||||
var blacklist = new HashSet<string>();
|
||||
|
||||
// Add theme zones to the blacklist.
|
||||
var themeZones = _widgetsService.GetZones();
|
||||
Add(blacklist, themeZones);
|
||||
|
||||
// Add any zones from the current layout (except the zone name of the current column) to the blacklist.
|
||||
var siblingColumns = context.Elements.Flatten().Where(x => x is Column && x != element).Cast<Column>().ToList();
|
||||
var siblingZones = siblingColumns.Where(x => !String.IsNullOrWhiteSpace(x.ZoneName)).Select(x => x.ZoneName);
|
||||
Add(blacklist, siblingZones);
|
||||
|
||||
// Check if the specified zone is blacklisted.
|
||||
if (blacklist.Contains(element.ZoneName))
|
||||
context.Updater.AddModelError("ZoneName", T("The zone name '{0}' is already in use.", element.ZoneName));
|
||||
}
|
||||
|
||||
private void RenderWidgets(Column element, ElementDisplayingContext context) {
|
||||
var zoneName = element.ZoneName;
|
||||
|
||||
@@ -59,22 +87,22 @@ namespace Orchard.Widgets.Drivers {
|
||||
continue;
|
||||
}
|
||||
|
||||
// ignore widget for different cultures
|
||||
// Ignore widget for different cultures,
|
||||
var localizablePart = widgetPart.As<ILocalizableAspect>();
|
||||
if (localizablePart != null) {
|
||||
// if localized culture is null then show if current culture is the default
|
||||
// this allows a user to show a content item for the default culture only
|
||||
// If localized culture is null then show if current culture is the default
|
||||
// this allows a user to show a content item for the default culture only.
|
||||
if (localizablePart.Culture == null && defaultCulture != currentCulture) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if culture is set, show only if current culture is the same
|
||||
// If culture is set, show only if current culture is the same.
|
||||
if (localizablePart.Culture != null && localizablePart.Culture != currentCulture) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// check permissions
|
||||
// Check permissions.
|
||||
if (!_orchardServices.Authorizer.Authorize(Core.Contents.Permissions.ViewContent, widgetPart)) {
|
||||
continue;
|
||||
}
|
||||
@@ -84,5 +112,11 @@ namespace Orchard.Widgets.Drivers {
|
||||
context.ElementShape.Add(widgetShape, widgetPart.Position);
|
||||
}
|
||||
}
|
||||
|
||||
private static void Add(ISet<string> set, IEnumerable<string> zones) {
|
||||
foreach (var zone in zones) {
|
||||
set.Add(zone);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user