Files
Orchard/src/Orchard.Web/Modules/Orchard.Alias/Navigation/NavigationAliasProvider.cs

126 lines
6.8 KiB
C#

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, bool isBreadcrumb = false) {
foreach (var item in items) {
if (item.Content != null && item.Content.ContentItem.ContentType == "AliasBreadcrumbMenuItem") {
if (isBreadcrumb) {
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 = _aliasService.Get(requestUrl);
}
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, "/");
}
}
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 = currentContentItem
};
yield return inserted;
}
}
}
}
else {
yield return item;
}
}
}
}
}