mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-21 19:34:40 +08:00
Merge pull request #6314 from OrchardCMS/issue/3537-alias-breadcrumb-linnk
Implementing Alias Breadcrumb Link to be able to add dynamically gene…
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.Core.Navigation.Models;
|
||||
|
||||
namespace Orchard.Core.Navigation.Drivers {
|
||||
public class BreadcrumbMenuItemPartDriver : ContentPartDriver<BreadcrumbMenuItemPart> {
|
||||
}
|
||||
}
|
@@ -11,6 +11,7 @@ using Orchard.Core.Title.Models;
|
||||
using Orchard.Localization;
|
||||
using Orchard.UI.Navigation;
|
||||
using Orchard.Utility.Extensions;
|
||||
using Orchard.ContentManagement.Utilities;
|
||||
|
||||
namespace Orchard.Core.Navigation.Drivers {
|
||||
public class MenuWidgetPartDriver : ContentPartDriver<MenuWidgetPart> {
|
||||
@@ -50,6 +51,11 @@ namespace Orchard.Core.Navigation.Drivers {
|
||||
var menuName = menu.As<TitlePart>().Title.HtmlClassify();
|
||||
var currentCulture = _workContextAccessor.GetContext().CurrentCulture;
|
||||
var menuItems = _navigationManager.BuildMenu(menu);
|
||||
|
||||
if (!part.Breadcrumb) {
|
||||
menuItems = menuItems.Where(x => !x.Content.Has<BreadcrumbMenuItemPart>());
|
||||
}
|
||||
|
||||
var localized = new List<MenuItem>();
|
||||
foreach(var menuItem in menuItems) {
|
||||
// if there is no associated content, it as culture neutral
|
||||
|
@@ -0,0 +1,6 @@
|
||||
using Orchard.ContentManagement;
|
||||
|
||||
namespace Orchard.Core.Navigation.Models {
|
||||
public class BreadcrumbMenuItemPart : ContentPart {
|
||||
}
|
||||
}
|
@@ -76,7 +76,7 @@ namespace Orchard.Core.Navigation.Services {
|
||||
|
||||
private IEnumerable<MenuItem> Filter(IEnumerable<MenuItem> menuItems) {
|
||||
IEnumerable<MenuItem> result = menuItems;
|
||||
foreach(var filter in _navigationFilters) {
|
||||
foreach (var filter in _navigationFilters) {
|
||||
result = filter.Filter(result);
|
||||
}
|
||||
|
||||
|
@@ -172,6 +172,7 @@
|
||||
<Compile Include="Dashboard\Services\CompilationErrorBanner.cs" />
|
||||
<Compile Include="Navigation\Commands\MenuCommands.cs" />
|
||||
<Compile Include="Navigation\Drivers\AdminMenuPartDriver.cs" />
|
||||
<Compile Include="Navigation\Drivers\BreadcrumbMenuItemPartDriver.cs" />
|
||||
<Compile Include="Navigation\Drivers\MenuItemPartDriver.cs" />
|
||||
<Compile Include="Navigation\Drivers\MenuWidgetPartDriver.cs" />
|
||||
<Compile Include="Navigation\Drivers\ShapeMenuItemPartDriver.cs" />
|
||||
@@ -182,6 +183,7 @@
|
||||
<Compile Include="Navigation\Handlers\MenuWidgetPartHandler.cs" />
|
||||
<Compile Include="Navigation\Models\AdminMenuPart.cs" />
|
||||
<Compile Include="Navigation\Models\AdminMenuPartRecord.cs" />
|
||||
<Compile Include="Navigation\Models\BreadcrumbMenuItemPart.cs" />
|
||||
<Compile Include="Navigation\Models\MenuWidgetPart.cs" />
|
||||
<Compile Include="Navigation\Models\ShapeMenuItemPart.cs" />
|
||||
<Compile Include="Navigation\Security\AuthorizationEventHandler.cs" />
|
||||
|
@@ -0,0 +1,24 @@
|
||||
using Orchard.Data.Migration;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Core.Navigation.Models;
|
||||
|
||||
namespace Orchard.Alias {
|
||||
[OrchardFeature("Orchard.Alias.BreadcrumbLink")]
|
||||
public class AliasBreadcrumbMigration : DataMigrationImpl {
|
||||
public int Create() {
|
||||
ContentDefinitionManager.AlterTypeDefinition("AliasBreadcrumbMenuItem",
|
||||
cfg => cfg
|
||||
.WithPart("BreadcrumbMenuItemPart")
|
||||
.WithPart("MenuPart")
|
||||
.WithPart("CommonPart")
|
||||
.WithIdentity()
|
||||
.DisplayedAs("Alias Breadcrumb Link")
|
||||
.WithSetting("Description", "A menu item that can be used to generate breadcrumb links, using Alias data, to content items without explicitly adding links to those content items in the menu.")
|
||||
.WithSetting("Stereotype", "MenuItem")
|
||||
);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
@@ -27,6 +27,5 @@ namespace Orchard.Alias {
|
||||
);
|
||||
return 2;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -18,3 +18,8 @@ Features:
|
||||
Description: Synchronizes aliases when created from different servers.
|
||||
Dependencies: Orchard.Alias
|
||||
Category: Content
|
||||
Orchard.Alias.BreadcrumbLink:
|
||||
Name: Alias Breadcrumb Link
|
||||
Description: Provides Alias Breadcrumb Link menu item type that can be used to generate breadcrumb links, using Alias data, to content items without explicitly adding links to those content items in the menu.
|
||||
Dependencies: Orchard.Alias
|
||||
Category: Navigation
|
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Mvc;
|
||||
using Orchard.UI.Navigation;
|
||||
|
||||
namespace Orchard.Alias.Navigation {
|
||||
|
||||
[OrchardFeature("Orchard.Alias.BreadcrumbLink")]
|
||||
public class NavigationAliasProvider : INavigationFilter {
|
||||
private readonly IAliasService _aliasService;
|
||||
private readonly IContentManager _contentManager;
|
||||
private readonly IHttpContextAccessor _hca;
|
||||
|
||||
public NavigationAliasProvider(
|
||||
IAliasService aliasService,
|
||||
IContentManager contentManager,
|
||||
IHttpContextAccessor hca) {
|
||||
_aliasService = aliasService;
|
||||
_contentManager = contentManager;
|
||||
_hca = hca;
|
||||
}
|
||||
|
||||
public IEnumerable<MenuItem> Filter(IEnumerable<MenuItem> items) {
|
||||
foreach (var item in items) {
|
||||
if (item.Content != null && item.Content.ContentItem.ContentType == "AliasBreadcrumbMenuItem") {
|
||||
var request = _hca.Current().Request;
|
||||
var path = request.Path;
|
||||
var appPath = request.ApplicationPath ?? "/";
|
||||
var requestUrl = (path.StartsWith(appPath) ? path.Substring(appPath.Length) : path).TrimStart('/');
|
||||
var endsWithSlash = requestUrl.EndsWith("/");
|
||||
|
||||
var menuPosition = item.Position;
|
||||
|
||||
var urlLevel = endsWithSlash ? requestUrl.Count(l => l == '/') - 1 : requestUrl.Count(l => l == '/');
|
||||
var menuLevel = menuPosition.Count(l => l == '.');
|
||||
|
||||
// Checking menu item if it's the leaf element or it's an intermediate element
|
||||
// or it's an unneccessary element according to the url.
|
||||
RouteValueDictionary contentRoute;
|
||||
if (menuLevel == urlLevel) {
|
||||
contentRoute = request.RequestContext.RouteData.Values;
|
||||
}
|
||||
else {
|
||||
// If menuLevel doesn't equal with urlLevel it can mean that this menu item is
|
||||
// an intermediate element (the difference is a positive value) or this menu
|
||||
// item is lower in the navigation hierarchy according to the url (negative
|
||||
// value). If the value is negative, removing the menu item, if the value
|
||||
// is positive finding its place in the hierarchy.
|
||||
var levelDifference = urlLevel - menuLevel;
|
||||
if (levelDifference > 0) {
|
||||
if (endsWithSlash) {
|
||||
levelDifference += levelDifference;
|
||||
}
|
||||
for (int i = 0; i < levelDifference; i++) {
|
||||
requestUrl = requestUrl.Remove(requestUrl.LastIndexOf('/'));
|
||||
path = path.Remove(path.LastIndexOf('/'));
|
||||
}
|
||||
contentRoute = _aliasService.Get(requestUrl);
|
||||
if (contentRoute == null) {
|
||||
// After the exact number of segments is cut out from the url and the
|
||||
// currentRoute is still null, trying another check with the added slash,
|
||||
// because we don't know if the alias was created with a slash at the end or not.
|
||||
contentRoute = _aliasService.Get(requestUrl.Insert(requestUrl.Length, "/"));
|
||||
path = path.Insert(path.Length, "/");
|
||||
if (contentRoute == null) {
|
||||
contentRoute = new RouteValueDictionary();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
contentRoute = new RouteValueDictionary();
|
||||
}
|
||||
}
|
||||
|
||||
object id;
|
||||
contentRoute.TryGetValue("Id", out id);
|
||||
int contentId;
|
||||
int.TryParse(id as string, out contentId);
|
||||
if (contentId == 0) {
|
||||
// If failed to get the Id's value from currentRoute, transform the alias to the virtual path
|
||||
// and try to get the content item's id from there. E.g. "Blogs/Blog/Item?blogId=12" where
|
||||
// the last digits represents the content item's id. If there is a match in the path we get
|
||||
// the digits after the equality sign.
|
||||
// There is an another type of the routes: like "Contents/Item/Display/13", but when the
|
||||
// content item's route is in this form we already have the id from contentRoute.TryGetValue("Id", out id).
|
||||
var virtualPath = _aliasService.LookupVirtualPaths(contentRoute, _hca.Current()).FirstOrDefault();
|
||||
int.TryParse(virtualPath != null ? virtualPath.VirtualPath.Substring(virtualPath.VirtualPath.LastIndexOf('=') + 1) : "0", out contentId);
|
||||
}
|
||||
if (contentId != 0) {
|
||||
var currentContentItem = _contentManager.Get(contentId);
|
||||
if (currentContentItem != null) {
|
||||
var menuText = _contentManager.GetItemMetadata(currentContentItem).DisplayText;
|
||||
var routes = _contentManager.GetItemMetadata(currentContentItem).DisplayRouteValues;
|
||||
|
||||
var inserted = new MenuItem {
|
||||
Text = new LocalizedString(menuText),
|
||||
IdHint = item.IdHint,
|
||||
Classes = item.Classes,
|
||||
Url = path,
|
||||
Href = item.Href,
|
||||
LinkToFirstChild = false,
|
||||
RouteValues = routes,
|
||||
LocalNav = item.LocalNav,
|
||||
Items = Enumerable.Empty<MenuItem>(),
|
||||
Position = menuPosition,
|
||||
Permissions = item.Permissions,
|
||||
Content = item.Content
|
||||
};
|
||||
|
||||
yield return inserted;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
yield return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -101,10 +101,12 @@
|
||||
<Content Include="Views\Admin\Edit.cshtml" />
|
||||
<Content Include="Views\Admin\IndexUnmanaged.cshtml" />
|
||||
<Content Include="Web.config" />
|
||||
<Compile Include="AliasBreadcrumbLinkMigrations.cs" />
|
||||
<Compile Include="Implementation\Updater\AliasHolderUpdater.cs" />
|
||||
<Compile Include="Implementation\Updater\AliasUpdateCursor.cs" />
|
||||
<Compile Include="Implementation\Updater\AliasUpdaterBackgroundTask.cs" />
|
||||
<Compile Include="Implementation\Updater\IAliasUpdateCursor.cs" />
|
||||
<Compile Include="Navigation\NavigationAliasProvider.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Content Include="Module.txt" />
|
||||
</ItemGroup>
|
||||
|
Reference in New Issue
Block a user