Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OCC-97: Country or region selector wrong spelling #208

Merged
merged 12 commits into from Oct 17, 2022
Expand Up @@ -6,9 +6,7 @@ public class AddressFormatterProvider : IAddressFormatterProvider
{
public string Format(Address address)
{
var region = address?.Region;
if (region != null &&
Regions.RegionCodes.TryGetValue(region, out var regionCode) &&
if (address?.Region is { } regionCode &&
KnownAddressFormatters.Formatters.TryGetValue(regionCode, out var formatter))
{
return formatter.Format(address);
Expand Down
10 changes: 10 additions & 0 deletions src/Libraries/OrchardCore.Commerce.AddressDataType/Region.cs
@@ -0,0 +1,10 @@
using System.Globalization;

namespace OrchardCore.Commerce.AddressDataType;

public record Region(string EnglishName, string TwoLetterISORegionName, string DisplayName)
{
public Region(RegionInfo info)
: this(info.EnglishName, info.TwoLetterISORegionName, info.EnglishName)
{ }
}
22 changes: 10 additions & 12 deletions src/Libraries/OrchardCore.Commerce.AddressDataType/Regions.cs
Expand Up @@ -10,27 +10,25 @@ public static class Regions
/// <summary>
/// Gets the list of regions.
/// </summary>
public static IList<RegionInfo> All { get; } =
[Obsolete("Use service! This is a temporary attribute.")]
public static IList<Region> All { get; } =
CultureInfo
.GetCultures(CultureTypes.SpecificCultures)
.Where(culture => !culture.Equals(CultureInfo.InvariantCulture) && !culture.IsNeutralCulture)
DemeSzabolcs marked this conversation as resolved.
Show resolved Hide resolved
.Select(culture =>
{
// This sometimes throws "CultureNotFoundException: Culture is not supported." exception on Linux only.
try { return new RegionInfo(culture.LCID); }
catch { return null; }
catch (CultureNotFoundException) { return null; }
})
.Where(region => region?.TwoLetterISORegionName.Length == 2) // Filter out world and other 3-digit regions
.Where(region =>
region != null &&
region.TwoLetterISORegionName.Length == 2 && // Filter out world and other 3-digit regions.
!string.IsNullOrEmpty(region.EnglishName))
.Distinct()
.Select(region => new Region(region))
.ToList();

/// <summary>
/// Gets region names mapped to two-letter ISO region codes.
/// </summary>
public static IDictionary<string, string> RegionCodes { get; } =
All.ToDictionary(
region => region.DisplayName,
region => region.TwoLetterISORegionName,
StringComparer.OrdinalIgnoreCase);

/// <summary>
/// Gets two-letter regions codes mapped to region names.
/// </summary>
Expand Down
@@ -1,3 +1,4 @@
using OrchardCore.Commerce.AddressDataType;
using System.Collections.Generic;
using System.Globalization;
using System.Threading.Tasks;
Expand All @@ -9,9 +10,14 @@ namespace OrchardCore.Commerce.Abstractions;
/// </summary>
public interface IRegionService
{
/// <summary>
/// Gets all regions and applies localization to their <see cref="Region.DisplayName"/> properties.
/// </summary>
IEnumerable<Region> GetAllRegions();

/// <summary>
/// Gets the available regions from the site settings.
/// </summary>
/// <returns>A collection of <see cref="RegionInfo"/>.</returns>
Task<IEnumerable<RegionInfo>> GetAvailableRegionsAsync();
Task<IEnumerable<Region>> GetAvailableRegionsAsync();
}
@@ -1,9 +1,7 @@
using Dapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using OrchardCore.Commerce.AddressDataType;
using OrchardCore.Commerce.Abstractions;
using OrchardCore.Commerce.Extensions;
using OrchardCore.Commerce.Models;
using OrchardCore.Commerce.ViewModels;
Expand All @@ -25,19 +23,20 @@ public class RegionSettingsDisplayDriver : SectionDisplayDriver<ISite, RegionSet
private readonly ShellSettings _shellSettings;
private readonly IHttpContextAccessor _hca;
private readonly IAuthorizationService _authorizationService;
private readonly IRegionService _regionService;

public RegionSettingsDisplayDriver(
IShellHost shellHost,
ShellSettings shellSettings,
IHttpContextAccessor hca,
IAuthorizationService authorizationService,
IDataProtectionProvider dataProtectionProvider,
ILogger<RegionSettingsDisplayDriver> logger)
IRegionService regionService)
{
_shellHost = shellHost;
_shellSettings = shellSettings;
_hca = hca;
_authorizationService = authorizationService;
_regionService = regionService;
}

public override async Task<IDisplayResult> EditAsync(RegionSettings section, BuildEditorContext context)
Expand All @@ -49,8 +48,9 @@ public override async Task<IDisplayResult> EditAsync(RegionSettings section, Bui
return Initialize<RegionSettingsViewModel>("RegionSettings_Edit", model =>
{
model.AllowedRegions = section.AllowedRegions;

model.Regions = Regions.All.AsEnumerable().CreateSelectListOptions();
model.Regions = _regionService
.GetAllRegions()
.CreateSelectListOptions();
})
.Location("Content")
.OnGroup(GroupId);
Expand All @@ -72,8 +72,9 @@ public override async Task<IDisplayResult> UpdateAsync(RegionSettings section, B
if (await context.Updater.TryUpdateModelAsync(model, Prefix))
{
var allowedRegions = model.AllowedRegions.AsList();

var allRegionTwoLetterIsoRegionNames = Regions.All.Select(region => region.TwoLetterISORegionName);
var allRegionTwoLetterIsoRegionNames = _regionService
.GetAllRegions()
.Select(region => region.TwoLetterISORegionName);

section.AllowedRegions = allowedRegions?.Any() == true
? allRegionTwoLetterIsoRegionNames
Expand Down
10 changes: 3 additions & 7 deletions src/Modules/OrchardCore.Commerce/Extensions/RegionExtensions.cs
@@ -1,18 +1,14 @@
using Microsoft.AspNetCore.Mvc.Rendering;
using OrchardCore.Commerce.AddressDataType;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

namespace OrchardCore.Commerce.Extensions;

public static class RegionExtensions
{
public static IEnumerable<SelectListItem> CreateSelectListOptions(this IEnumerable<RegionInfo> regionInfos) =>
regionInfos.OrderBy(region => region.DisplayName).Select(region => new SelectListItem(
region.DisplayName,
public static IEnumerable<SelectListItem> CreateSelectListOptions(this IEnumerable<Region> regionInfos) =>
regionInfos.OrderBy(region => region.EnglishName).Select(region => new SelectListItem(
DemeSzabolcs marked this conversation as resolved.
Show resolved Hide resolved
region.EnglishName,
region.TwoLetterISORegionName));

public static IEnumerable<RegionInfo> GetRegionInfosFromTwoLetterRegionIsos(this IEnumerable<string> twoLetterRegionISOs) =>
Regions.All.Where(region => twoLetterRegionISOs.Contains(region.TwoLetterISORegionName));
}
30 changes: 22 additions & 8 deletions src/Modules/OrchardCore.Commerce/Services/RegionService.cs
@@ -1,25 +1,39 @@
using Microsoft.Extensions.Localization;
using OrchardCore.Commerce.Abstractions;
using OrchardCore.Commerce.AddressDataType;
using OrchardCore.Commerce.Extensions;
using OrchardCore.Commerce.Models;
using OrchardCore.Entities;
using OrchardCore.Settings;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;

namespace OrchardCore.Commerce.Services;
public class RegionService : IRegionService
{
private readonly ISiteService _siteService;
private readonly IStringLocalizer<RegionService> T;

public RegionService(ISiteService siteService) =>
public RegionService(ISiteService siteService, IStringLocalizer<RegionService> stringLocalizer)
{
_siteService = siteService;
T = stringLocalizer;
}

public async Task<IEnumerable<RegionInfo>> GetAvailableRegionsAsync() =>
(await _siteService.GetSiteSettingsAsync()).As<RegionSettings>()?.AllowedRegions is { } regions &&
regions.Any()
? regions.GetRegionInfosFromTwoLetterRegionIsos()
: Regions.All;
public IEnumerable<Region> GetAllRegions() =>
#pragma warning disable CS0618
Regions.All.Select(region => region with { DisplayName = T[region.EnglishName] });
#pragma warning restore CS0618

public async Task<IEnumerable<Region>> GetAvailableRegionsAsync()
{
var settings = await _siteService.GetSiteSettingsAsync();
var allowedRegionCodes = (settings.As<RegionSettings>()?.AllowedRegions ?? Enumerable.Empty<string>()).AsList();

var allRegions = GetAllRegions();

if (!allowedRegionCodes.Any()) return allRegions;

return allRegions.Where(region => allowedRegionCodes.Contains(region.TwoLetterISORegionName));
}
}
4 changes: 1 addition & 3 deletions src/Modules/OrchardCore.Commerce/Views/Checkout.cshtml
@@ -1,6 +1,4 @@
@using Newtonsoft.Json
@using OrchardCore.Commerce.Settings
@model OrchardCore.Commerce.ViewModels.CheckoutViewModel
@model CheckoutViewModel

<mvc-title text="@T["Checkout"]" />
@{
Expand Down
Expand Up @@ -30,7 +30,7 @@ public PersistenceRegionSettingsTests(ITestOutputHelper testOutputHelper)
.GetAll(By.XPath("id('OrderPart_BillingAddress_Address_Region')/option"))
.Select(selectListOption => selectListOption.Text)
.ToArray()
.ShouldBe(new[] { "Argentina", "Luxemburg", "Magyarország" });
.ShouldBe(new[] { "Argentina", "Hungary", "Luxembourg" });
},
browser);
}