public async Task <PageRoutingInfo> ExecuteAsync(GetPageRoutingInfoByPathQuery query, IExecutionContext executionContext)
        {
            // Deal with malformed query
            if (!string.IsNullOrWhiteSpace(query.Path) && !Uri.IsWellFormedUriString(query.Path, UriKind.Relative))
            {
                return(null);
            }

            var path      = _pathHelper.StandardizePath(query.Path);
            var allRoutes = await _queryExecutor.ExecuteAsync(new GetAllPageRoutesQuery(), executionContext);

            var pageRoutes = allRoutes
                             .Where(r => r.FullPath.Equals(path) || (r.PageType == PageType.CustomEntityDetails && IsCustomRoutingMatch(path, r.FullPath)))
                             .Where(r => query.IncludeUnpublished || r.IsPublished())
                             .Where(r => r.Locale == null || MatchesLocale(r.Locale, query.LocaleId))
                             .OrderByDescending(r => r.FullPath.Equals(path))
                             .ThenByDescending(r => MatchesLocale(r.Locale, query.LocaleId))
                             .ToList();

            PageRoutingInfo result = null;

            if (!pageRoutes.Any())
            {
                return(result);
            }

            // Exact match
            if (pageRoutes[0].PageType != PageType.CustomEntityDetails)
            {
                result = ToRoutingInfo(pageRoutes[0]);
            }
            else
            {
                var allRules = await _queryExecutor.ExecuteAsync(new GetAllCustomEntityRoutingRulesQuery(), executionContext);

                // I'm only anticipating a single rule to match at the moment, but eventually there might be multiple rules to match e.g. categories page
                foreach (var pageRoute in pageRoutes)
                {
                    // Find a routing rule, matching higher priorities first
                    var rule = allRules
                               .Where(r => r.MatchesRule(query.Path, pageRoute))
                               .OrderBy(r => r.Priority)
                               .ThenBy(r => r.RouteFormat.Length)
                               .FirstOrDefault();

                    if (rule != null)
                    {
                        var customEntityRouteQuery = rule.ExtractRoutingQuery(query.Path, pageRoute);
                        var customEntityRoute      = await _queryExecutor.ExecuteAsync(customEntityRouteQuery, executionContext);

                        if (customEntityRoute != null && (query.IncludeUnpublished || customEntityRoute.IsPublished()))
                        {
                            return(ToRoutingInfo(pageRoute, customEntityRoute, rule));
                        }
                    }
                }
            }

            return(result);
        }
Exemple #2
0
        public async Task <PageRoute> ExecuteAsync(GetNotFoundPageRouteByPathQuery query, IExecutionContext executionContext)
        {
            if (!string.IsNullOrWhiteSpace(query.Path) && !Uri.IsWellFormedUriString(query.Path, UriKind.Relative))
            {
                return(null);
            }

            var path = _pathHelper.StandardizePath(query.Path);

            var allRoutes = await _queryExecutor.ExecuteAsync(new GetAllPageRoutesQuery(), executionContext);

            var allNotFoundRoutes = allRoutes
                                    .Where(r => r.IsPublished() || query.IncludeUnpublished)
                                    .Where(r => r.PageType == PageType.NotFound);

            var paths = path
                        .Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries)
                        .ToList();

            PageRoute notFoundRoute = null;

            // Work backwards through the path to find a 404 page
            while (notFoundRoute == null)
            {
                var pathToTest = string.Join("/", paths);
                if (string.IsNullOrEmpty(pathToTest))
                {
                    pathToTest = "/";
                }

                // Prefer the specified locale, but fall back to a non-specific locale page
                notFoundRoute = allNotFoundRoutes
                                .Where(r => r.IsInDirectory(pathToTest) && r.Locale == null || MatchesLocale(r.Locale, query.LocaleId))
                                .OrderByDescending(r => MatchesLocale(r.Locale, query.LocaleId))
                                .FirstOrDefault();

                // After we've checked the root directory, break and return null
                if (paths.Count <= 0)
                {
                    break;
                }

                // Move backwards down the path
                paths.Remove(paths.Last());
            }

            return(notFoundRoute);
        }