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

Fixed issue with Paths-integers being converted using local culture. #11180

Merged
merged 13 commits into from
Sep 24, 2021
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Umbraco.Core/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ static StringExtensions()
public static int[] GetIdsFromPathReversed(this string path)
{
var nodeIds = path.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.TryConvertTo<int>())
.Select(x => int.TryParse(x, NumberStyles.Integer, CultureInfo.InvariantCulture, out var output) ? Attempt<int>.Succeed(output) : Attempt<int>.Fail())
.Where(x => x.Success)
.Select(x => x.Result)
.Select(x=>x.Result)
.Reverse()
.ToArray();
return nodeIds;
Expand Down
4 changes: 4 additions & 0 deletions src/Umbraco.Core/Models/Mapping/UserMapDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,10 @@ private IEnumerable<EditorNavigation> CreateUserEditorNavigation()

private static int GetIntId(object id)
{
if (id is string strId && int.TryParse(strId, NumberStyles.Integer, CultureInfo.InvariantCulture, out var asInt))
{
return asInt;
}
var result = id.TryConvertTo<int>();
if (result.Success == false)
{
Expand Down
6 changes: 3 additions & 3 deletions src/Umbraco.Core/Models/UserExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -219,14 +219,14 @@ private static bool StartsWithPath(string test, string path)

private static string GetBinPath(UmbracoObjectTypes objectType)
{
var binPath = Constants.System.Root + ",";
var binPath = Constants.System.RootString + ",";
switch (objectType)
{
case UmbracoObjectTypes.Document:
binPath += Constants.System.RecycleBinContent;
binPath += Constants.System.RecycleBinContentString;
p-m-j marked this conversation as resolved.
Show resolved Hide resolved
break;
case UmbracoObjectTypes.Media:
binPath += Constants.System.RecycleBinMedia;
binPath += Constants.System.RecycleBinMediaString;
p-m-j marked this conversation as resolved.
Show resolved Hide resolved
break;
default:
throw new ArgumentOutOfRangeException(nameof(objectType));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,20 @@ public override object ConvertSourceToIntermediate(IPublishedElement owner, IPub
{
if (source == null) return null;


if(source is not string)
{
var attemptConvertInt = source.TryConvertTo<int>();
if (attemptConvertInt.Success)
return attemptConvertInt.Result;
}
//Don't attempt to convert to int for UDI
if(!(source is string) || source is string strSource && !string.IsNullOrWhiteSpace(strSource) && !strSource.StartsWith("umb"))
if( source is string strSource
&& !string.IsNullOrWhiteSpace(strSource)
&& !strSource.StartsWith("umb")
&& int.TryParse(strSource, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intValue))
{
var attemptConvertInt = source.TryConvertTo<int>();
if (attemptConvertInt.Success)
return attemptConvertInt.Result;
return intValue;
}

var attemptConvertUdi = source.TryConvertTo<Udi>();
Expand Down
4 changes: 2 additions & 2 deletions src/Umbraco.Core/Security/ContentPermissions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,11 +236,11 @@ public static bool HasPathAccess(string path, int[] startNodeIds, int recycleBin

// only users with root access have access to the recycle bin,
// if the above check didn't pass then access is denied
if (formattedPath.Contains(string.Concat(",", recycleBinId, ",")))
if (formattedPath.Contains(string.Concat(",", recycleBinId.ToString(CultureInfo.InvariantCulture), ",")))
return false;

// check for a start node in the path
return startNodeIds.Any(x => formattedPath.Contains(string.Concat(",", x, ",")));
return startNodeIds.Any(x => formattedPath.Contains(string.Concat(",", x.ToString(CultureInfo.InvariantCulture), ",")));
}

public static bool IsInBranchOfStartNode(string path, int[] startNodeIds, string[] startNodePaths, out bool hasPathAccess)
Expand Down
7 changes: 4 additions & 3 deletions src/Umbraco.Core/Services/UserServiceExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models.Membership;
Expand All @@ -12,9 +13,9 @@ public static class UserServiceExtensions
public static EntityPermission GetPermissions(this IUserService userService, IUser user, string path)
{
var ids = path.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.TryConvertTo<int>())
.Where(x => x.Success)
.Select(x => x.Result)
.Select(x => int.TryParse(x, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value) ? (int?)value : null)
bergmania marked this conversation as resolved.
Show resolved Hide resolved
.Where(x => x.HasValue)
.Select(x => x.Value)
.ToArray();
if (ids.Length == 0) throw new InvalidOperationException("The path: " + path + " could not be parsed into an array of integers or the path was empty");

Expand Down
86 changes: 0 additions & 86 deletions src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -382,91 +382,5 @@ private void AppendPath(StringBuilder sb, string path, bool includeThisNode)
sb.Append(path);
sb.Append("\\,*");
}

// TODO: When/Where is this used?

/// <summary>
/// Returns a collection of entities for media based on search results
/// </summary>
/// <param name="results"></param>
/// <returns></returns>
private IEnumerable<SearchResultEntity> MemberFromSearchResults(IEnumerable<ISearchResult> results)
{
//add additional data
foreach (var result in results)
{
var m = _umbracoMapper.Map<SearchResultEntity>(result);

//if no icon could be mapped, it will be set to document, so change it to picture
if (m.Icon == Constants.Icons.DefaultIcon)
{
m.Icon = Constants.Icons.Member;
}

if (result.Values.ContainsKey("email") && result.Values["email"] != null)
{
m.AdditionalData["Email"] = result.Values["email"];
}
if (result.Values.ContainsKey(UmbracoExamineFieldNames.NodeKeyFieldName) && result.Values[UmbracoExamineFieldNames.NodeKeyFieldName] != null)
{
if (Guid.TryParse(result.Values[UmbracoExamineFieldNames.NodeKeyFieldName], out var key))
{
m.Key = key;
}
}

yield return m;
}
}

// TODO: When/Where is this used?

/// <summary>
/// Returns a collection of entities for media based on search results
/// </summary>
/// <param name="results"></param>
/// <returns></returns>
private IEnumerable<SearchResultEntity> MediaFromSearchResults(IEnumerable<ISearchResult> results)
=> _umbracoMapper.Map<IEnumerable<SearchResultEntity>>(results);

// TODO: When/Where is this used?

/// <summary>
/// Returns a collection of entities for content based on search results
/// </summary>
/// <param name="results"></param>
/// <returns></returns>
private IEnumerable<SearchResultEntity> ContentFromSearchResults(IEnumerable<ISearchResult> results, string culture = null)
{
var defaultLang = _languageService.GetDefaultLanguageIsoCode();
foreach (var result in results)
{
var entity = _umbracoMapper.Map<SearchResultEntity>(result, context =>
{
if (culture != null)
{
context.SetCulture(culture);
}
}
);

var intId = entity.Id.TryConvertTo<int>();
if (intId.Success)
{
//if it varies by culture, return the default language URL
if (result.Values.TryGetValue(UmbracoExamineFieldNames.VariesByCultureFieldName, out var varies) && varies == "y")
{
entity.AdditionalData["Url"] = _publishedUrlProvider.GetUrl(intId.Result, culture: culture ?? defaultLang);
}
else
{
entity.AdditionalData["Url"] = _publishedUrlProvider.GetUrl(intId.Result);
}
}

yield return entity;
}
}

}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Examine;
using Umbraco.Cms.Core.Scoping;
Expand Down Expand Up @@ -30,7 +31,7 @@ public bool ValidatePath(string path, string category)
{
// we cannot return FAILED here because we need the value set to get into the indexer and then deal with it from there
// because we need to remove anything that doesn't pass by parent Id in the cases that umbraco data is moved to an illegal parent.
if (!path.Contains(string.Concat(",", ParentId.Value, ",")))
if (!path.Contains(string.Concat(",", ParentId.Value.ToString(CultureInfo.InvariantCulture), ",")))
return false;
}

Expand All @@ -39,7 +40,7 @@ public bool ValidatePath(string path, string category)

public bool ValidateRecycleBin(string path, string category)
{
var recycleBinId = category == IndexTypes.Content ? Constants.System.RecycleBinContent : Constants.System.RecycleBinMedia;
var recycleBinId = category == IndexTypes.Content ? Constants.System.RecycleBinContentString : Constants.System.RecycleBinMediaString;

//check for recycle bin
if (PublishedValuesOnly)
Expand Down
8 changes: 4 additions & 4 deletions src/Umbraco.Infrastructure/Search/UmbracoTreeSearcher.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Examine;
using Umbraco.Cms.Core.Mapping;
Expand Down Expand Up @@ -162,17 +163,16 @@ private IEnumerable<SearchResultEntity> ContentFromSearchResults(IEnumerable<ISe
}
);

var intId = entity.Id.TryConvertTo<int>();
if (intId.Success)
if (int.TryParse(entity.Id.ToString(),NumberStyles.Integer, CultureInfo.InvariantCulture, out var intId))
{
//if it varies by culture, return the default language URL
if (result.Values.TryGetValue(UmbracoExamineFieldNames.VariesByCultureFieldName, out var varies) && varies == "y")
{
entity.AdditionalData["Url"] = _publishedUrlProvider.GetUrl(intId.Result, culture: culture ?? defaultLang);
entity.AdditionalData["Url"] = _publishedUrlProvider.GetUrl(intId, culture: culture ?? defaultLang);
}
else
{
entity.AdditionalData["Url"] = _publishedUrlProvider.GetUrl(intId.Result);
entity.AdditionalData["Url"] = _publishedUrlProvider.GetUrl(intId);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Microsoft.Extensions.Logging;
using Umbraco.Cms.Core.Events;
Expand Down Expand Up @@ -946,11 +947,7 @@ public IEnumerable<EntityContainer> GetContainers(int[] containerIds)
public IEnumerable<EntityContainer> GetContainers(TItem item)
{
var ancestorIds = item.Path.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries)
.Select(x =>
{
var asInt = x.TryConvertTo<int>();
return asInt ? asInt.Result : int.MinValue;
})
.Select(x => int.TryParse(x, NumberStyles.Integer, CultureInfo.InvariantCulture, out var asInt) ? asInt : int.MinValue)
.Where(x => x != int.MinValue && x != item.Id)
.ToArray();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -568,11 +568,11 @@ private XElement SerializePropertyType(IPropertyType propertyType, IDataType def
private XElement SerializeContentBase(IContentBase contentBase, string urlValue, string nodeName, bool published)
{
var xml = new XElement(nodeName,
new XAttribute("id", contentBase.Id),
new XAttribute("id", contentBase.Id.ToInvariantString()),
new XAttribute("key", contentBase.Key),
new XAttribute("parentID", contentBase.Level > 1 ? contentBase.ParentId : -1),
new XAttribute("parentID", (contentBase.Level > 1 ? contentBase.ParentId : -1).ToInvariantString()),
new XAttribute("level", contentBase.Level),
new XAttribute("creatorID", contentBase.CreatorId),
new XAttribute("creatorID", contentBase.CreatorId.ToInvariantString()),
new XAttribute("sortOrder", contentBase.SortOrder),
new XAttribute("createDate", contentBase.CreateDate.ToString("s")),
new XAttribute("updateDate", contentBase.UpdateDate.ToString("s")),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
<IsPackable>true</IsPackable>
</PropertyGroup>

<ItemGroup Condition="'$(OS)' == 'Windows_NT'">
<PackageReference Include="Microsoft.ICU.ICU4C.Runtime" Version="68.2.0.6" />
<RuntimeHostConfigurationOption Include="System.Globalization.AppLocalIcu" Value="68.2" />
</ItemGroup>

<PropertyGroup Condition=" '$(OS)' == 'Windows_NT' ">
<DefineConstants>IS_WINDOWS</DefineConstants>
</PropertyGroup>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -49,49 +49,43 @@ public void ConvertToBoolTest()


[Test]
[TestCase("en-US")]
[TestCase(null)]
[TestCase("da-DK")]
[TestCase("tr-TR")]
public void ConvertToIntegerTest(string culture)
[TestCase("en-US", -1, ExpectedResult = -1)]
[TestCase("en-US", "-1", ExpectedResult = -1)]
[TestCase("en-US", "100", ExpectedResult = 100)]
[TestCase("en-US", "100.000", ExpectedResult = 100)]
[TestCase("en-US", "100,000", ExpectedResult = 100)]
[TestCase("en-US", "100.001", ExpectedResult = 100)]
[TestCase("en-US", 100, ExpectedResult = 100)]
[TestCase("en-US", 100.000, ExpectedResult = 100)]
[TestCase("en-US", 100.001, ExpectedResult = 100)]
[TestCase("sv-SE", -1, ExpectedResult = -1)]
[TestCase("sv-SE", "−1", ExpectedResult = -1)] // Note '−' vs '-'
[TestCase("sv-SE", "100", ExpectedResult = 100)]
[TestCase("sv-SE", "100.000", ExpectedResult = 100)]
[TestCase("sv-SE", "100,000", ExpectedResult = 100)]
[TestCase("sv-SE", "100.001", ExpectedResult = 100)]
[TestCase("sv-SE", 100, ExpectedResult = 100)]
[TestCase("sv-SE", 100.000, ExpectedResult = 100)]
[TestCase("sv-SE", 100.001, ExpectedResult = 100)]
[TestCase("da-DK", "-1", ExpectedResult = -1)]
[TestCase("da-DK", -1, ExpectedResult = -1)]
[TestCase("da-DK", "100", ExpectedResult = 100)]
[TestCase("da-DK", "100.000", ExpectedResult = 100)]
[TestCase("da-DK", "100,000", ExpectedResult = 100)]
[TestCase("da-DK", "100.001", ExpectedResult = 100)]
[TestCase("da-DK", 100, ExpectedResult = 100)]
[TestCase("da-DK", 100.000, ExpectedResult = 100)]
[TestCase("da-DK", 100.001, ExpectedResult = 100)]
public int ConvertToIntegerTest(string culture, object input)
{
if (culture is not null)
{
CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo(culture);
}
var conv = "-1".TryConvertTo<int>();
var conv = input.TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(-1, conv.Result);

conv = "100".TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);

conv = "100.000".TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);

conv = "100,000".TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);

// oops
conv = "100.001".TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);

conv = 100m.TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);

conv = 100.000m.TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);

// oops
conv = 100.001m.TryConvertTo<int>();
Assert.IsTrue(conv);
Assert.AreEqual(100, conv.Result);
return conv.Result;
}

[Test]
Expand Down
Loading