From e8b80c2edd37fb3839dc357afbafac81d2b5ce72 Mon Sep 17 00:00:00 2001 From: Tobias Klika Date: Thu, 4 Nov 2021 23:46:41 +0100 Subject: [PATCH] new IRoutes implementation --- zero.Core/Routing/New/Routes.cs | 197 ++++++++++++++++++++ zero.Core/Routing/New/TestRouteProvider.cs | 9 +- zero.Core/Routing/New/ZeroRoutingContext.cs | 7 +- zero.Core/Routing/Page/PageRoute.cs | 2 + 4 files changed, 205 insertions(+), 10 deletions(-) create mode 100644 zero.Core/Routing/New/Routes.cs diff --git a/zero.Core/Routing/New/Routes.cs b/zero.Core/Routing/New/Routes.cs new file mode 100644 index 00000000..63af4aca --- /dev/null +++ b/zero.Core/Routing/New/Routes.cs @@ -0,0 +1,197 @@ +using Microsoft.Extensions.Logging; +using Raven.Client.Documents.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using zero.Core.Database; +using zero.Core.Entities; +using zero.Core.Extensions; + + +namespace zero.Core.Routing +{ + public class NewRoutes : INewRoutes + { + public const char PATH_SEPERATOR = '/'; + + protected IZeroContext Context { get; set; } + protected IZeroStore Store { get; set; } + protected ILogger Logger { get; set; } + protected IEnumerable Providers { get; set; } + + + public NewRoutes(IZeroContext context, IZeroStore store, ILogger logger, IEnumerable providers) + { + Context = context; + Store = store; + Logger = logger; + Providers = providers; + } + + + /// + public async Task GetUrl(T model, object parameters = null) where T : IZeroRouteEntity => (await GetRoute(model, parameters))?.Url; + + + /// + public async Task GetUrl(string id, object parameters = null) where T : IZeroRouteEntity => (await GetRoute(id, parameters))?.Url; + + + /// + public async Task> GetUrls(IEnumerable models, object parameters = null) where T : IZeroRouteEntity => (await GetRoutes(models, parameters)).ToDictionary(x => x.Key, x => x.Value?.Url); + + + /// + public async Task GetRoute(string id, object parameters = null) where T : IZeroRouteEntity + { + if (id.IsNullOrEmpty()) + { + return null; + } + + Type type = typeof(T); + INewRouteProvider routeProvider = Providers.FirstOrDefault(x => x.CanHandle(type)); + + if (routeProvider == null) + { + return null; + } + + RoutingContext context = GetContext(); + T model = await context.Session.LoadAsync(id); + + if (model == null) + { + return null; + } + + return await FindRoute(routeProvider, context, model); + } + + + /// + public async Task GetRoute(T model, object parameters = null) where T : IZeroRouteEntity + { + if (model == null) + { + return null; + } + + Type type = model.GetType(); + INewRouteProvider routeProvider = Providers.FirstOrDefault(x => x.CanHandle(type)); + + if (routeProvider == null) + { + return null; + } + + RoutingContext context = GetContext(); + return await FindRoute(routeProvider, context, model); + } + + + /// + public async Task> GetRoutes(IEnumerable models, object parameters = null) where T : IZeroRouteEntity + { + if (!models.Any()) + { + return new(); + } + + T firstExistingModel = models.FirstOrDefault(x => x != null); + + if (firstExistingModel == null) + { + return new(); + } + + Type type = firstExistingModel.GetType(); + INewRouteProvider routeProvider = Providers.FirstOrDefault(x => x.CanHandle(type)); + + if (routeProvider == null) + { + return null; + } + + RoutingContext context = GetContext(); + Dictionary idMap = models.ToDictionary(x => GetId(routeProvider, x), x => x); + Dictionary routes = await context.Session.LoadAsync(idMap.Select(x => x.Key)); + Dictionary result = new(); + + foreach ((string id, T model) in idMap) + { + result.Add(model, routes.GetValueOrDefault(id)); + } + + return result; + } + + + /// + /// Find a persisted route for an entity + /// + protected virtual async Task FindRoute(INewRouteProvider provider, RoutingContext context, IZeroRouteEntity model) + { + return await context.Session.LoadAsync(GetId(provider, model)); + } + + + /// + /// Get ID in collection for an entity + /// + protected virtual string GetId(INewRouteProvider provider, IZeroRouteEntity model) + { + string key = provider.Key(model); + + if (key.IsNullOrEmpty()) + { + return null; + } + + return "routes." + provider.Alias + "." + key; + } + + + /// + /// Build a new routing context + /// + protected virtual RoutingContext GetContext() + { + return new(Store, Context, Store.Session()); + } + } + + public interface INewRoutes + { + /// + /// Get the URL for an entity + /// + Task GetUrl(T model, object parameters = null) where T : IZeroRouteEntity; + + /// + /// Get the URL for an entity + /// + Task GetUrl(string id, object parameters = null) where T : IZeroRouteEntity; + + /// + /// Get URLs for multiple entities + /// + Task> GetUrls(IEnumerable models, object parameters = null) where T : IZeroRouteEntity; + + /// + /// Get the route object for an entity + /// + Task GetRoute(T model, object parameters = null) where T : IZeroRouteEntity; + + /// + /// Get the route object for an entity + /// + Task GetRoute(string id, object parameters = null) where T : IZeroRouteEntity; + + /// + /// Get routes for multiple entities + /// + Task> GetRoutes(IEnumerable models, object parameters = null) where T : IZeroRouteEntity; + } +} diff --git a/zero.Core/Routing/New/TestRouteProvider.cs b/zero.Core/Routing/New/TestRouteProvider.cs index eb9714d4..9b0ef2ac 100644 --- a/zero.Core/Routing/New/TestRouteProvider.cs +++ b/zero.Core/Routing/New/TestRouteProvider.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Threading.Tasks; using zero.Core.Database.Indexes; using zero.Core.Entities; +using zero.Core.Extensions; namespace zero.Core.Routing { @@ -33,10 +34,9 @@ namespace zero.Core.Routing Route route = new(); route.Url = UrlBuilder.GetUrl(model, parents); - route.Dependencies.Add(model.Id); - route.Dependencies.AddRange(parents.Select(x => x.Id)); - - route.Params.Add(PAGE_TYPE_PARAM, model.PageTypeAlias); + route.DependsOn(model.Id); + route.DependsOn(parents.Select(x => x.Id).ToArray()); + route.Param(PAGE_TYPE_PARAM, model.PageTypeAlias); return route; } @@ -48,6 +48,7 @@ namespace zero.Core.Routing PageRoute resolved = new(route); resolved.Page = entity; resolved.Parents = await GetParents(context, entity); + resolved.PageType = route.Param(PAGE_TYPE_PARAM); return resolved; } diff --git a/zero.Core/Routing/New/ZeroRoutingContext.cs b/zero.Core/Routing/New/ZeroRoutingContext.cs index a02f41a1..73292ee6 100644 --- a/zero.Core/Routing/New/ZeroRoutingContext.cs +++ b/zero.Core/Routing/New/ZeroRoutingContext.cs @@ -9,16 +9,13 @@ namespace zero.Core.Routing public IZeroContext Context { get; private set; } - public IZeroOptions Options { get; private set; } - public IZeroDocumentSession Session { get; private set; } - public RoutingContext(IZeroStore store, IZeroContext context, IZeroOptions options, IZeroDocumentSession session) + public RoutingContext(IZeroStore store, IZeroContext context, IZeroDocumentSession session) { Store = store; Context = context; - Options = options; Session = session; } } @@ -30,8 +27,6 @@ namespace zero.Core.Routing IZeroContext Context { get; } - IZeroOptions Options { get; } - IZeroDocumentSession Session { get; } } } diff --git a/zero.Core/Routing/Page/PageRoute.cs b/zero.Core/Routing/Page/PageRoute.cs index aac3e1e2..6527adea 100644 --- a/zero.Core/Routing/Page/PageRoute.cs +++ b/zero.Core/Routing/Page/PageRoute.cs @@ -9,5 +9,7 @@ namespace zero.Core.Routing public PageRoute(Route route) : base(route) { } public IList Parents { get; set; } + + public string PageType { get; set; } } }