Skip to content

Commit c22f039

Browse files
author
Jan Nielsen
committed
fix current language selection if is not allowed for sitemap
1 parent 9afa6c7 commit c22f039

File tree

3 files changed

+60
-19
lines changed

3 files changed

+60
-19
lines changed

src/Libraries/Nop.Core/Http/NopHttpDefaults.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,9 @@ public static partial class NopHttpDefaults
1919
/// Gets the name of a request item that stores the value that indicates whether the request is being redirected by the generic route transformer
2020
/// </summary>
2121
public static string GenericRouteInternalRedirect => "nop.RedirectFromGenericPathRoute";
22+
23+
/// <summary>
24+
/// Gets the name of a request item that stores the value with default language for sitemap.xml
25+
/// </summary>
26+
public static string ForcedSitemapXmlLanguage => "nop.ForcedSitemapXmlLanguage";
2227
}

src/Presentation/Nop.Web.Framework/Mvc/Routing/LanguageParameterTransformer.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using Microsoft.AspNetCore.Http;
22
using Microsoft.AspNetCore.Routing;
33
using Nop.Core;
4+
using Nop.Core.Http;
45
using Nop.Core.Infrastructure;
56
using Nop.Services.Localization;
67

@@ -38,7 +39,11 @@ public LanguageParameterTransformer(IHttpContextAccessor httpContextAccessor,
3839
/// <returns>The transformed value</returns>
3940
public string TransformOutbound(object value)
4041
{
41-
//first try to get a language code from the route values
42+
// first check if we have forced value for sitemap.xml
43+
if (_httpContextAccessor.HttpContext?.Items[NopHttpDefaults.ForcedSitemapXmlLanguage] is string forcedLang && !string.IsNullOrEmpty(forcedLang))
44+
return forcedLang;
45+
46+
// then try to get a language code from the route values
4247
var routeValues = _httpContextAccessor.HttpContext.Request.RouteValues;
4348
if (routeValues.TryGetValue(NopRoutingDefaults.RouteValue.Language, out var routeValue))
4449
{

src/Presentation/Nop.Web/Factories/SitemapModelFactory.cs

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
using Nop.Core.Domain.Localization;
1414
using Nop.Core.Domain.News;
1515
using Nop.Core.Domain.Seo;
16+
using Nop.Core.Domain.Stores;
1617
using Nop.Core.Domain.Topics;
1718
using Nop.Core.Events;
19+
using Nop.Core.Http;
1820
using Nop.Core.Infrastructure;
1921
using Nop.Services.Blogs;
2022
using Nop.Services.Catalog;
@@ -522,7 +524,7 @@ protected virtual async Task WriteSitemapUrlAsync(XmlWriter writer, SitemapUrlMo
522524
/// <param name="fullPath">The path and name of the sitemap file</param>
523525
/// <param name="id">Sitemap identifier</param>
524526
/// <returns>A task that represents the asynchronous operation</returns>
525-
protected virtual async Task GenerateAsync(string fullPath, int id = 0)
527+
protected virtual async Task GenerateAsync(string fullPath, int id = 0)
526528
{
527529
//generate all URLs for the sitemap
528530
var sitemapUrls = await GenerateUrlsAsync();
@@ -603,6 +605,22 @@ protected string GetLocalizedUrl(string currentUrl, Language lang)
603605
return new Uri(new Uri(scheme), localizedPath).ToString();
604606
}
605607

608+
/// <summary>
609+
/// Retrieves the list of languages for the given store that are not excluded in the sitemap XML settings,
610+
/// if SEO-friendly URLs for languages are enabled.
611+
/// </summary>
612+
/// <param name="store">The store to retrieve allowed languages for.</param>
613+
/// <returns>
614+
/// A list of <see cref="Language"/> if SEO-friendly URLs are enabled; otherwise, <c>null</c>.
615+
/// </returns>
616+
protected async Task<List<Language>> GetAllowedLanguagesAsync(Store store)
617+
{
618+
return _localizationSettings.SeoFriendlyUrlsForLanguagesEnabled
619+
? (await _languageService.GetAllLanguagesAsync(storeId: store.Id))
620+
.Where(lang => !_sitemapXmlSettings.DisallowLanguages.Contains(lang.Id))
621+
.ToList()
622+
: null;
623+
}
606624
#endregion
607625

608626
#region Methods
@@ -823,27 +841,43 @@ public virtual async Task<SitemapModel> PrepareSitemapModelAsync(SitemapPageMode
823841
/// </returns>
824842
public virtual async Task<SitemapXmlModel> PrepareSitemapXmlModelAsync(int id = 0)
825843
{
826-
var language = await _workContext.GetWorkingLanguageAsync();
844+
var workingLanguage = await _workContext.GetWorkingLanguageAsync();
827845
var store = await _storeContext.GetCurrentStoreAsync();
846+
847+
// get list of allowed languages (null if multilingual URLs are disabled)
848+
var languages = await GetAllowedLanguagesAsync(store);
828849

829-
var fileName = string.Format(NopSeoDefaults.SitemapXmlFilePattern, store.Id, language.Id, id);
830-
var fullPath = _nopFileProvider.GetAbsolutePath(NopSeoDefaults.SitemapXmlDirectory, fileName);
850+
// select current language if allowed, fallback to first allowed if needed
851+
var language = languages?.FirstOrDefault(lang => lang.Id == workingLanguage?.Id) ?? languages?.FirstOrDefault() ?? workingLanguage;
831852

832-
if (_nopFileProvider.FileExists(fullPath) && _nopFileProvider.GetLastWriteTimeUtc(fullPath) > DateTime.UtcNow.AddHours(-_sitemapXmlSettings.RebuildSitemapXmlAfterHours))
853+
if (language.Id != workingLanguage.Id)
854+
_actionContextAccessor.ActionContext.HttpContext.Items[NopHttpDefaults.ForcedSitemapXmlLanguage] = language.UniqueSeoCode.ToLowerInvariant();
855+
856+
try
833857
{
858+
var fileName = string.Format(NopSeoDefaults.SitemapXmlFilePattern, store.Id, language.Id, id);
859+
var fullPath = _nopFileProvider.GetAbsolutePath(NopSeoDefaults.SitemapXmlDirectory, fileName);
860+
861+
if (_nopFileProvider.FileExists(fullPath) && _nopFileProvider.GetLastWriteTimeUtc(fullPath) > DateTime.UtcNow.AddHours(-_sitemapXmlSettings.RebuildSitemapXmlAfterHours))
862+
{
863+
return new SitemapXmlModel { SitemapXmlPath = fullPath };
864+
}
865+
866+
//execute task with lock
867+
if (!await _locker.PerformActionWithLockAsync(
868+
fullPath,
869+
TimeSpan.FromSeconds(_sitemapXmlSettings.SitemapBuildOperationDelay),
870+
async () => await GenerateAsync(fullPath, id)))
871+
{
872+
throw new InvalidOperationException();
873+
}
874+
834875
return new SitemapXmlModel { SitemapXmlPath = fullPath };
835876
}
836-
837-
//execute task with lock
838-
if (!await _locker.PerformActionWithLockAsync(
839-
fullPath,
840-
TimeSpan.FromSeconds(_sitemapXmlSettings.SitemapBuildOperationDelay),
841-
async () => await GenerateAsync(fullPath, id)))
877+
finally
842878
{
843-
throw new InvalidOperationException();
879+
_actionContextAccessor.ActionContext.HttpContext.Items.Remove(NopHttpDefaults.ForcedSitemapXmlLanguage);
844880
}
845-
846-
return new SitemapXmlModel { SitemapXmlPath = fullPath };
847881
}
848882

849883
/// <summary>
@@ -886,10 +920,7 @@ var name when name.Equals(nameof(ProductTag), StringComparison.InvariantCultureI
886920
var store = await _storeContext.GetCurrentStoreAsync();
887921

888922
var updatedOn = dateTimeUpdatedOn ?? DateTime.UtcNow;
889-
var languages = _localizationSettings.SeoFriendlyUrlsForLanguagesEnabled
890-
? (await _languageService.GetAllLanguagesAsync(storeId: store.Id))
891-
.Where(lang => !_sitemapXmlSettings.DisallowLanguages.Contains(lang.Id)).ToList()
892-
: null;
923+
var languages = await GetAllowedLanguagesAsync(store);
893924

894925
if (languages == null || languages.Count == 1)
895926
return new SitemapUrlModel(url, new List<string>(), updateFreq, updatedOn);

0 commit comments

Comments
 (0)