diff --git a/src/VirtoCommerce.Xapi.Core/Models/SlugInfoResponse.cs b/src/VirtoCommerce.Xapi.Core/Models/SlugInfoResponse.cs index 13b87c8..b95102e 100644 --- a/src/VirtoCommerce.Xapi.Core/Models/SlugInfoResponse.cs +++ b/src/VirtoCommerce.Xapi.Core/Models/SlugInfoResponse.cs @@ -5,6 +5,6 @@ namespace VirtoCommerce.Xapi.Core.Models public class SlugInfoResponse { public SeoInfo EntityInfo { get; set; } - //public string RedirectUrl { get; set; } + public string RedirectUrl { get; set; } } } diff --git a/src/VirtoCommerce.Xapi.Core/Schemas/SlugInfoResponseType.cs b/src/VirtoCommerce.Xapi.Core/Schemas/SlugInfoResponseType.cs index 7322542..b196e17 100644 --- a/src/VirtoCommerce.Xapi.Core/Schemas/SlugInfoResponseType.cs +++ b/src/VirtoCommerce.Xapi.Core/Schemas/SlugInfoResponseType.cs @@ -7,7 +7,7 @@ public class SlugInfoResponseType : ExtendableGraphType public SlugInfoResponseType() { Field("entityInfo").Description("SEO info").Resolve(context => context.Source.EntityInfo); - // here should be redirectUrl soon + Field(x => x.RedirectUrl, nullable: true).Description("Target URL when SEO is null"); } } } diff --git a/src/VirtoCommerce.Xapi.Core/VirtoCommerce.Xapi.Core.csproj b/src/VirtoCommerce.Xapi.Core/VirtoCommerce.Xapi.Core.csproj index baa05bd..8156751 100644 --- a/src/VirtoCommerce.Xapi.Core/VirtoCommerce.Xapi.Core.csproj +++ b/src/VirtoCommerce.Xapi.Core/VirtoCommerce.Xapi.Core.csproj @@ -23,18 +23,17 @@ - + - + - diff --git a/src/VirtoCommerce.Xapi.Data/Queries/SlugInfoQueryHandler.cs b/src/VirtoCommerce.Xapi.Data/Queries/SlugInfoQueryHandler.cs index f5194f2..31bb9d3 100644 --- a/src/VirtoCommerce.Xapi.Data/Queries/SlugInfoQueryHandler.cs +++ b/src/VirtoCommerce.Xapi.Data/Queries/SlugInfoQueryHandler.cs @@ -14,16 +14,12 @@ namespace VirtoCommerce.Xapi.Data.Queries; -public class SlugInfoQueryHandler : IQueryHandler +public class SlugInfoQueryHandler( + ICompositeSeoResolver seoResolver, + IStoreService storeService, + IBrokenLinkSearchService brokenLinkSearchService) + : IQueryHandler { - private readonly ICompositeSeoResolver _seoResolver; - private readonly IStoreService _storeService; - - public SlugInfoQueryHandler(ICompositeSeoResolver seoResolver, IStoreService storeService) - { - _seoResolver = seoResolver; - _storeService = storeService; - } public async Task Handle(SlugInfoQuery request, CancellationToken cancellationToken) { @@ -34,7 +30,7 @@ public async Task Handle(SlugInfoQuery request, CancellationTo return result; } - var store = await _storeService.GetByIdAsync(request.StoreId); + var store = await storeService.GetByIdAsync(request.StoreId); if (store is null) { return result; @@ -54,18 +50,34 @@ public async Task Handle(SlugInfoQuery request, CancellationTo result.EntityInfo = await GetBestMatchingSeoInfo(criteria, store); - //if (result.EntityInfo == null) - //{ - // // todo: use seofaultservice - // result.RedirectUrl = ""; - //} + if (result.EntityInfo == null) + { + var brokenLinkCriteria = AbstractTypeFactory.TryCreateInstance(); + + brokenLinkCriteria.Permalink = request.Permalink; + brokenLinkCriteria.StoreId = store.Id; + brokenLinkCriteria.Status = Seo.Core.ModuleConstants.LinkStatus.Resolved; + brokenLinkCriteria.LanguageCode = request.CultureName; + + var brokenLinkResult = await brokenLinkSearchService.SearchAsync(brokenLinkCriteria); + + if (brokenLinkResult.Results.Count > 0) + { + var resultItem = brokenLinkResult.Results.FirstOrDefault(x => + (x.Language == request.CultureName) || + (!request.CultureName.IsNullOrEmpty() && x.Language.IsNullOrEmpty())) + ?? brokenLinkResult.Results.FirstOrDefault(); + + result.RedirectUrl = resultItem?.RedirectUrl; + } + } return result; } protected virtual async Task GetBestMatchingSeoInfo(SeoSearchCriteria criteria, Store store) { - var itemsToMatch = await _seoResolver.FindSeoAsync(criteria); + var itemsToMatch = await seoResolver.FindSeoAsync(criteria); return itemsToMatch.GetBestMatchingSeoInfo(store, criteria.LanguageCode); } }