diff --git a/src/Orchard.Web/Core/Navigation/Drivers/BreadcrumbMenuItemPartDriver.cs b/src/Orchard.Web/Core/Navigation/Drivers/BreadcrumbMenuItemPartDriver.cs new file mode 100644 index 000000000..9422f1c0a --- /dev/null +++ b/src/Orchard.Web/Core/Navigation/Drivers/BreadcrumbMenuItemPartDriver.cs @@ -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 { + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Navigation/Drivers/MenuWidgetPartDriver.cs b/src/Orchard.Web/Core/Navigation/Drivers/MenuWidgetPartDriver.cs index 82c58de8a..626a66691 100644 --- a/src/Orchard.Web/Core/Navigation/Drivers/MenuWidgetPartDriver.cs +++ b/src/Orchard.Web/Core/Navigation/Drivers/MenuWidgetPartDriver.cs @@ -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 { @@ -49,7 +50,12 @@ namespace Orchard.Core.Navigation.Drivers { var menuName = menu.As().Title.HtmlClassify(); var currentCulture = _workContextAccessor.GetContext().CurrentCulture; - var menuItems = _navigationManager.BuildMenu(menu, part.Breadcrumb); + var menuItems = _navigationManager.BuildMenu(menu); + + if (!part.Breadcrumb) { + menuItems = menuItems.Where(x => !x.Content.Has()); + } + var localized = new List(); foreach(var menuItem in menuItems) { // if there is no associated content, it as culture neutral diff --git a/src/Orchard.Web/Core/Navigation/Models/BreadcrumbMenuItemPart.cs b/src/Orchard.Web/Core/Navigation/Models/BreadcrumbMenuItemPart.cs new file mode 100644 index 000000000..4c91990cf --- /dev/null +++ b/src/Orchard.Web/Core/Navigation/Models/BreadcrumbMenuItemPart.cs @@ -0,0 +1,6 @@ +using Orchard.ContentManagement; + +namespace Orchard.Core.Navigation.Models { + public class BreadcrumbMenuItemPart : ContentPart { + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Navigation/Services/NavigationManager.cs b/src/Orchard.Web/Core/Navigation/Services/NavigationManager.cs index 044accde8..33dbdc86e 100644 --- a/src/Orchard.Web/Core/Navigation/Services/NavigationManager.cs +++ b/src/Orchard.Web/Core/Navigation/Services/NavigationManager.cs @@ -44,29 +44,21 @@ namespace Orchard.Core.Navigation.Services { public ILogger Logger { get; set; } public IEnumerable BuildMenu(string menuName) { - return BuildMenu(menuName, false); - } - - public IEnumerable BuildMenu(string menuName, bool isBreadcrumb) { var sources = GetSources(menuName); var hasDebugShowAllMenuItems = _authorizationService.TryCheckAccess(Permission.Named("DebugShowAllMenuItems"), _orchardServices.WorkContext.CurrentUser, null); - return FinishMenu(Reduce(Filter(Merge(sources), isBreadcrumb), menuName == "admin", hasDebugShowAllMenuItems).ToArray()); + return FinishMenu(Reduce(Filter(Merge(sources)), menuName == "admin", hasDebugShowAllMenuItems).ToArray()); } public IEnumerable BuildMenu(IContent menu) { - return BuildMenu(menu,false); - } - - public IEnumerable BuildMenu(IContent menu, bool isBreadcrumb) { var sources = GetSources(menu); var hasDebugShowAllMenuItems = _authorizationService.TryCheckAccess(Permission.Named("DebugShowAllMenuItems"), _orchardServices.WorkContext.CurrentUser, null); - return FinishMenu(Reduce(Arrange(Filter(Merge(sources), isBreadcrumb)), false, hasDebugShowAllMenuItems).ToArray()); + return FinishMenu(Reduce(Arrange(Filter(Merge(sources))), false, hasDebugShowAllMenuItems).ToArray()); } public string GetNextPosition(IContent menu) { var sources = GetSources(menu); var hasDebugShowAllMenuItems = _authorizationService.TryCheckAccess(Permission.Named("DebugShowAllMenuItems"), _orchardServices.WorkContext.CurrentUser, null); - return Position.GetNext(Reduce(Arrange(Filter(Merge(sources), false)), false, hasDebugShowAllMenuItems).ToArray()); + return Position.GetNext(Reduce(Arrange(Filter(Merge(sources))), false, hasDebugShowAllMenuItems).ToArray()); } public IEnumerable BuildImageSets(string menuName) { @@ -82,10 +74,10 @@ namespace Orchard.Core.Navigation.Services { return menuItems; } - private IEnumerable Filter(IEnumerable menuItems, bool isBreadcrumb) { + private IEnumerable Filter(IEnumerable menuItems) { IEnumerable result = menuItems; foreach (var filter in _navigationFilters) { - result = filter.Filter(result, isBreadcrumb); + result = filter.Filter(result); } return result; diff --git a/src/Orchard.Web/Core/Orchard.Core.csproj b/src/Orchard.Web/Core/Orchard.Core.csproj index d7df66382..66e82c042 100644 --- a/src/Orchard.Web/Core/Orchard.Core.csproj +++ b/src/Orchard.Web/Core/Orchard.Core.csproj @@ -172,6 +172,7 @@ + @@ -182,6 +183,7 @@ + diff --git a/src/Orchard.Web/Modules/Orchard.Alias/AliasBreadcrumbLinkMigrations.cs b/src/Orchard.Web/Modules/Orchard.Alias/AliasBreadcrumbLinkMigrations.cs index 4a458ac80..232525650 100644 --- a/src/Orchard.Web/Modules/Orchard.Alias/AliasBreadcrumbLinkMigrations.cs +++ b/src/Orchard.Web/Modules/Orchard.Alias/AliasBreadcrumbLinkMigrations.cs @@ -1,6 +1,7 @@ using Orchard.Data.Migration; using Orchard.ContentManagement.MetaData; using Orchard.Environment.Extensions; +using Orchard.Core.Navigation.Models; namespace Orchard.Alias { [OrchardFeature("Orchard.Alias.BreadcrumbLink")] @@ -8,6 +9,7 @@ namespace Orchard.Alias { public int Create() { ContentDefinitionManager.AlterTypeDefinition("AliasBreadcrumbMenuItem", cfg => cfg + .WithPart("BreadcrumbMenuItemPart") .WithPart("MenuPart") .WithPart("CommonPart") .WithIdentity() diff --git a/src/Orchard.Web/Modules/Orchard.Alias/Navigation/NavigationAliasProvider.cs b/src/Orchard.Web/Modules/Orchard.Alias/Navigation/NavigationAliasProvider.cs index ea7ea0cf2..837fe2e3d 100644 --- a/src/Orchard.Web/Modules/Orchard.Alias/Navigation/NavigationAliasProvider.cs +++ b/src/Orchard.Web/Modules/Orchard.Alias/Navigation/NavigationAliasProvider.cs @@ -27,93 +27,94 @@ namespace Orchard.Alias.Navigation { _hca = hca; } - public IEnumerable Filter(IEnumerable items, bool isBreadcrumb = false) { + public IEnumerable Filter(IEnumerable items) { 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 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 menuPosition = item.Position; - var urlLevel = endsWithSlash ? requestUrl.Count(l => l == '/') - 1 : requestUrl.Count(l => l == '/'); - var menuLevel = menuPosition.Count(l => l == '.'); + 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) { + // 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 { - // 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(); - } + 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; + 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(), - Position = menuPosition, - Permissions = item.Permissions, - Content = currentContentItem - }; + 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(), + Position = menuPosition, + Permissions = item.Permissions, + Content = item.Content + }; - yield return inserted; - } + yield return inserted; } } } diff --git a/src/Orchard.Web/Modules/Orchard.Projections/Navigation/NavigationQueryProvider.cs b/src/Orchard.Web/Modules/Orchard.Projections/Navigation/NavigationQueryProvider.cs index 3dd6a366c..988cf8c49 100644 --- a/src/Orchard.Web/Modules/Orchard.Projections/Navigation/NavigationQueryProvider.cs +++ b/src/Orchard.Web/Modules/Orchard.Projections/Navigation/NavigationQueryProvider.cs @@ -21,7 +21,7 @@ namespace Orchard.Projections.Navigation { _projectionManager = projectionManager; } - public IEnumerable Filter(IEnumerable items, bool isBreadcrumb) { + public IEnumerable Filter(IEnumerable items) { foreach (var item in items) { if (item.Content != null && item.Content.ContentItem.ContentType == "NavigationQueryMenuItem") { diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Navigation/TaxonomyNavigationProvider.cs b/src/Orchard.Web/Modules/Orchard.Taxonomies/Navigation/TaxonomyNavigationProvider.cs index 52ee07004..6ca41931c 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Navigation/TaxonomyNavigationProvider.cs +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Navigation/TaxonomyNavigationProvider.cs @@ -24,7 +24,7 @@ namespace Orchard.Taxonomies.Navigation { _taxonomyService = taxonomyService; } - public IEnumerable Filter(IEnumerable items, bool isBreadcrumb) { + public IEnumerable Filter(IEnumerable items) { foreach (var item in items) { if (item.Content != null && item.Content.ContentItem.ContentType == "TaxonomyNavigationMenuItem") { diff --git a/src/Orchard/UI/Navigation/INavigationFilter.cs b/src/Orchard/UI/Navigation/INavigationFilter.cs index 679dee49b..cd51420bd 100644 --- a/src/Orchard/UI/Navigation/INavigationFilter.cs +++ b/src/Orchard/UI/Navigation/INavigationFilter.cs @@ -5,6 +5,6 @@ namespace Orchard.UI.Navigation { /// Provides a way to alter the main navigation, for instance by dynamically injecting new items /// public interface INavigationFilter : IDependency { - IEnumerable Filter(IEnumerable menuItems, bool isBreadcrumb = false); + IEnumerable Filter(IEnumerable menuItems); } } diff --git a/src/Orchard/UI/Navigation/INavigationManager.cs b/src/Orchard/UI/Navigation/INavigationManager.cs index 6ea24dfe3..0c0045f1d 100644 --- a/src/Orchard/UI/Navigation/INavigationManager.cs +++ b/src/Orchard/UI/Navigation/INavigationManager.cs @@ -5,9 +5,7 @@ using Orchard.ContentManagement; namespace Orchard.UI.Navigation { public interface INavigationManager : IDependency { IEnumerable BuildMenu(string menuName); - IEnumerable BuildMenu(string menuName, bool isBreadcrumbMenu); IEnumerable BuildMenu(IContent menu); - IEnumerable BuildMenu(IContent menu, bool isBreadcrumbMenu); IEnumerable BuildImageSets(string menuName); string GetUrl(string menuItemUrl, RouteValueDictionary routeValueDictionary); string GetNextPosition(IContent menu);